问题
TLDR:Next 的 Webpack 配置将动态加载的组件分块作为自己的块,这可能会创建重复或组合的块依赖项。
在您的示例中,我将组件 1 和 2 分别复制为组件 3 和 4。但是,对于组件 4(它是组件 2 的副本),我添加了一个额外的moment-timezone
依赖项。结果是一个具有重复victory-pie
依赖项的分离块(它还为包和包导入了整个库):
victory
moment-timezone

解释
即使两个 3rd 方图表包之间存在相当多的依赖共享(主要是两者共享d3
依赖),如果组件正在重用恰好具有共享依赖并跨多个路由动态加载的 3rd 方库,Webpack 可能会尝试将这些 3rd 方块组合成一个组合块:
而不是预期的两个或更多块:

但是,正如您在上面的块截图中注意到的那样,即使第 3 方包没有在多个路由中重用/重新导入,您仍然有重复的依赖项(例如,大桃子和柠檬绿色块在上面的屏幕截图包含重复的d3-scale
、d3-time
、d3-path
等依赖块)。
不幸的是,这是通过next/dynamic
(也适用于使用 Webpack 的动态import
语句)导入的组件的必要和预期行为,因为它必须遍历整个每个动态导入的组件的依赖图并(可能)将它们添加为自己的块——换句话说,在动态加载组件的情况下,Webpack 不知道运行时正在加载什么组件,因此它必须创建一个整个块以便能够根据请求加载(即使其他组件可能共享相同的依赖项,它也不会知道)。不仅如此,因为它不知道动态组件中正在导入/使用什么,所以它不能摇树依赖!因此,当您添加更多动态加载的组件时,这会创建非常大且重复的块。
解决方案
不幸的是,真的没有办法解决。即使我尝试手动将这些依赖项分离和分组为它们自己单独的块(以减少冗余/构建大小),该组件也将不再呈现。这是有道理的,当每个组件以某种方式在主应用程序中成为自己独立的“应用程序”时。
在这种情况下,最简单的解决方案是渲染静态图像而不是动态加载的 React 组件(如视频的缩略图)。
其他想法
我查看了 Next 的 Webpack 配置,并取得了一些进展。您可以创建自己的 webpack splitChunks规则供 Next 使用,这将有助于减少一些块冗余;但是,即便如此,我仍然收到重复的块(主要来自d3
共享依赖项)。你可以试试看。绝对不适合胆小的人,因为您将在一个黑洞中追逐一只兔子,并且您将无法实现块分布的完美。也就是说,它确实有助于减少构建尺寸......

以下是用作next.config.js
文件基础的一些初步工作:
下一个.config.js
module.exports = {
webpack(config, { isServer }) {
/* adds client-side webpack optimization rules for splitting chunks during build-time */
if (!isServer) {
config.optimization.splitChunks.cacheGroups = {
...config.optimization.splitChunks.cacheGroups,
victory: {
test: /[\\/]node_modules[\\/](victory-pie|victory-core|victory-pie\/es)[\\/]/,
name: "victory",
priority: 50,
reuseExistingChunk: true,
},
recharts: {
test: /[\\/]node_modules[\\/](recharts|recharts-scale)[\\/]/,
priority: 20,
name: "recharts",
reuseExistingChunk: true,
},
lodash: {
test: /[\\/]node_modules[\\/](lodash)[\\/]/,
name: "lodash",
reuseExistingChunk: true,
priority: 40,
},
};
}
/* return new config to next */
return config;
},
};