作為一個前端開發人員如果你只會寫一些業務代碼,從程序員的角度來考慮已經可以了。但是從架構的角度來考慮那遠遠不夠;
在此記錄下成長中的經歷:
想要達成的目的:運行一個腳本實現代碼的打包,上傳至服務器並部署到服務器中;
服務端:需要安裝pm2、nodejs;
在本地根目錄下創建一個腳本文件名稱自編自便;
1.下載需要依賴的包
npm i compressing ssh2 -S //compressing 的作用是用來壓縮文件的 //ssh2 的作用是用來連接服務器並執行操作的
2.創建操作的文件在根目錄
2.1導入node的核心模塊child_process
const {exec} = require('child_process')
2.2
const compressing = require('compressing')
2.3
const Client = require('ssh2').Client;
2.4創建一個對象里面是服務器連接的屬性
const server = { host : '遠程服務器的ip地址', prot : 22, //默認的不用該如果沒有修改過的話 username : '登陸遠程服務器的用戶名', password : '登陸的用戶名密碼' }
2.5創建一個ssh2的對象
const connect = new Client()
2.6在執行整個文件的時候讓node創建一個子線程
/*第一個參數是要運行的命令,第二個參數是可選的如果有興趣可以查看node官網的child_process.exec了解,第三個參數是是回調方法 在回調方法中有三個形參 error stdout stderr 如果成功 error 將會是null else error將會是Error實例 stdout和stderr參數將會包含子進程stdout和stderr輸出 */ const bat = exec('npm run build',(err,stdout,stderr)=>{ if (err) return console.log(`exec error: ${err}`); console.log("打包成功"); //啟動壓縮方法 compress(); })
2.7在執行完打包子線程后就對打包好的文件進行壓縮
function compress () { console.log('*******壓縮中*******'); //使用導入的compressing插件壓縮我們需要的文件 //第一個參數是要壓縮的文件夾,第二個參數是壓縮過后的壓縮包名稱 compressing.zip.compressDir('dist/','dist.zip').then(()=>{ console.log('*****壓縮成功*****'); // 成功之后就調用連接服務器的方法 conn(); }) }
2.8創建一個連接服務器的方法等壓縮成功之后就調用
function conn () { console.log('*****連接服務器******'); //使用前面定義好的ssh2對象 //ready 表示身份驗證成功 //error 表示發生錯誤 //end 表示斷開連接 //close 表示連接以關閉,如果這離是由於錯誤,hadError則設置為true connect.on('ready',()=>{ //在驗證成功之后對文件進行上傳操作 upload() }).on('error',(err)=>{ console.error(err) console.log('*****連接出錯*****') }).on('end',()=>{ console.log('*****連接關閉*****') }).on('close',(err)=>{ if (err) return console.log('*****連接出錯*****') }).connect(server) //connect方法使用server里面的參數連接到服務器參數詳情可查看ssh2-npm官網 }
2.9當ssh2驗證完成之后就調用上傳文件的方法
function upload () { console.log('******開始上傳******'); //開啟一個sftp會話參數是個回調方法 回調方法有兩個參數一個err實例,一個sftp實例 connect.sftp((err,sftp)=>{ if (err) throw err; //sftp的上傳操作第一個參數是本地需要上傳的文件路徑,第二個參數是要將本地的文件上傳到服務器的那個目錄下 sftp.fastPut('壓縮好的文件名稱','上傳到服務器的目錄',(err,res)=>{ if (err) { console.log('****上傳失敗*****'); console.error(err); //如果發生錯誤就調用end方法斷開連接 connect.end(); return; } //如果上傳成功就調用解壓文件的方法 unzipShell() }) }) }
2.10當文件上傳成功之后就調用解壓方法
function unzipShell() { //在服務器上啟動一個交互shell會話第一個參數是可選的,第二個參數是回調方法第一個是error實例第二個是shell會話流 connect.shell((err,stream)=>{ console.log('******解壓中******'); if (err) throw err; let buf = ""; //當會話檢測到輸出的時候嗲用close方法 stream.on('close',err =>{ //關閉連接 connect.end(); //如果失敗就打印失敗如果成功就答應成功 if (err) return console.error(err); console.info('****** SUCCESS!! *******'); }).on('data',data=>{ //data是從stream.data事件接受的字符串塊 buf += data; console.log(buf) }) //當解壓完成后在終端中輸入命令 //(以下命令只是示范具體操作看你的項目) //1.到上傳的目錄下取並且解壓上傳的文件 //2.cd 到解壓后的文件夾里面 將文件夾里面的所有東西復制到上一層 //3.到上一層目錄中刪除掉壓縮文件和解壓過后的文件夾 //4.cd 到最上層 並且使用pm2托管node服務 stream.write('cd 上傳的文件夾路徑 && unzip 壓縮的文件名稱 \nnext\n'); stream.write('cd 解壓后的文件夾下面 && /bin/cp -r -f * ../ \nnext\n'); stream.write('cd ../ && rm -r -f dist && rm -r -f 壓縮的文件名稱 \nnext\n'); stream.write('cd ../ && pm2 start nodemon server.js \nexit\n'); //server.js就是你需要啟動的文件 }) }
3.在服務端的項目根目錄中增加server.js文件我使用的是node服務托管文件
//導入node模塊express const express = require("express"); //創建一個服務 const app = express(); //將靜態文件托管到本地服務中 文件名稱不一定是dist app.use(express.static("./dist")); //啟動一個服務在3000端口中 app.listen(3000,(err)=>{ if (err) return err; console.log('server running at http://127.0.0.1:3000'); })
完成的代碼
server.js是單獨的需要手動創建和下面代碼不關聯
const { exec } = require("child_process"); const compressing = require("compressing"); const Client = require("ssh2").Client; const server = { host: '服務器ip', port: 22, username: '用戶名', password: '密碼' } const connect = new Client(); function conn() { console.log('*******連接服務器***********'); connect.on('ready', () => { upload(); }).on('error', (err) => { console.error(err); console.log('*****連接出錯******') }).on('end', () => { console.log('*******連接關閉********') }).on('close', (err) => { if (err) throw err; }).connect(server); } function upload() { console.log('******開始上傳********'); connect.sftp((err, sftp) => { if (err) throw err; sftp.fastPut('./dist.zip', '/home/yunwo/dist/dist.zip', (err, res) => { if (err) { console.error(err); console.log("*******上傳失敗******"); connect.end(); return; } unzipShell() }) }) } function unzipShell() { connect.shell((err, stream) => { console.log('*******解壓中*******'); if (err) throw err; let buf = ""; stream.on('close', err => { connect.end(); if (err) return console.error(err); console.info('******** success!! *********'); }).on('data', data => { buf += data; console.log(buf); }) stream.write('cd /home/yunwo/dist && unzip dist.zip \nnext\n'); stream.write('cd dist && /bin/cp -r -f * ../ \nnext\n'); stream.write('cd .. && rm -r -f dist && rm -r -f dist.zip \nnext\n'); stream.write('cd .. && pm2 start nodemon yunwoserver.js \nexit\n'); }) } function compress() { console.log('******壓縮中********'); compressing.zip.compressDir('dist/', 'dist.zip').then(() => { console.log('******壓縮成功******'); conn(); }) } console.log('*******打包中*******'); const bat = exec('npm run build', (err, stdout, stderr) => { if (err) return console.error(`exec error : ${err}`); console.log('********打包成功**********'); compress(); })