背景說明
前端專案開發完成,需要部署在第三方伺服器。由於第三方伺服器是脫離公網的環境,所有的前端服務和所有的依賴都需要在離線環境中部署。記錄下解決方案,希望可以幫助到有類似需求的旁友。會涉及到基礎的Linux知識,對Linux不熟悉的童鞋可以先看看資料入門。
基本解決思路
- 把Node環境下載下來作為離線包備用。
- 本地構建前端程式碼,將所有前端構建產出以及node_modules依賴,node離線包全部打包成一個
output.tar.gz
。 - 上傳到伺服器。
- 解壓,將node環境安裝到伺服器,執行。
- 要是都是指令碼控制就更完美了~
最終產出的output目錄內容
output
bin // pm2 控制指令碼
config // 配置檔案
dist // webpack 產出
node_modules // 專案所有依賴,當然這裡面的內容可以只保留伺服器需要的依賴,根據需求定
server // 代理伺服器,我想你的專案應該會用到
thirdparty // 執行環境目錄,這裡是node-v8.x
install.sh // 自動安裝node環境指令碼
複製程式碼
離線包製作步驟
這裡關於前端的webpack構建就不贅述了,直接看關鍵點:
-
準備node離線包。直接在Node官網下載圖示版本(這裡要根據需要下載Node的具體版本,我的專案用的是
Node-LTS
),這裡下載的是linux通用的可執行檔案,直接解壓就可執行,方便後續指令碼化操作。- 有了離線包,在上傳到伺服器之後肯定還要手動安裝啊,這個過程很機械,機械的東西就交給機器幹吧。準備一個node環境安裝指令碼
output/install.sh
,讓它來完成這些事情。由於下載的是可執行檔案,解壓後就相當於直接把node安裝到了output/thirdparty
目錄下,需要做的就是把node暴露給作業系統,讓它擁有node執行環境。常用的有兩種方法:- 新增全域性環境變數
- 新增軟連結
- 指令碼中有個問題,希望有大神能幫忙解答下,我把node環境變數新增到
/etc/profile
後,使用soure
呼叫了它,但是沒有生效,所以採用了軟連結的方法將node暴露在系統中。 - 指令碼是在
CentOS7
中執行測試,開發時需要安裝虛擬機器模擬真實Linux環境,如果是mac,可能不能正常執行。具體安裝步驟,可自行百度。
#!/bin/bash # install nodejs base_dir=$(dirname $(readlink -f $0)) node_dir="node-v8.12.0-linux-x64" # 第一步:將node解壓到thirdparty,也就是當前資料夾 if [ ! -d ${base_dir}/thirdparty/${node_dir} ]; then echo -e "\033[33m 正在解壓Node \033[0m" tar -xvf ${base_dir}/thirdparty/node-env.tar.xz -C ${base_dir}/thirdparty echo -e "\033[32m Node 解壓完成 \033[0m" else echo -e "\033[32m Node 已解壓完成 \033[0m" fi # 賦予執行許可權 chmod u+x ${base_dir}/thirdparty/${node_dir}/bin/* #######問題######## # 新增環境變數 # export PATH=$PATH:${base_dir}/thirdparty/${node_dir}/bin # if [[ ! $PATH =~ "${base_dir}/thirdparty/${node_dir}/bin" ]] # then # echo "export PATH=$PATH:${base_dir}/thirdparty/${node_dir}/bin" >> /etc/profile # echo "Node 環境變數已新增" # fi # echo $PATH # source /etc/profile # echo $PATH #######問題######## # 軟連結 ln -sf ${base_dir}/thirdparty/${node_dir}/bin/node /usr/bin/node if [ -f /usr/bin/node ]; then echo -e "\033[32m Node 軟連結已新增 \033[0m" else echo -e "\033[31m Error: Node 軟連結新增失敗,確認是否以ROOT身份執行 \033[0m" exit fi # 聯動pm2控制 if [ -f ./bin/control ]; then echo -e "\033[33m 啟動Server... \033[0m" ./bin/control start echo -e "\033[32m Server啟動成功,可使用./bin/control維護當前服務 \033[0m" ./bin/control help fi 複製程式碼
- 有了離線包,在上傳到伺服器之後肯定還要手動安裝啊,這個過程很機械,機械的東西就交給機器幹吧。準備一個node環境安裝指令碼
-
在前端構建完成後把node壓縮包拷貝至output中。貼上我的構建指令碼
build.sh
(專案根目錄中),讓指令碼去執行npm install balabala... 可以參考下:#!/bin/sh echo $(date +"%Y-%m-%d %H:%M:%S") 'build begin' rm -rf node_modules echo $(date +"%Y-%m-%d %H:%M:%S") 'rm -rf node_modules end' npm install echo $(date +"%Y-%m-%d %H:%M:%S") 'install end' mkdir output echo $(date +"%Y-%m-%d %H:%M:%S") 'mkdir output end' npm run build echo $(date +"%Y-%m-%d %H:%M:%S") 'npm build end' # 將所有需要的檔案通通塞到output下 cp -r build config node_modules server dist yunyi/bin thirdparty install output echo $(date +"%Y-%m-%d %H:%M:%S") 'move files end' # 給指令碼新增執行許可權 chmod +x output/bin/control chmod +x output/install echo $(date +"%Y-%m-%d %H:%M:%S") 'build end' # GZ壓縮output tar -czvf output.tar.gz output 複製程式碼
-
如果順利的話,執行完以上指令碼,你會在專案根目錄中發現一個
output.tar.gz
的檔案。至此,前端的離線部署包就完成了。
「真實」環境操作
- 這裡採用已經安裝好的虛擬環境
CentOS7
, 有了虛擬環境,再把離線包複製到虛擬環境中,tar
解壓之... - 進入解壓出來的output中,你會看到
install
。 - 執行
install
指令碼安裝node,這裡注意要以root許可權執行,不然會報錯。如果終端中顯示Node 軟連結已新增
就說明node已經安裝完成了。 - 啟動你的server指令碼,我把維護server的指令碼(pm2操作)都放在了
bin/control
。install
指令碼執行完畢後會呼叫這個檔案的start
方法,這裡根據需求自行修改吧,執行如圖: - pm2控制指令碼
#!/bin/sh
cd "$(dirname $0)"/.. || exit 1
PROC_NAME='proxy-server'
help(){
echo "${0} <start|stop|restart|status|monit|list|delete>"
exit 1
}
status(){
status=$(node_modules/pm2/bin/pm2 show $PROC_NAME | grep status | awk '{print $4}')
echo $status
if [ X"$status" == X"online" ]; then
return 0
else
return 1
fi
}
start(){
node_modules/pm2/bin/pm2 set pm2-logrotate:max_size 100M
node_modules/pm2/bin/pm2 set pm2-logrotate:retain 15
node_modules/pm2/bin/pm2 start ./server/app.js --name $PROC_NAME -l "../log/nf1-server"
}
list(){
node_modules/pm2/bin/pm2 list $PROC_NAME
}
restart(){
node_modules/pm2/bin/pm2 restart $PROC_NAME
}
monit(){
node_modules/pm2/bin/pm2 monit $PROC_NAME
}
stop(){
node_modules/pm2/bin/pm2 stop $PROC_NAME
}
delete(){
node_modules/pm2/bin/pm2 delete $PROC_NAME
}
case "${1}" in
monit)
monit
;;
list)
list
;;
start)
start
;;
stop)
stop
;;
delete)
delete
;;
status|health|checkhealth|st)
status
;;
restart)
restart
;;
*)
help
;;
esac
複製程式碼