
从Webpack到Snowpack,编译速度提高了十几倍。——TRPG引擎迁移注意事项
原文链接: http://moonrailgun.com/posts/74598ef5/
动机
TRPG引擎已经迭代了很长时间,项目变得非常臃肿。几分钟的完全编译,每次按Save,都会触发从10s到1m的增量编译,让我很痛苦。巨大的依赖性使得每次编译都涉及到很多文件和包,长时间的编译大大降低了开发效率和迭代速度。
优化方式
经过一段时间的调查,我选择了Snowpack作为解决方案。与Webpack不同的是,除了第一次完全编译之外,Snowpack的增量编译不会涉及巨大的node_modules文件夹,只会编译变更文件本身。即使依赖关系没有改变,下一次完全编译也会直接使用之前编译的文件缓存,而不需要等待node_modules的编译。
为什么这么快?这是因为Snowpack的实现本身就和设计理念有关。与Webpack相比,Snowpack利用了现代浏览器的模块系统,跳过了复杂模型之间的组织和编译过程,只专注于变更文件的编译,当然更快。
给雪原官方照张相,
snowpack的最小编译单位是文件,而webpack的最小编译单位是组块,组块需要额外计算,无论是编译后的部分还是编译后的组装部分。雪堆的设计逻辑自然决定了她的速度。
优化前(使用webpack):
完全编译:
增量编译:
完整的请求需要:个小时
优化后(使用snowpack):
完全编译:
增量编译:
(看不到编译时间,但是体感在1s以内,电脑运行其他应用时效果更显著)
完整的请求需要:个小时
使用http 1
使用http 2
以上测试是为了保证电脑处于空闲时间,存储和操作的内容是同一个文件
这个时间已经是正常运行最快的时间了。因为这个原因,我的MBR重启一次,强行清空交换空间,实际性能会更显著
因为文件依赖于浏览器的时间消耗,并且浏览器需要串行请求依赖,所以时间消耗会更长
不过,实际上还是用雪堆比较好。与webpack相比,可以大大节省计算机资源。编译webpack时,会占用大量计算机资源,影响其他操作
遇到的坑与解决方案
TRPG引擎是一个经典的网络包应用程序,它使用各种加载器。光学通用配置250行,各种优化配置,各种别名。等久了迭代累积配置,遇到很多问题和坑也就不足为奇了。
以下是我的问题及解决方法:
问题1:
条目文件使用HtmlwebpackPlugin编译的车把文件,而snowpack不支持车把文件作为条目
解决方案:重写一个特定于雪堆的条目文件。使用车把主要解决dll的问题,snowpack不需要处理这部分优化,直接跳过
问题2:
Snowpack加载文件策略不同于节点。同名的文件和文件夹将优先使用文件夹的index.js作为路径解析。具体现象请参考本次讨论: https://github.com/snowpackjs/snowpack/discussions/1320
解决方案:更改名称,使文件夹和文件名不重复。包括同名但大小写不同的问题,因为底层是节点的fs.stat实现,在区分大小写的系统下还是会被视为同名
问题3:
TRPG引擎不仅有web端,还有react-native端,react-native无法正常解析。我只想处理web端的开发环境,用snowpack优化开发体验
解决方案:不包括配置手动过滤
问题4:
不支持Tspath。虽然@snowpack/plugin-typescript可用,但不支持tspath。
解决方案:手动编写了一个自动解析逻辑,将其转换为相应的别名,并将其添加到配置中
问题5:
字体文件被引入css,但是不能正常加载。因为snowpack无法正确识别url指定的资源并打包它(webpack是使用css-loader实现的)
解决方案:脚本3360 {
mount : font ‘ : ‘ mount src/web/assets/font-to/main/font ‘,
},
问题6:
我不想因为一些特殊的写作而影响webpack的实现,但是snowpack不支持这种写作。比如引入由外部实现的配置,比如由DefinePlugin实现的process.env(在snowpack中必须使用import.meta.env),以及使用require
解决方案:我实现了一个snowpack-plugin-replace插件,用我想要的代码替换所有这些东西。具体用途如下: [
‘ snowpack-plugin-replace ‘,
{
列表: [
{
from: /process\。环境/g,
to: ‘import.meta.env ‘,
},
{
from: `require(‘././package.json’).version `,
到: ”0.0.0 ‘ ‘,
},
{
from : ` const Resbundle=require(‘ i18 next-resource-store-loader!/langs/index . js ‘);`,
to:“从导入resBundle”。/langs/zh-CN/translation.json ‘ ‘,
},
{
“from:”从“Config”导入配置;
to : ` const Config=$ { JSON . stringify({
sentry: require(‘config ‘)。get(‘sentry ‘),
})};`,
},
],
},
],
问题7:
汇总引发了无法解决此问题的警告
解决方案:使用上下文指向窗口来删除警告安装选项: {
滚动: {
context: ‘窗口’,
},
},
问题8:
Snowpack打包目标路径与原始生成文件夹冲突
解决方案:将输出目录修改为。snowpack并添加文件夹devOptions: {
out: ‘。雪堆’,
},
问题9:
将出现使用@snowpack/plugin-typescript内部包的全局变量声明
重复声明错误
解决方案: tsconfig ‘ Skiplibccheck ‘ : true
问题10:
现有的依赖需要@ babel/plugin-transform-runtime提供的助手作为全局依赖
检查解决方案:以使用再生器功能,手动安装再生器-运行时,并在包之前导入“再生器-运行时/运行时”。
问题11:
部分依赖,其中部分代码使用request作为引入方法,但是snowpack不能正确处理request
查看解决方案:后,发现全部修改完毕。升级取决于最新版本
问题12:
使用较少的导入逻辑无法正常工作,这是由snowpack的具体实现决定的。
暂时无法解决,用snowpack-plugin-replace替换为css文件导入作为临时解决方案,见讨论: Github。
总结
Snowpack作为一种新的包装工具,目前还不完善,功能也没有webpack丰富完整。但其新的包装设计对于具有一定规模的前端应用来说是极好的。可以大大提高开发效率。这是一个很好的解决方案。当然最后的输出还是需要用webpack来优化。毕竟,当前浏览器对本机模块的支持还没有达到理想的覆盖水平。https://caniuse.com/es6-module
最后,这是我最后一次提交的pr