Webpack node、output.jsonpFunction 配置详解
最近尝试给一些用到 webpack 的项目升级到最新 webpack5 版本,其中遇到了一些问题,我挑了两个比较典型的问题,其中主要涉及到了 webpack 的 node 属性跟 output.jsonpFunction (webpack5 以前版本)属性,下面我们结合 webpack 的源码来分析一下这两个属性。
开始
这里使用的 webpack 版本为:
- webpack@^4.46.0
- webpack@^5.88.2
首先我们创建一个 webpack4 的项目:
webpack-node1:
mkdir webpack-node2 && cd webpack-node2 && npm init -y
接着安装 webpack4 :
npm install -D webpack@4.46.0 webpack-cli@4.10.0
创建创建一个 src/index.js 入口文件:
mkdir src && touch src/index.js
在项目根目录 webpack-node1 目录下创建一个 webpack 配置文件 webpack.config.js:
cd .. && touch webpack.config.js
// webpack.config.js
module.exports = {
output: {
publicPath: "./dist/",
},
devtool: false, // 关闭 source-map 功能
};
ok,我们在项目根目录 webpack-node1 下执行一下 webpack 打包命令看效果:
npx webpack build --mode=development

可以看到,因为我们的入口文件 src/index.js 是一个空文件,所以打包后的 dist/main.js 文件除了一些 webpack 的辅助函数外,入口文件里面为空。
最后我们创建一个 test.html 文件来测试:
touch test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack4</title>
<script src="./dist/main.js"></script>
</head>
<body>
</body>
</html>
ok,项目我们就创建完了,接下来我们看一下 webpack.node 配置。
Node 配置
我们先看一下 webpack官网 对它的介绍:
这些选项可以配置是否 polyfill 或 mock 某些 Node.js 全局变量。
此功能由 webpack 内部的
NodeStuffPlugin插件提供。Warning
从 webpack 5 开始,你只能在
node选项下配置global、__filename或__dirname。如果需要在 webpack 5 下的 Node.js 中填充fs,请查阅 resolve.fallback 获取相关帮助。node
boolean: false` `objectwebpack.config.js
module.exports = { //... node: { global: false, __filename: false, __dirname: false, }, };从 webpack 3.0.0 开始,
node选项可能被设置为false,以完全关闭NodeStuffPlugin插件。node.global
boolean` `'warn'Tip
如果你正在使用一个需要全局变量的模块,请使用
ProvidePlugin替代global。关于此对象的准确行为,请查看Node.js 文档。
选项:
true: 提供 polyfill.false: 不提供任何 polyfill。代码可能会出现ReferenceError的崩溃。'warn': 当使用global时展示一个警告。node.__filename
boolean` `'mock' | 'warn-mock' | 'eval-only'选项:
true: 输入文件的文件名,是相对于context选项。false: webpack 不会更改__filename的代码。在 Node.js 环境中运行时,出文件的文件名。'mock': value 填充为'index.js'。'warn-mock': 使用'/index.js'但是会展示一个警告。'eval-only'node.__dirname
boolean` `'mock' | 'warn-mock' | 'eval-only'选项:
true: 输入 文件的目录名,是相对于context选项。false: webpack 不会更改__dirname的代码,这意味着你有常规 Node.js 中的__dirname的行为。在 Node.js 环境中运行时,输出 文件的目录名。'mock': value 填充为'/'。'warn-mock': 使用'/'但是会显示一个警告。'eval-only'
以上是 webpack5 的 node 配置的描述。
webpack4
ok,看完了官网的描述,我们来用一下这个 node 配置。
我们修改一下 src/index.js 文件:
// 判断是浏览器环境
const isBrowser = process.browser; // 使用 nodejs 的 process 对象
console.log(isBrowser);
console.log(__dirname); // 使用 nodejs 的 __dirname 全局属性
console.log(global); // 使用 nodejs 全局对象 global
我们重新执行打包命令看效果:
npx webpack build --mode=development
浏览器打开 test.html 文件:

可以看到,即使是 nodejs 环境中的变量,我们在浏览器中仍然可以访问,这是为什么呢?
因为 webpack 提前给我们注入了这些 nodejs 的全局变量,我们来找一下 webpack4 的源码。
node_modules/webpack/lib/node/NodeSourcePlugin.js:
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
const ParserHelpers = require("../ParserHelpers");
const nodeLibsBrowser = require("node-libs-browser");
module.exports = class NodeSourcePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
const options = this.options;
// 当 webpack.node 配置为 false 的时候关闭该插件
if (options === false) {
// allow single kill switch to turn off this plugin
return;
}
// 获取 nodepollyfill 的依赖地址
const getPathToModule = (module, type) => {
// 配置成 true 的话就去找到对应的 pollyfill 库
if (type === true || (type === undefined && nodeLibsBrowser[module])) {
if (!nodeLibsBrowser[module]) {
throw new Error(
`No browser version for node.js core module ${
module} available`
);
}
return nodeLibsBrowser[module];
// 配置成 mock 就简单模拟一下
} else if (type === "mock") {
return require.resolve(`node-libs-browser/mock/${
module}`);
// 配置成 empty 就返回 undeifned
} else if (type === "empty") {
return require.resolve("node-libs-browser/mock/empty");
} else {
return module;
}
};
// 修改变量为依赖引入
const addExpression = (parser, name, module,<

本文详细解析了Webpack中的node配置项,包括node.global、node.__filename和node.__dirname等,以及output.jsonpFunction配置在Webpack4和Webpack5中的应用。文章通过实例展示了如何避免全局变量污染,理解其工作原理,并给出了在Webpack5中去除jsonpFunction配置的解决方案。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



