Published on

浏览器中有node的process对象?

Authors

问题

webpack 构建出来的 js,运行在浏览器中竟然带有一个提供 node process 的模块,什么来头?

这两天在写一个兼容 IE9 跨域的请求库,因为 axios 对 IE9 下跨域支持存在问题,所以得自己造,其中有一个地方需要做如下判断

/** 返回当前是否为node环境 */
function isNodeEnvironment() {
return typeof process !== 'undefined'
}

构建后在浏览器里运行,返回结果始终是 false。查源代码发现 webpack 秉持雷锋精神,为我们引入了一个 process 的 polyfill,源代码路径是node_modules/process/browser.js GitHub ,在浏览器 window 下创建了一个 process 对象,模拟了 node 端 process 提供的几个接口;这个 polyfill 不管是 development 还是 production 模式,都会加入;

webpack 为什么要这么处理?

This allows code originally written for the Node.js environment to run in other environments like the browser.

webpack 官方文档有说明,目的时让一些为 nodejs 端编写的代码,可以运行在如浏览器等其他环境中。

当 webpack 的构建目标是 target 的值是 browser(这也是 webpack 构建目标的默认值)时,会自动激活内置的插件NodeStuffPluginNodeSourcePlugin ,在检测到项目源代码使用到了 node 对象比如 process 时,自动加入对应的 polyfill。

处理方式

为了准确判断是否 node 环境,有多种方式可以达到

1. 去掉 polyfill

如果明确不需要包含 node 的 polyfill,在 webpack 3.0 及以后中,可以在配置文件中加入node:false,关闭所有的 node polyfill;webpack 3.0 以前则只能使用 node 配置为对象,并配置对象内部具体 polyfill 项的 polyfill 值,参考下边的部分关闭 polyfill 方式。

module.exports = {
//...
node: false,
}

如果只想关闭 node polyfill 的一部分,可以参考官方文档,针对对应的选项设置其 polyfill 形式

  • true:加入 polyfill;
  • "mock":加入一个 mock 文件,提供预期的接口,但接口无实际行为;
  • "empty":提供一个空对象;
  • false:不提供 polyfill;
module.exports = {
//...
node: {
console: false,
global: true,
process: true,
__filename: 'mock',
__dirname: 'mock',
Buffer: true,
setImmediate: true,
// See "Other node core libraries" for additional options.
},
}

2. 代码引入附加判断

让环境判断更准确

/** 返回当前是否为node环境 */
function isNodeEnvironment() {
return typeof process !== 'undefined' && process.browser !== true
}

总体来说,个人不建议直接粗暴的把为 node 端的模块直接拿过来,除非包明确声明了可以用于浏览器端,否则这个不确定性有点大;