webpack-require-from v 1.8.1
允许为获取动态导入配置路径或 URL 的 webpack 插件。
在运行时控制动态导入的路径/URL
- 支持 webpack 5,4,3,2
- 支持 web-worker 加载
- 生产环境OK。
- 无依赖。
- 轻量。
- 测试完备。
为什么要在运行时更改动态道路的路径?
Webpack 允许使用[require.ensure][require.ensure]
或dynamic importimport()
来自动分割和加载代码。当你的主包在浏览器中运行时,模块以“按需”方式获取。
Webpack 根据配置中的config.output.publicPath
从静态 URL 加载模块(包块)。
有些时候您需要在运行时控制模块(包块)的加载,举个例子:
- 包块(chunks)托管在 CDN 上。
- 不同的环境使用的 URL 来加载静态资源(生产环境,测试环境等)。
- 您的
index
文件来自不同的域名/端口。 - 您需要从不同的域名动态加载预编译文件。
- 您需要从 CDN 加载第三方的 web worker。
如何使用?
// webpack.config.js
const WebpackRequireFrom = require("webpack-require-from");
const webpackRequireFromConfig = (module.exports = {
output: {
publicPath: "/webpack/"
},
plugins: [
new WebpackRequireFrom({
// 参见下方配置
})
]
});
2
3
4
5
6
7
8
9
10
11
12
配置
如果没有传入任何配置项,那么该插件将默认使用[config.output.publicPath](https://webpack.js.org/guides/public-path/#on-the-fly)
。
path
为动态加载模块设置路径。您传入的值将在动态导入代码块时替换config.output.publicPath
。
举个例子,如果默认的 URL 是https://localhost
,包名是0.js
同时配置对象为{path: "customPath/" }
,那么代码块将从https://localhost/customPath/0.js
获取。
注意:
path
/methodName
/variableName
这三个配置项是互斥的,不可同时使用。
variableName
variableName
是全局定义的变量,它会在运行时进行计算,variableName
是变量的名称,带有字符串的值表示路径/URL,它们用于动态导入代码块。
举个例子,如果默认的 URL 是https://localhost
,包名是0.js
同时配置对象为{variableName: "chunkURL" }
,同时window.chunkURL
将定义为:
window.chunkURL = "https://app.cdn.com/buildXXX/"
代码块将从https://app.cdn.com/buildXXX/0.js
获取。
methodName
全局定义的方法名,它将在运行时调用,该方法应该返回动态导入的代码块的路径/URL。
举个例子,如果默认的 URL 是https://localhost
,包名是0.js
,配置项为{methodName: "getChunkURL" }
,同时window.getChunkURL
将定义为:
window.getChunkURL = function() {
if (true) {
// 使用任何条件来选择URL
return "https://app.cdn.com/buildXXX/";
}
};
2
3
4
5
6
代码块将从https://app.cdn.com/buildXXX/0.js
获取。
如果与replaceSrcMethodName
一起使用,chunk URL 将首先被 window[methodName]
修改,然后修改的值作为一个参数传递给window[replaceSrcMethodName]
函数。
注意:
path
/methodName
/variableName
这三个配置项是互斥的,不可同时使用。
注意: 该方法应该在全局命名空间中定义,并且应该在调用
require.ensure
或import()
之前定义。请参见下面的例子:
replaceSrcMethodName
全局定义的方法名,它将在运行时调用,该方法接收动态引入的代码块的完整URL作为其参数并返回新 URL 的字符串。
举个例子,如果默认的 URL 是https://localhost
,包名是0.js
和common.js
,配置项为{replaceSrcMethodName: "replaceSrc" }
,同时window.replaceSrc
将定义为:
window.replaceSrc = function(originalSrc) {
if (originalSrc.match(/common/)) {
// 对指定的 chunk 进行重命名
return originalSrc.replace(/common/, "static");
}
return originalSrc;
};
2
3
4
5
6
7
代码块将从https://localhost/0.js
和https://localhost/static.js
获取。
如果同时使用了methodName
或variableName
,chunk URL 将首先被 window[methodName]
修改亦或是修改为window[variableName]
,然后修改的值作为一个参数传递给window[replaceSrcMethodName]
函数。
注意: 该方法应该在全局命名空间中定义,并且应该在调用
require.ensure
或import()
之前定义。
supressErrors
默认值false
。当无法检测到您在replaceSrcMethodName
、methodName
或variableName
中定义的方法名时,插件将调用console.error
。打开该配置项将压制错误信息。
全局方法和变量
当您的 JS 代码在浏览器中执行时,您作为variableName
、methodName
或replaceSrcMethodName
值的方法/变量名应该在第一次调用require.ensure()
或import()
执行之前设置。
方法的返回值将用于构建获取资源的 URL。
例如,在执行主包之前我们可以定义一个veryFirst
的全局方法:
const window.veryFirst = function () {
console.log("I am very first!");
}
2
3
您可以使用单独的文并使用 webpack 的配置项:
// 文件名: veryFirst.js
const window.veryFirst = function () {
console.log("I am very first!");
}
// webpack.config.js
module.exports = {
entry: {
['./veryFirst.js', './index.js']
}
}
2
3
4
5
6
7
8
9
10
11
另一个方法是在服务端构建时将veryFirst
定义为index.html
的一部分:
// 文件名:server/app.js
app.get("/", (req, res) =>
res.render("views/index", {
cdnPath: "https://qa.cdn.com/|https://prod.cdn.com/"
})
);
2
3
4
5
6
<!-- 文件名: views/index.ejs -->
<html>
<script>
const baseCDN = "<%= cdnPath %>";
window.veryFirst = function () {
console.log(`${baseCDN}/js/`);
}
</script>
</html>
2
3
4
5
6
7
8
9
Web Workers
使用replaceSrcMethodName
提供一个修改 web-worker 加载路径的方法。该方法必须是全局可用的,并且必须在 web-worker 内的import()
调用之前定义。
/* webpack.config.js */
// ...
module: {
rules: [
{
test: /worker\.js$/,
use: {
loader: `worker-loader`
}
}
]
},
plugins: [
new HtmlWebpackPlugin(),
new RequireFrom({
replaceSrcMethodName: "getSrc"
})
]
// ...
/* worker.js */
require("./globals.js");
import("./worker-module.js").then(workerModule => {
workerModule.default();
console.log("loaded workerModule");
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
详细信息
该插件允许更改加载 web-worker 的路径。
为达成这个需求,使用了[worker-loader][worker-loader]
加载器。该加载器使用[importScripts][importScripts]
从您的 web-worker 中动态加载模块,并支持跨域web worker。更具体地说:
- 创建一个新的 webpack 入口,它只包含
new Worker(workerURL)
,而workerURL
是您的主要 webworker 模块。 - 用 webpack 运行时工具增强您的 webworker 主模块。
- 使用
importScripts
在 webworker 上下文中动态加载新模块(从而避免跨域限制)。
该插件重写了importScript
并调用您在replaceSrcMethodName
中定义的方法。您提供的方法将在调用importScripts
之前被调用,所需的模块路径作为单个参数。
您可以在这里找到本插件联动 web worker 的应用实例。
排忧解难
${methodName}不是函数,或者在运行时不可用。
- 确保
webpack.config.js
中的方法名与在全局window
对象中定义的方法名匹配。 - 确保在第一次调用
require.ensure()
或import()
之前定义该方法。
配置
methodName
或path
中的一个,不要两者都配置。
path
和methodName
是互斥的,不能一起使用,随便使用一个就行。
${methodName} 不返回字符串。
- 当使用
replaceSrcMethodName
配置项时,调用window[replaceSrcMethodName]
的结果将被验证——它应该被定义并且是一个字符串。 - 确保您从
window[replaceSrcMethodName]
返回一个字符串值。