使用webpack打包koa2 框架app
以前在用koa写server的时候,发布简直是噩梦。需要将src里面的全部文件都覆盖掉,config配置文件也要覆盖,稍有不慎就会线上报各种各样的问题,然后就得回退,本地调好在发布。偶然看见一篇文章讲如何使用webpack打包koaapp,惊为天人,原来webpack也能打包后台。这在以前想都没想过。
关键问题
一:所有node_modules里的模块都不进行打包
webpack的核心功能是将引用的各个模块打到一个文件里,并会将各种规范的模块进行统一的模块化处理(webpack规范)。
然而node中包含大量的fs、path操作,这些fs和path操作在打包完成后将没有操作对象,还会报出很多各样的错误。
所以使用webpack打包的核心就是拒绝打包一切node_modules里的模块,只是将相对路径引用的文件打包到一个文件里。恰巧我们发现webapck提供externals属性来排除掉不需要打包的模块。
再深入点我们可以发现:像webpack、nodemon、babel-preset-env这样的模块是app开发环境依赖的包,我们的程序里根本不会require这些模块。
综上可以发现:我们只将所有require到的包排除掉就可以了,这个模块对应的也就是package.json里dependencies下的模块。有关dependencies和devDependencies的区别要理解好。
因此我们可以使用externals-dependencies这个插件配合externals属性实现dependencies的排除工作。
代码:
constwebpack=require('webpack'); const_externals=require('externals-dependencies') module.exports={ ... externals:_externals(), ... }
二:target指向node
官方文档:编译为类Node.js环境可用(使用Node.jsrequire加载chunk)
代码:
target:'node',
三:增加node配置
官方文档:这些选项可以配置是否polyfill或mock某些Node.js全局变量和模块。这可以使最初为Node.js环境编写的代码,在其他环境(如浏览器)中运行。
代码:
node:{
console:true,
global:true,
process:true,
Buffer:true,
__filename:true,
__dirname:true,
setImmediate:true,
path:true
},
四:babel配置
为了兼容低版本的node不原生支持async/await的问题。这里babel我使用了babel-preset-env{"modules":false}的配置。此配置会将es6语法转为es5语法,例如let、const转为var。
同时将所有的async/await函数也转成了polyfill里定义的_asyncToGenerator函数。
function_asyncToGenerator(fn){returnfunction(){vargen=fn.apply(this,arguments);returnnewPromise(function(resolve,reject){functionstep(key,arg){try{varinfo=gen[key](arg);varvalue=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{returnPromise.resolve(value).then(function(value){step("next",value);},function(err){step("throw",err);});}}returnstep("next");});};}
其实是使用promise实现了async函数的功能。
当然这个函数在运行时还需要regeneratorRuntime函数。所以我在全局引入了babel-polyfill来提供regeneratorRuntime函。
注:如果你的node版本很高且原生支持async/await,大可将babel-preset-env和babel-polyfill省略掉
代码:
constpath=require('path'); constwebpack=require('webpack'); const_externals=require('externals-dependencies') module.exports={ entry:{ app:[ //如果polyfill放在这里,打包的时候将不会被external,必须在js里require才能有效external //'babel-polyfill', './src/index.js' ] }, output:{ path:path.resolve(__dirname), filename:'[name].js' }, resolve:{ extensions:[".js"] }, target:'node', externals:_externals(), context:__dirname, node:{ console:true, global:true, process:true, Buffer:true, __filename:true, __dirname:true, setImmediate:true, path:true }, module:{ rules:[ { test:/\.js/, use:['babel-loader'] } ] }, plugins:[ newwebpack.DefinePlugin({ 'process.env':{ NODE_ENV:'"development"' } }), ] }
部署
经过打包,部署的时候就方便多了,只需要将package.json、app.js、以及view里的html部署上线就好了。然后在服务器上执行
1.npminstall
2.npmrunfor
然后server就后台运行了。如果需要更新发布,只需要本地重新npmrundev或npmrunbuild打好包,拖到服务器覆盖app.js即可。