Published on
693

实现一个简单的 webpack5 nodejs polyfill 插件

Authors
  • avatar
    Name
    小辉辉
    Twitter

现象

有一次项目开发中需要实现对js代码进行转换,包括提取一个对象中的方法,根据特殊规则对某些字符串进行转换等。第一反应就是可以借助babel这个库来实现,具体的实现逻辑就是现将js字符串转换为AST对象,再遍历这个AST对象,实现相关转换逻辑,利用babel自带的类型功能进行AST相关节点的替换,完成转化后再将AST转换为js字符串。

借助babel官方稳定实现这个功能并不难,但是最终在调试过程中遇到了一些意外情况。对应的开发环境是这样的,webpack5 + babel7.x版本,在项目中引入相关babel库后就出现了相关编译错误,主要错误总结如下:

process未定义,Buffer模块无法找到,path模块无法找到

方案

对于上述错误,大家都知道这些模块只有在nodejs开发环境下才存在,在浏览器环境下因为缺失这些模块肯定会报错。那怎么解决呢?首先是看了webpack的官方文档,里面就提到饿可以使用resolve.fallback属性来解决,按照文档尝试了一番,发现又有了其它模块提示找不到这些模块的问题。

所以就有了这个webpack5-node-polyfill-plugin这个插件,我是怎么想的呢?如果后期有些项目也遇到这种错误场景,我们有去配置这些参数相对来说就有些做重复工作了,为何不将这类配置直接封装到一个webpack插件里面呢?后面有需要直接引入这个插件就行了,这个样子就多简单了。除此之外,我们还可以考虑对这个插件将所有nodejs环境下可能存在在浏览器环境中用到的相关模块全部实现了,这样一来,可谓是一劳永逸啊。

最后,这个插件的实现也很简单,主要引入了node-libs-browser这个插件,完整代码如下

const webpack = require('webpack');
const nodeLibs = require('node-libs-browser');

module.exports = class Webpack5NodePolyfillPlugin {

  apply(compiler) {

    compiler.options.plugins.push(
      new webpack.ProvidePlugin({
        Buffer: ['buffer', 'Buffer'],
        process: nodeLibs.process,
      }),
    );

    const extractfallBack = Object.keys(nodeLibs).reduce((memo, key) => {
      if (nodeLibs[key]) {
        memo[key] = nodeLibs[key];
      } else {
        memo[key] = false;
      }
      return memo;
    }, {});

    compiler.options.resolve.fallback = {
      ...extractfallBack,
      ...compiler.options.resolve.fallback,
    };

  }
}

核心逻辑就是遍历node-libs-browser模块库,将里面每个暴露的模块添加到webpack的resolve.fallback对象下,特别要注意的是通过webpack自带的webpack.ProvidePlugin插件单独处理了process和Buffer两个模块。

现在该插件也同时发布到了npm仓库,有需要直接本地安装即可:

npm i webpack5-node-polyfill-plugin