不說廢話,直接上貨。node
webpack
打包後自動部署插件:webpack-auto-upload-j
webpack
插件項目地址:https://github.com/jiangji1/w...git
在項目中安裝該模塊github
npm i webpack-auto-upload-j --save-dev
webpack導入插件並配置web
const WebpackAutoUploadJ = require('webpack-auto-upload-j') { plugins: [ new WebpackAutouploadJ({ path: path.resolve(__dirname, '../serviceConf.json'),// 服務器配置文件路徑 key: 'web' }), // 服務器配置文件對象key值 ] }
// serviceConf.json配置文件,根目錄下配置 { "web": { // 測試環境服務器配置 "build_upload_test": { "host": "xxx.xxx.xxx.xxx", "port": 22, "user": "xxx",// 服務器用戶名 "password": "xxxx",// 服務器遠程鏈接密碼 "entryDir": "dist",// 打包目錄文件,會將該目錄下全部文件上傳到服務器serviceDir變量指定路徑下 "serviceDir": "/usr/local/tomcat/webapps/test" // 服務器web存放目錄 }, // 生產環境服務器配置 "build_upload_pro": { "host": "xxx.xxx.xxx.xxx", "port": 22, "user": "xxx", "password": "xxxx", "entryDir": "dist", "serviceDir": "/usr/local/tomcat/webapps/test" } } }
// package.json "up": { "kaiguan": 2 // 0:表示不上傳部署,1:表示部署到測試環境,2:表示部署到生產環境 }
上傳服務器顯示結果:
npm
插件源碼解析:json
// index.js var tool = require('./tool.js') var path = require('path') var fs = require('fs') var readAndDelEvery = tool.readAndDelEvery var readAndPut = tool.readAndPut var opt // 服務器配置變量 function Gouzi(options) { if (!fs.existsSync(options.path)) { return } opt = JSON.parse(fs.readFileSync(options.path))[options.key] // 讀取服務器配置文件 } Gouzi.prototype.apply = function(compiler) { compiler.plugin("beforeRun", function() { handle({ compiler, type: 'beforeRun' }) }) compiler.plugin("done", function(params) { // 當webpack打包完後會執行這個鉤子 handle({ compiler, type: 'done' }) }); }; function handle ({ compiler, type }) { let opt2 = JSON.parse(JSON.stringify(opt)) if (!opt2) { process.exit() return } const pajp = path.resolve(compiler.context, 'package.json') // 讀取package.json中up配置 if (fs.existsSync(pajp)) { const config = JSON.parse(fs.readFileSync(pajp)) if (Object.prototype.hasOwnProperty.call(config, 'up')) { // 判斷打包到哪一個環境 if (config.up.kaiguan === 0) { return } else if (config.up.kaiguan === 1) { opt2 = opt2.build_upload_test } else if (config.up.kaiguan === 2) { opt2 = opt2.build_upload_pro } else { return } } } opt2.serviceConfig = { host: opt2.host, port: opt2.port, user: opt2.user, password: opt2.password, } // 能夠多入口上傳部署 if (Array.isArray(opt2.entryDir)) { var arr = [] opt2.entryDir.forEach((v, i) => arr.push({ entryDir: v, serviceDir: opt2.serviceDir[i], serviceConfig: opt2.serviceConfig })) arr.forEach(v => ( type === 'done' ? readAndPut(v, compiler.context) : readAndDelEvery(v, compiler.context) )) } else { if (Array.isArray(opt2.serviceDir)) { var arr = [] opt2.serviceDir.forEach((v, i) => arr.push({ entryDir: opt2.entryDir, serviceDir: v, serviceConfig: opt2.serviceConfig })) arr.forEach(v => ( type === 'done' ? readAndPut(v, compiler.context) : readAndDelEvery(v, compiler.context) )) } else { type === 'done' ? readAndPut(opt2, compiler.context) : readAndDelEvery(opt2, compiler.context) } } } module.exports = Gouzi
// tool.js const fs = require('fs') const path = require('path') const cc = require('ssh2-sftp-client') // node的ftp包,用於上傳下載 function readAll (dirPath, currentPath) { dirPath = path.resolve( currentPath, dirPath ) const paths = [dirPath] const aaa = [] let res = [] while (paths.length) { const head = paths.shift() aaa.push(head) if (!fs.existsSync(head)) continue const f = fs.statSync(head) if (!f.isDirectory()) res.push(head) const d = fs.readdirSync(head) d.forEach(v => { const p = path.resolve(head, v) if (!fs.existsSync(p)) return const f = fs.statSync(p) if (!f.isDirectory()) res.push(p) else paths.push(p) }) } const reg = new RegExp(dirPath.replace(/\\/g, '\\\\'), 'g') return res.map(v => v.replace(reg, '').replace(/\\/g, '/')) } // 將指定目錄文件上傳到服務器指定目錄 async function uploadAll ({ serviceDir, allFiles, config, entryDir }, currentPath) { const successArr = [] const failArr = [] const c = new cc(config) let a await c.connect(config) for (const i in allFiles) { const v = allFiles[i] const localDir = path.resolve(currentPath, entryDir, v.slice(1)) const remoteDir = serviceDir + v try { const a = await c.exists(remoteDir.slice(0, remoteDir.lastIndexOf('/'))) if (!a) { await c.mkdir(remoteDir.slice(0, remoteDir.lastIndexOf('/')), true) } const p = await c.put( localDir, serviceDir + v ) successArr.push(`${localDir} to: ${remoteDir}`) } catch (e) { failArr.push({ failFile: `${localDir} to: ${remoteDir}`, reason: e + '' }) } } c.end() successArr.length && console.log(` \x1B[32m[ 上傳完畢. uploaded \n 成功列表.successFiles \n ${successArr.map(v => `success: ${v} \n`)} ]\x1B[39m `) failArr.length && console.log(` \x1B[31m[ 失敗列表.failedFiles \n ${failArr.map(v => `failed: ${JSON.stringify(v, 0, ' ')} \n`)} ]\x1B[39m `) } async function delEvery ({ serviceDir, allFiles, config, entryDir }, uploadAfterDel) { const c = new cc(config) await c.connect(config) for (const i in allFiles) { const v = allFiles[i] const remoteDir = serviceDir + v try { const a = await c.exists(remoteDir.slice(0, remoteDir.lastIndexOf('/'))) if (a) { await c.delete(remoteDir) } } catch (e) { } } c.end() uploadAfterDel() } var delObj function readAndDelEvery (item, currentPath) { const allDelFiles = readAll(item.entryDir, currentPath) delObj = { entryDir: item.entryDir, serviceDir: item.serviceDir, allFiles: allDelFiles, config: item.serviceConfig, } } function readAndPut (item, currentPath) { const allFiles = readAll(item.entryDir, currentPath) var obj = { entryDir: item.entryDir, serviceDir: item.serviceDir, allFiles, config: item.serviceConfig, } delEvery(obj, () => uploadAll(obj, currentPath)) } module.exports = { readAndDelEvery, readAndPut, }
項目地址:https://github.com/Revelation...tomcat