目錄html
示例代碼託管在:http://www.github.com/dashnowords/blogs前端
博客園地址:《大史住在大前端》原創博文目錄vue
華爲雲社區地址:【你要的前端打怪升級指南】node
前端工程出包後實現簡易的自動化部署。linux
網站的建設可使用任何本身熟悉的框架,三大框架都有本身的官方Cli
工具,從代碼編寫到生成可用於生產環境部署的包基本都有自動化命令,各個打包工具也在零配置的追求上作了不少工做。本篇中從獲得一個生產環境的包之後開始,對站點部署的相關知識進行一些介紹。git
首先你須要一個Web服務器,常見的有:github
Nginx
Tomcat
Apache
或相關集成環境
XAMMP
【Apache
+MySQL
+PHP
+PERL
】LAMP
【Linux
+Apache
+MySQL
+PHP
】nodejs
或相關框架+守護進程
Express
Koa2
以上任何一種在服務器上運行起來後均可以擔任Web服務器的角色,只是具有的擴展功能和應用場景有區別,Nginx
基本上是正式環境部署的首選方案。常見的基本部署方案以下:vue-cli
使用訪問,可直接訪問對應端口的服務,部署方式相對簡單:shell
使用域名訪問時,一般會使用A記錄進行解析,它只能映射到80端口(https時映射到443),這時就須要使用反向代理將80
端口的請求分發到本地不一樣的內部端口來訪問對應服務:express
本例中使用域名+IP
的方式進行部署。
以Express
爲例,步驟以下:
yarn global add express-generator
或npm install express-generator -g
全局安裝腳手架express mydemo --ejs
生成一個使用ejs
做爲模板渲染引擎的express
工程cd mydemo && yarn
或cd mydemo && npm install
安裝依賴/bin/www
文件中修改端口號爲指望的端口號(自動生成的是80端口),例如3001
/public
目錄中npm start
後,在瀏覽器中http://localhost:3001
就能夠訪問到網站了FlashFxp
或FileZilla Client
等)鏈接到部署機器,將mydemo
目錄壓縮爲zip
包後上傳到服務器指定目錄。Xshell
或MobaXter
)登陸遠程機器,假設爲linux
系統,輸入unzip mydemo.zip
解壓壓縮包,而後cd mydemo
進入服務端工程,輸入npm start
便可在服務器上開啓Web服務,經過ip地址:3001
就能夠訪問到網站。SSH
工具斷開鏈接,就會發現express
應用沒法繼續訪問了,因此還須要一個守護進程來維持應用的啓動狀態,在服務端經過npm install pm2 -g
來安裝nodejs
應用的部署管理模塊,它能夠實現多應用管理、Hook更新、自動重啓等等許多經常使用功能,詳細信息能夠訪問 【PM2官方網站】。pm2 start ./bin/www
便可之後臺模式運行應用。瞭解了手動部署的過程後,就能夠經過自動化腳原本實現後續的更新和部署。nodejs
工程的自動化是依賴於package.json
文件中的scripts
配置項來實現的,例如使用vue-cli
搭建的工程中就會帶有:
{ ... "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" }, ... }
在項目根目錄下打開命令行,輸入npm run [script-key]
或者yarn [script-key]
([script-key]
指上面示例中的serve,build,lint這些鍵名),就會執行對應的scripts[key]
對應的命令。咱們先添加一條用於自動部署的腳本指令:
{ ... "scripts": { "build": "vue-cli-service build", "deploy" "node ./scripts/deploy/deploy.js" }, ... }
當輸入npm run deploy
或yarn deploy
時,實際上就至關於用node去執行./scripts/deploy/deploy.js
這個腳本,其中就編寫了自動化發佈的指令。scripts
還提供了生命週期鉤子,好比你對接的是一個測試環境,但願每次build後自動發佈,就可使用post鉤子來實現:
{ ... "scripts": { "build": "vue-cli-service build", "postbuild":"npm run deploy", "deploy" "node ./scripts/deploy/deploy.js" }, ... }
這樣每次build執行完畢後,就會自動執行npm run deploy
,也就是運行發佈的腳本。
自動化發佈腳本須要完成這樣幾個任務:
dist
壓縮爲zip
包zip
包發上去shell
腳原本完成剩餘的工做涉及的幾個模塊包括實現SSH鏈接的node-ssh
模塊(底層是ssh2
模塊,這個模塊是一個Promise封裝),用於製做zip
壓縮包的archiver
模塊。node-ssh
提供了上傳本地目錄的方法,但實際使用過程當中發現並不穩定,從告警信息來看是node-stream
模塊在傳送時將不一樣格式的文件轉換爲流時可能會出現異常,實測大約有一半機率觸發,嘗試修改了一些配置參數並未解決,因此採用archiver
模塊先壓縮爲單個文件後再進行上傳。
參考代碼以下:
const path = require('path'); const archiver =require('archiver'); const fs = require('fs'); const node_ssh = require('node-ssh'); const ssh = new node_ssh(); const srcPath = path.resolve(__dirname,'../../dist'); const configs = require('./config'); console.log('開始壓縮dist目錄...'); startZip(); //壓縮dist目錄爲public.zip function startZip() { var archive = archiver('zip', { zlib: { level: 5 } //遞歸掃描最多5層 }).on('error', function(err) { throw err;//壓縮過程當中若是有錯誤則拋出 }); var output = fs.createWriteStream(__dirname + '/public.zip') .on('close', function(err) { /*壓縮結束時會觸發close事件,而後才能開始上傳, 不然會上傳一個內容不全且沒法使用的zip包*/ if (err) { console.log('關閉archiver異常:',err); return; } console.log('已生成zip包'); console.log('開始上傳public.zip至遠程機器...'); uploadFile(); }); archive.pipe(output);//典型的node流用法 archive.directory(srcPath,'/public');//將srcPach路徑對應的內容添加到zip包中/public路徑 archive.finalize(); } //將dist目錄上傳至正式環境 function uploadFile() { ssh.connect({ //configs存放的是鏈接遠程機器的信息 host: configs.host, username: configs.user, password: configs.password, port:22 //SSH鏈接默認在22端口 }).then(function () { //上傳網站的發佈包至configs中配置的遠程服務器的指定地址 ssh.putFile(__dirname + '/public.zip', configs.path).then(function(status) { console.log('上傳文件成功'); console.log('開始執行遠端腳本'); startRemoteShell();//上傳成功後觸發遠端腳本 }).catch(err=>{ console.log('文件傳輸異常:',err); process.exit(0); }); }).catch(err=>{ console.log('ssh鏈接失敗:',err); process.exit(0); }); } //執行遠端部署腳本 function startRemoteShell() { //在服務器上cwd配置的路徑下執行sh deploy.sh腳原本實現發佈 ssh.execCommand('sh deploy.sh', { cwd:'/usr/bin/XXXXX' }).then(function(result) { console.log('遠程STDOUT輸出: ' + result.stdout) console.log('遠程STDERR輸出: ' + result.stderr) if (!result.stderr){ console.log('發佈成功!'); process.exit(0); } }); }
當發佈包上傳至遠程服務器後,剩餘的工做在遠端來完成就能夠了,你只須要將後續的工做寫進shell
腳本並放在對應的目錄裏就能夠了,本例中deploy.sh
放在了服務端項目目錄/mydemo
中。示例以下(因爲是自用系統,不考慮灰度發佈等,直接暴力刪除靜態目錄public,而後替換爲新的包):
#!/bin/bash cd /usr1/AAA/mydemo #刪除原靜態資源目錄 rm -rf public cd /usr1/AAA #解壓新的包 unzip public.zip #將解壓出的public目錄移動到服務端程序目錄BBB中 mv public ./mydemo
提示:
若是腳本文件是在windows下編寫的,請注意將編輯器中的回車換行改成
LF
,windows下一般默認是CRLF
,這可能會致使腳本在linux機器上沒法正常執行。
至此,一個簡易的自動化部署就作完了。你只須要在本地輸入npm run deploy
,後續的工做就會自動執行。
本篇只是一個簡易的自動化部署流程,因爲部署環境沒有外網因此暫時沒法藉助通用的自動化流水線實現全自動的DevOps
流程。PM2
實際上還有很是多實用的功能,能夠管理多個不一樣的應用實例,以集羣模式運行實例,或者預設發佈流程,能夠直接響應Web Hook
並對接指定的代碼倉,在根目錄下創建ecosystem.config.js
配置文件就能夠添加更多配置來指定pm2
的表現,感興趣的讀者能夠研究一下。