我正在用新的(react)代码部分更新现有的Web应用程序,并使用webpack将所有内容捆绑在一起以供生产使用。因为现有的HTML页面(实际上是XML转换成HTML)已经存在,所以我不能使用HtmlWebpackPlugin
生成的index.html
。
我想实现的是webpack生成一个小的runtime.bundle.js
,它将动态加载其他生成的块(main.[contenthash]
和vendor.[contenthash]
),而不是将这些条目作为script
标签添加到index.html
。这样,runtime.bundle.js
可以设置为nocache
,而其他大块可以由浏览器缓存,并在代码更改时正确获取。
例如,下面是生成的index.html
的body块,请注意注解:
<html>
<head>...</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="runtime.bundle.js"></script>
<!-- I want these two files below not injected as script tags,
but loaded from the runtime.bundle.js file above -->
<script type="text/javascript" src="vendors.31b8acd750477817012d.js"></script>
<script type="text/javascript" src="main.1e4a456d496cdd2e1771.js"></script>
</body>
</html>
字符串
运行时文件已经加载了一个不同的块,该块是通过以下代码从JS动态导入的:
const App = React.lazy(() => import(/* webpackChunkName: "modulex" */ './App'));
型
这将在runtime.bundle.js
中创建以下代码段
a = document.createElement('script');
(a.charset = 'utf-8'),
(a.timeout = 120),
i.nc && a.setAttribute('nonce', i.nc),
(a.src = (function(e) {
return (
i.p +
'' +
({ 1: 'modulex' }[e] || e) +
'.' +
{ 1: '0e0c4000d075e81c1e5b' }[e] +
'.js'
);
型
那么,vendors
和main
块也能实现同样的效果吗?
我能想到的唯一其他替代解决方案是使用WebpackManifestPlugin
生成manifest.json
,并使用它将块注入到已经存在的HTML文件中。
3条答案
按热度按时间j9per5c41#
最后,我通过创建一个脚本来解决这个问题,该脚本使用
manifest.json
(由WebpackManifestPlugin
生成)来生成一个runtime.js
脚本,该脚本将在页面加载时动态加载块,并将此runtime.js
插入到index.html
的头部。这可以从npm scripts
部分使用tasksfile npm包调用。在webpack配置中,将插件添加到插件数组中:
字符串
我有下面的外部JS文件,我可以使用tasksfile npm包从我的
npm scripts
调用,它被配置为调用此函数:型
该函数基本上循环了
manifest.json
中的所有JS条目文件。然后创建脚本标记,将这些条目作为
src
属性,然后将这些脚本标记作为子项添加到document.head
(触发条目的加载)。最后,将此脚本保存到runtime.js
文件中,并存储在构建目录中。现在你可以将这个
runtime.js
文件包含到你的html文件中,如果所有的路径都设置正确,你的块应该会被加载。3j86kqsm2#
HtmlWebpackPlugin提供了一个
chunks
选项,您可以使用它来选择性地包含webpack配置的entry
对象中的某些条目。使用它,您可以将自定义脚本中的大部分逻辑简化为单独的src/dynamic-load.js
文件,只需将其添加到插件配置中:字符串
(另一个
chunks
用法的例子可以在这里看到)。甚至它们内置的
templateParameters
也可能允许您将构建输出文件名放入变量中,并在dynamic-load.js
中读取它们。您必须为它创建自己的模板,但这可能是一条路线。您甚至可以看到他们建议的templateParameters
示例是如何做到的。如果这不起作用,您可以通过webpack本身通过
afterEmit
钩子获取捆绑的输出文件名,然后将其输出到dynamic-load.js
将调用的JSON文件中。要点如下所示,但此时,您正在做与WebpackManifestPlugin
相同的事情。型
最后一点:WebpackManifestPlugin实际上是一个assets manifest,不会产生correct manifest.json。他们应该将默认文件名更新为
assets-manifest.json
,但我猜还没有人向他们指出这一点。osh3o9ms3#
https://github.com/webpack/webpack/issues/11816#issuecomment-716402552
字符串
巴里快跑。RUNNNNN...用这个超级强大的脚本!