用 webpack 构建 node 后端代码采坑记录

1,042 阅读3分钟
  • webpack不仅可以构建浏览器端的npm包,也可以构建node端使用的npm包,有些比如构建类的脚本,但是node端的代码其实是不用编译或者构建的,整个node的环境有它自己的一个模块化或者依赖机制,但是即使是现在最新的node版本,对ES6/7的支持还是捉襟见肘。当然使用一些第三方库可以做到支持类似 async/await 这样的语法,但是毕竟不是规范不是标准,这样看来,node端的代码还是有构建的需要的。这里我们选取的工具就是 webpack 以及它的一些 loader。

  • 首先,一个 node app 必定有一个入口文件 index.js,按照 webpack 的规则,我们可以把所有的代码打包成一个文件 bundle.js ,然后运行这个 bundle.js即可,webpack.config.js 如下:

var webpcak = require('webpack');module.exports = {
    entry: ['./index.js'
    ],
    output: {
        pathpath.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    }
}

但是有一个很严重的问题,这样打包的话,一些 npm中的模块也会被打包进这个 bundle.js,还有 node的一些原生模块,比如 fs/path 也会被打包进来,这明显不是我们想要的。所以我们得告诉 webpack,你打包的是 node 的代码,原生模块就不要打包了,还有 node_modules 目录下的模块也不要打包了,webpack.config.js 如下:

var webpcak = require('webpack')
var nodeModules = {}
fs.readdirSync('node_modules')
    .filter(function(x) {
        return ['.bin'].indexOf(x) === -1;
    })
    .forEach(function(mod) {
        nodeModules[mod] = 'commonjs ' + mod;
    })
module.exports = {
    entry: [        
        './index.js'
    ],
    output: {
        pathpath.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    target: 'node',
    externals: nodeModules
}

主要就是在 webpack 的配置中加上 target: 'node'告诉 webpack 打包的对象是 node 端的代码,这样一些原生模块 webpack 就不会做处理。另一个 webpack 的 externals 属性,它的主要作用是告知 webpack 在打包过程中,遇到 externals中声明的模块不用处理。比如在前端, jQuery 的包通过 CDN 的方式以 script 标签引入,如果此时在代码中出现 require('jQuery') ,并且直接用 webpack 打包比定会报错。因为在本地并没有这样的一个模块,此时就必须在 externals 中声明 jQuery 的存在。也就是 externals 中的模块,虽然没有被打包,但是是代码运行是所要依赖的,而这些依赖是直接存在在整个代码运行环境中,并不用做特殊处理。 在 node 端所要做的处理就是过滤出 node_modules中所有模块,并且放到 externals中。

采坑:
ReferenceError: regeneratorRuntime is not defined
这个报错一般是语法不兼容引起的,浏览器对es6新语法并不支持,可以用babel-polyfill去解决

Babel 包含一个可自定义的 regenerator runtime 它会仿效一个完整的 ES2015+ 环境,并意图运行于一个应用中而不是一个库/工具。这个 polyfill 会在使用 babel-node 时自动加载。

这意味着你可以使用新的内置对象比如 Promise 或者 WeakMap, 静态方法比如 Array.from 或者 Object.assign, 实例方法比如 Array.prototype.includes 和生成器函数(提供给你使用 regenerator)。为了达到这一点, polyfill 添加到了全局范围,就像原生类型比如 String 一样。

解决方法

安装

1、npm install --save babel-polyfill

引入

第一种:require("babel-polyfill")

第二种:import "babel-polyfill"

第三种(适用于webpack构建的方式,在webpack.config.js中配置):
    module.exports = {
        entry: ["babel-polyfill""./app/js"]
    }