diff --git a/README.md b/README.md index 04cd541..8c5ecb9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Introduction -A plugin that deploys webpack bundles to server. It's useful when server ftp/sftp is forbidden or accessing server need pin + dynamic token. +A plugin that deploys webpack bundles to server. It's useful when server ftp/sftp is forbidden or accessing server need pin + dynamic token each time. # Install ``` @@ -10,10 +10,11 @@ npm i deploy-server-webpack-plugin -D **Client config** -You need config your webpack conf file like this: +Modify your webpack config file like below, change the "from" and "dest" fields according to your own project, "from" is based on webpack output dirname, "dest" means the path on server you want to push. token field validation need server side to cooperate. ```js -const DeployServerPlugin = require('deploy-server-webpack-plugin'); +const path = require('path') +const DeployServerPlugin = require('deploy-server-webpack-plugin') module.exports = { // ... @@ -23,7 +24,7 @@ module.exports = { receiver: 'http://1.23.45.678:9999/receiver', mapping: { // Object type from: path.resolve(__dirname, '../dist'), // absolute path - dest: '/data/front' + dest: '/data/project/front' } }) ] @@ -32,6 +33,7 @@ module.exports = { or ```js +const path = require('path') const DeployServerPlugin = require('deploy-server-webpack-plugin') module.exports = { @@ -42,12 +44,12 @@ module.exports = { receiver: 'http://1.23.45.678:9999/receiver', mapping: [ // Array type { - from: path.resolve(__dirname, '../dist/static'), // absolute path - dest: '/data/public/static', + from: path.resolve(__dirname, '../dist/static'), + dest: '/data/project/public/static', }, { - from: path.resolve(__dirname, '../dist/index.tpl'), // absolute path - dest: '/data/views/index.tpl', + from: path.resolve(__dirname, '../dist/index.tpl'), + dest: '/data/project/views/index.tpl', }, // ... ], @@ -59,7 +61,7 @@ module.exports = { **Server Config** -Please copy ./server folder to you remote server somewhere, init the project and start it. +Copy ./server folder to you server machine somewhere, init the project and start it. ``` npm i @@ -67,7 +69,7 @@ npm run start ``` Next config your nginx/apache to allow your node service can be accessed. -Try to visit "@your host/receiver" in browser, when you see "Method Not Allowed", it means node server started success, but 'GET' method is not allowed because we only config "POST" router to upload files. +Try to visit "@your host/receiver" in browser, when you see "Method Not Allowed", it means node server started success, but 'GET' method is not allowed because we only config "POST" router to upload files. Server code is based on Koa, change it according your demand. # Options @@ -78,7 +80,7 @@ Try to visit "@your host/receiver" in browser, when you see "Method Not Allowed" |token|String|false|for security if needed| # Others -Sometimes bundle files are too big and uploading appears "504 Gateay Time-out" error, enlarge client_max_body_size value in nginx.conf may solve this problem: +Sometimes bundle file is too big and uploading appears "504 Gateay Time-out" error, enlarge client_max_body_size value in nginx.conf may solve this problem: ``` client_max_body_size: 10M; #default 1M ``` diff --git a/dist/index.js b/dist/index.js index c4d9047..97fe12b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,4 +1,4 @@ -'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i0&&arguments[0]!==undefined?arguments[0]:{};_classCallCheck(this,DeployServerWebpackPlugin);this.config=config;}_createClass(DeployServerWebpackPlugin,[{key:'apply',value:function apply(compiler){var _this=this;compiler.plugin('after-emit',function(compilation,callback){_this.validConfig(compilation);_this.deployHandler(callback);});}},{key:'validConfig',value:function validConfig(compilation){var _config=this.config,receiver=_config.receiver,_config$token=_config.token,token=_config$token===undefined?'':_config$token;var mapping=this.config.mapping;if(!receiver){this.error('Missing param: receiver');}if(!mapping){this.error('Missing param: mapping');}var mappingType=Object.prototype.toString.call(mapping);if(mappingType==='[object Object]'){mapping=[mapping];}else if(mappingType==='[object Array]'){// do nothing +'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i0&&arguments[0]!==undefined?arguments[0]:{};_classCallCheck(this,DeployServerWebpackPlugin);this.config=config;}_createClass(DeployServerWebpackPlugin,[{key:'apply',value:function apply(compiler){var _this=this;compiler.plugin('after-emit',function(compilation,callback){_this.validateConfig(compilation);_this.deployHandler(callback);});}},{key:'validateConfig',value:function validateConfig(compilation){var _config=this.config,receiver=_config.receiver,_config$token=_config.token,token=_config$token===undefined?'':_config$token;var mapping=this.config.mapping;if(!receiver){this.error('Missing param: receiver');}if(!mapping){this.error('Missing param: mapping');}var type=Object.prototype.toString.call(mapping);if(type==='[object Object]'){mapping=[mapping];}else if(type==='[object Array]'){// do nothing }else{this.error('Invalid param: mapping');}var assets=compilation.assets;var avalAssets={};mapping.map(function(item,index){for(var key in assets){var asset=assets[key];var assetPath=asset.existsAt;var from=item.from;// limit "src" path within compiled files if(assetPath.startsWith(from)){if(!avalAssets[from]){avalAssets[from]=[assetPath];continue;}avalAssets[from].push(assetPath);}}});var avalKeys=Object.keys(avalAssets);if(!avalKeys.length){this.error('No available mapping files');}this.receiver=receiver;this.mapping=mapping;this.token=token;this.avalKeys=avalKeys;this.avalAssets=avalAssets;}},{key:'deployHandler',value:function deployHandler(callback){var _this2=this;var formData={};this.avalKeys.map(function(item,index){_this2.avalAssets[item].map(function(from){// compatible with windows -var dest=(_this2.mapping[index].to+from.replace(item,'')).replace(/\\/g,'/');_this2.deploy({dest:dest,token:_this2.token,file:fs.createReadStream(from)});});});callback();}},{key:'deploy',value:function deploy(formData){request.post({url:this.receiver,formData:formData},function(err){var _ref=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{},statusCode=_ref.statusCode;var body=arguments[2];var time=new Date().toLocaleTimeString();if(!err&&200===statusCode){console.log(chalk.green('['+time+'] [success] => '+formData.dest));return;}console.log(chalk.yellow('['+time+'] [failed] => '+formData.dest+' '+body));});}},{key:'error',value:function error(err){console.log('\n'+chalk.yellow('[deploy-server-webpack-plugin] '+err));process.exit();}}]);return DeployServerWebpackPlugin;}(); \ No newline at end of file +var dest=(_this2.mapping[index].to+from.replace(item,'')).replace(/\\/g,'/');_this2.deploy({file:fs.createReadStream(from),dest:dest,token:_this2.token});});});callback();}},{key:'deploy',value:function deploy(formData){request.post({url:this.receiver,formData:formData},function(err){var _ref=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{},statusCode=_ref.statusCode;var body=arguments[2];var time=new Date().toLocaleTimeString();if(!err&&statusCode===200){console.log(chalk.green('['+time+'] [success] => '+formData.dest));return;}console.log(chalk.yellow('['+time+'] [failed] => '+formData.dest+' '+body));});}},{key:'error',value:function error(err){console.log('\n'+chalk.yellow('[deploy-server-webpack-plugin] '+err+'. Deploy interrupted.'));process.exit();}}]);return DeployServerWebpackPlugin;}(); \ No newline at end of file diff --git a/package.json b/package.json index 51a4bd4..6142424 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "deploy-server-webpack-plugin", - "version": "0.0.1", + "version": "0.0.2", "description": "A plugin that deploys wepack bundles to server", "main": "dist/index.js", "scripts": { @@ -12,7 +12,14 @@ }, "keywords": [ "deploy server", - "webpack plugin" + "push server", + "publish server", + "release server", + "webpack plugin", + "node deploy", + "node push", + "node publish", + "node release" ], "author": "Jordan Wang", "license": "MIT", diff --git a/server/app.js b/server/app.js index 70af632..8d39c36 100644 --- a/server/app.js +++ b/server/app.js @@ -1,12 +1,12 @@ const Koa = require('koa'); const koaBody = require('koa-body'); -const Router = require('koa-router'); +const KoaRouter = require('koa-router'); const fse = require('fs-extra'); -const router = new Router(); +const router = new KoaRouter(); router.post('/receiver', koaBody({ multipart: true -}), async (ctx, next) => { +}), async ctx => { const { files, body: { dest, token } } = ctx.request; // deal with "token" here if needed diff --git a/server/package.json b/server/package.json index 98e401e..ee2180c 100644 --- a/server/package.json +++ b/server/package.json @@ -1,19 +1,19 @@ { - "name": "receiver", - "version": "0.0.1", - "description": "file receiver", - "main": "app.js", - "scripts": { - "start": "pm2 start app.js", - "stop": "pm2 stop app.js" - }, - "author": "Jordan Wang", - "license": "MIT", - "dependencies": { - "fs-extra": "^6.0.1", - "koa": "^2.5.2", - "koa-body": "^4.0.4", - "koa-router": "^7.4.0", - "pm2": "^3.0.0" - } + "name": "receiver", + "version": "0.0.2", + "description": "files receiver", + "main": "app.js", + "scripts": { + "start": "pm2 start app.js", + "stop": "pm2 stop app.js" + }, + "author": "Jordan Wang", + "license": "MIT", + "dependencies": { + "fs-extra": "^6.0.1", + "koa": "^2.5.2", + "koa-body": "^4.0.4", + "koa-router": "^7.4.0", + "pm2": "^3.0.0" + } } diff --git a/src/index.js b/src/index.js index a6f8e97..37e7823 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,4 @@ const fs = require('fs'); -const path = require('path'); const chalk = require('chalk'); const request = require('request'); @@ -10,12 +9,12 @@ module.exports = class DeployServerWebpackPlugin { apply(compiler) { compiler.plugin('after-emit', (compilation, callback) => { - this.validConfig(compilation); + this.validateConfig(compilation); this.deployHandler(callback); }); } - validConfig(compilation) { + validateConfig(compilation) { const { receiver, token = '' } = this.config; let { mapping } = this.config; @@ -26,10 +25,10 @@ module.exports = class DeployServerWebpackPlugin { this.error('Missing param: mapping'); } - const mappingType = Object.prototype.toString.call(mapping); - if (mappingType === '[object Object]') { + const type = Object.prototype.toString.call(mapping); + if (type === '[object Object]') { mapping = [mapping]; - } else if (mappingType === '[object Array]') { + } else if (type === '[object Array]') { // do nothing } else { this.error('Invalid param: mapping'); @@ -72,9 +71,9 @@ module.exports = class DeployServerWebpackPlugin { // compatible with windows const dest = (this.mapping[index].to + from.replace(item, '')).replace(/\\/g, '/'); this.deploy({ + file: fs.createReadStream(from), dest, - token: this.token, - file: fs.createReadStream(from) + token: this.token }); }); }); @@ -88,7 +87,7 @@ module.exports = class DeployServerWebpackPlugin { formData }, (err, { statusCode } = {}, body) => { const time = new Date().toLocaleTimeString(); - if (!err && 200 === statusCode) { + if (!err && statusCode === 200) { console.log(chalk.green(`[${time}] [success] => ${formData.dest}`)); return; } @@ -97,7 +96,7 @@ module.exports = class DeployServerWebpackPlugin { } error(err) { - console.log(`\n${chalk.yellow('[deploy-server-webpack-plugin] ' + err)}`); + console.log(`\n${chalk.yellow('[deploy-server-webpack-plugin] ' + err + '. Deploy interrupted.')}`); process.exit(); } };