彻底搞懂webpack5为什么总是提示process is not defined

1,309 阅读3分钟

项目中使用到了net模块,因为要支持web环境,所以fallback里面配置了net-browserify进行了模块重定向。

net: require.resolve("net-browserify"),

运行起来的时候仍旧报错process is not defined

 Uncaught ReferenceError: process is not defined
    at ./node_modules/readable-stream/lib/_stream_writable.js
    at ./node_modules/readable-stream/readable-browser.js
    at ./node_modules/browserify-sign/browser/index.js
    at ./node_modules/crypto-browserify/index.js
    at ./node_modules/net-browserify/api.js // 可以看到这里没有使用browser.js作为入口

在package.json中是有明确定义browser的入口逻辑的,但是从报错堆栈中发现并没有加载browser对应的入口文件,npm package.json browser字段含义解释

{
  "name": "net-browserify",
  "main": "api.js",
  "browser": "browser.js",
}

查了好久,也没有找到为什么没有加载browser对应的入口文件,网上给出相关的解决方案比较多,大部分也是针对webpack4的,我使用的是webpack5,也看了webpack5相关的源码,相关的逻辑比较重,对browser的处理看着应该是没有。

最后的解决办法,既然无法正确识别到browser,手动指定browser的入口即可

net: require.resolve("net-browserify/browser.js"),

process.debug的问题

在后续的开发中,同样又是遇到了报错:Uncaught ReferenceError: process is not defined,只不过这次是出现在其他的package里面,仔细看了下附近的代码:

/*<replacement>*/
var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;

和上边的情况非常雷同,猜测底层会根据process进行环境的判定,然后加载不同的入口逻辑,大概问题还是在定义的process的身上,在webpack配置里面我仅仅配置了全局的porcess变量的部分属性

webpackChain.plugin("process_define")
    .use(webpack.DefinePlugin, [{
        'process.env': {}, // 我仅仅配置了env
        'process.browser': true // 追加配置browser字段
    }]);

重新构建运行后,发现之前的代码process.browser附近的逻辑被正确的压缩了

/*<replacement>*/
var asyncWrite =  false ? 0 : pna.nextTick;

其实之前遇到的问题也是因为没有process.browser变量导致的后续问题,在webpack DefinePlugin里面追加该变量即可。

深入了解: process/browser

在搜索到的其他解决方案里面,有在fallback中配置process/browser的解决办法。

实际我测试是没用的,我也尝试着调整了fallback中,将process/browser放在前边,同样也没有任何的效果。

falllback的这种处理方式我理解的是在import "process"的时候有效果,像我使用到的net-borwserify等一些第三方库,在源码里面人家没有使用import或者require,直接写的就是process.xxx,所以这就导致只能通过DefinePlugin去解决这个问题。

看了下process/browser的源码,其本质也是在定义一个process变量,在web环境中模拟nodejs的process。

var process = module.exports = {};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

问题总结

其实遇到process相关的问题,大部分原因还是因为Define Plugin缺失相关的process变量导致的undefined报错,我的第一反应是webpack没有加载正确的入口文件,一直在追查为什么没有加载对应的入口,顺着这个思路追查下去,还要啃源码,其实方向就错了。