我正在开发一个网络应用程序,其中包含应该使用dynamic imports延迟加载的小部件。 。 每个小部件都应该收到其单独的包,并且它们的依赖项只有在用户请求时才由浏览器获取。有一个异常(exception):流行的小部件应该包含在主包以及它们使用或扩展的库类中。下面您可以看到我想要实现的文件夹结构以及我想要的输出:
File Structure Desired chunk
src/
├── widgets/
│ ├── popular-widget/index.ts main
│ ├── edge-case-widget/index.ts edge-case-widget
│ └── interesting-widget/index.ts interesting-widget
├── library/
│ ├── Widget.ts main
│ └── WidgetFactory.ts main
└── index.ts main (incl. entry point)
dist/
├── edge-case-widget.app.js edge-case-widget
├── interesting-widget.app.js interesting-widget
└── main.app.js main (incl. entry point)
为了延迟加载小部件,我在 create
中使用以下表达式WidgetFactory
中的方法。这工作正常,小部件模块会被 Webpack 神奇地拾取。
const Widget = await import(`../widgets/${name}/index`)
我试图通过配置 optimization.splitChunks.cacheGroups
来解决代码分割挑战在 Webpack 中。提供test
函数我将模块分配到 library
或widgets
缓存组。
module.exports = {
entry: './src/index.ts',
[...]
optimization: {
splitChunks: {
cacheGroups: {
library: {
test: module => isInLibrary(module.identifier()),
name: 'library',
chunks: 'all',
minSize: 0
},
widgets: {
test: module => isWidgetBundle(module.identifier()),
name: module => widgetNameFromModuleId(module.identifier()),
chunks: 'async',
minSize: 0
}
}
}
}
}
我被困住了!
- 如何在小部件包中包含小部件依赖项?
- 使用
chunks: 'async'
关于library
缓存组使一些库类转到main
block 而其他人留在library
block 。为什么? - 当我使用
chunks: 'all'
时关于library
缓存组所有模块都正确地组合在其中,但我丢失了main
上的入口点 block 并获得一个空白页。怎么办? - 当我重命名
library
时将组缓存到main
我丢失了入口点,as documented here 。我不太明白为什么会出现这种情况以及我如何设法将main
结合起来入口点为library
打包成一个包。
希望您能帮助我了解我陡峭的 Webpack 学习曲线。
最佳答案
创建了一个简单的github repo具有您需要的配置。
- SplitChunks 配置(如果需要,请将
test
和name
函数更改为您的):
splitChunks: {
cacheGroups: {
widgets: {
test: module => {
return module.identifier().includes('src/widgets');
},
name: module => {
const list = module.identifier().split('/');
list.pop();
return list.pop();
},
chunks: 'async',
enforce: true
}
}
}
- 如果您希望PopularWidget位于
main
中,则不应动态导入它。使用常规import
语句。因为 webpack 总是会为任何动态导入创建一个新 block 。那么请看一下this文件。
import { Widget } from '../widgets/popular-widget';
export class WidgetFactory {
async create(name) {
if (name === 'popular-widget') return await Promise.resolve(Widget);
return await import(`../widgets/${name}/index`)
}
}
UPD
更改了配置以保留相关的 node_modules 和小部件。
我为新的小部件 block 创建编写了两个简单的函数。
这里的技巧是 module.issuer 属性,它意味着谁导入了这个文件。因此,函数 isRelativeToWidget
将为在小部件文件结构的任何深度导入的任何依赖项(无论是否为 node_modules)返回 true。
代码可查here .
结果配置:
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: false,
default: false,
edgeCaseWidget: getSplitChunksRuleForWidget('edge-case-widget'),
interestingWidget: getSplitChunksRuleForWidget('interesting-widget')
}
}
function isRelativeToWidget(module, widgetName) {
if (module.identifier().includes(widgetName)) return true;
if (module.issuer) return isRelativeToWidget(module.issuer, widgetName)
}
function getSplitChunksRuleForWidget(widgetName) {
return {
test: module => isRelativeToWidget(module, widgetName),
name: widgetName,
chunks: 'async',
enforce: true,
}
}
关于javascript - Webpack:将动态导入的模块拆分为单独的 block ,同时将库保留在主包中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58901229/