Javascript 动态组件查找导致Next.js捆绑包大小爆炸,如何解决? tldr:

Javascript 动态组件查找导致Next.js捆绑包大小爆炸,如何解决? tldr:,javascript,reactjs,webpack,next.js,Javascript,Reactjs,Webpack,Next.js,检查-common.js是否包含所有依赖项,即使在相应的页面上只使用了一个依赖项 http://localhost:3000/components/ComponentOne http://localhost:3000/components/ComponentTwo Livedemo: 更多详情: 我有一个应用程序(附带了一个非常简化的版本),根据用户的输入呈现不同的组件。通过组件映射查找要渲染的组件。 common.js包含切换器页面的所有依赖项是有意义的,在切换器页面中,两个组件都必须是可

检查-common.js是否包含所有依赖项,即使在相应的页面上只使用了一个依赖项

  • http://localhost:3000/components/ComponentOne
  • http://localhost:3000/components/ComponentTwo
Livedemo:

更多详情: 我有一个应用程序(附带了一个非常简化的版本),根据用户的输入呈现不同的组件。通过组件映射查找要渲染的组件。 common.js包含切换器页面的所有依赖项是有意义的,在切换器页面中,两个组件都必须是可访问的(因此它们的依赖项也是如此)。 但是单独的页面包含各自的其他依赖项是没有意义的

总结如下:

  • 我希望能够有一大组组件,可以根据用户的输入进行渲染。对于我的用例来说,序列化和反序列化()它们是不可行的,因为组件差异很大,需要不同的依赖关系
  • 我还想将每个组件呈现到它自己的静态生成页面,在那里我从数据库检索额外的SEO信息。然而,在这种情况下,我只想为手头的特定组件加载所需的依赖项
http://localhost:3000

选择ComponentOne会导致:
使用recharts.js

选择组件两个结果:
使用victory.js

问题 TLDR:Next的Webpack配置是将动态加载的组件分块为自己的分块,这可能会创建重复的或组合的分块依赖项

在您的示例中,我将组件1和2分别复制为组件3和4。然而,对于组件4(它是组件2的副本),我添加了一个额外的
时刻时区
依赖项。结果是一个具有重复的
victory pie
依赖项的独立块(它还为
victory
moment timezone
包导入了整个库):

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

但是,正如您在上面的chunk屏幕截图中所注意到的,即使第三方软件包没有跨多个路由重用/重新导入,您仍然有重复的依赖项(例如,上面屏幕截图中的大桃色块和灰绿色块都包含重复的
d3 scale
d3 time
d3 path
,等等依赖项块)

不幸的是,这是通过
next/dynamic
导入的组件的必要和预期行为(也适用于使用Webpack的dynamic
import
语句),因为它必须遍历每个动态导入组件的整个依赖关系图,并且(可能)将它们添加为自己的区块——换句话说,在动态加载组件的情况下,Webpack不知道运行时加载的是什么组件,因此它必须创建一个完整的区块,以便能够在请求时加载(即使其他组件可能共享相同的依赖项,它也不知道)。不仅如此,因为它不知道动态组件中导入/使用的是什么,所以它无法对依赖项进行树震动!因此,当您添加更多动态加载的组件时,会创建非常大且重复的数据块

解决方案 不幸的是,确实没有修复方法。即使我尝试手动将这些依赖项分离并分组为它们自己的独立块(以减少冗余/构建大小),该组件也不会再呈现。这是有意义的,当每个组件以一种方式分块成为主应用程序中自己的独立“应用程序”时

在这种情况下,最简单的解决方案是渲染静态图像,而不是动态加载的React组件(如视频的缩略图)

其他想法 我查看了Next的Webpack配置,并取得了一些进展。您可以创建自己的Webpack规则供Next使用,这将有助于减少某些块冗余;但即使如此,我仍然得到重复的块(主要来自
d3
共享依赖项).你可以试试。绝对不适合心脏虚弱的人,因为你会在一个黑洞里追赶一只兔子,你不会达到块分布的完美。也就是说,它确实有助于减小体型大小。。。

这里有一些初步的工作可以作为你的代码>下一个.CONFIG.JS文件:

next.config.js

module.exports={
网页包(配置,{isServer}){
/*添加客户端网页包优化规则,用于在构建期间拆分块*/
如果(!isServer){
config.optimization.splitChunks.cacheGroups={
…config.optimization.splitChunks.cacheGroups,
胜利:{
测试:/[\\/]节点单元模块[\\/](胜利派|胜利核心|胜利派\/es)[\\\/],
名称:“胜利”,
优先:50,
ReuseeExistingChunk:true,
},
记录:{
测试:/[\\/]节点单元模块[\\/](recharts | recharts标度)[\\\/],
优先事项:20,
名称:“recharts”,
ReuseeExistingChunk:true,
},
洛达斯:{
测试:/[\\/]节点单元模块[\\/](lodash)[\\\/]/,,
名称:“洛达斯”,
ReuseeExistingChunk:true,
优先事项:40,
},
};
}
/*将新配置返回到下一个*/
返回配置;
},
};
@Ra