使用webpack打包koa2 app

前言

之前在用koa写server的时候,发布简直是噩梦。须要将src里面的所有文件都覆盖掉,config配置文件也要覆盖,稍有不慎就会线上报各类各样的问题,而后就得回退,本地调好在发布。偶然看见一篇文章讲如何使用webpack打包koa app,惊为天人,原来webpack也能打包后台。这在之前想都没想过。html

关键问题

一:全部node_modules里的模块都不进行打包

webpack的核心功能是将引用的各个模块打到一个文件里,并会将各类规范的模块进行统一的模块化处理(webpack规范)。node

然而node中包含大量的fs、path操做,这些fs和path操做在打包完成后将没有操做对象,还会报出不少各样的错误。webpack

因此使用webpack打包的核心就是拒绝打包一切node_modules里的模块,只是将相对路径引用的文件打包到一个文件里。恰巧咱们发现webapck提供externals属性来排除掉不须要打包的模块。git

再深刻点咱们能够发现:像webpack、nodemon、babel-preset-env这样的模块是app开发环境依赖的包,咱们的程序里根本不会require这些模块。es6

综上能够发现:咱们只将全部require到的包排除掉就能够了,这个模块对应的也就是package.json里dependencies下的模块。有关dependencies和devDependencies的区别要理解好。github

所以咱们能够使用externals-dependencies这个插件配合externals属性实现dependencies的排除工做。web

代码:npm

const webpack = require('webpack');
const _externals = require('externals-dependencies')
module.exports = {
    ...
    externals: _externals(),
    ...
}
复制代码

二:target指向node

官方文档:编译为类 Node.js 环境可用(使用 Node.js require 加载 chunk)json

代码:promise

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) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
复制代码

实际上是使用promise实现了async函数的功能。

固然这个函数在运行时还须要regeneratorRuntime函数。因此我在全局引入了babel-polyfill来提供regeneratorRuntime函。

注:若是你的node版本很高且原生支持async/await,大可将babel-preset-env和babel-polyfill省略掉

代码:

const path = require('path');
const webpack = 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: [
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"development"'
            }
        }),
    ]
}

复制代码

部署

通过打包,部署的时候就方便多了,只须要将package.json、app.js、以及view里的html部署上线就行了。而后在服务器上执行

1. npm install 
2. npm run for
复制代码

而后server就后台运行了。若是须要更新发布,只须要本地从新npm run dev或npm run build打好包,拖到服务器覆盖app.js便可。

脚手架项目地址

相关文章
相关标签/搜索