使用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便可。

腳手架項目地址

相關文章
相關標籤/搜索