从 Webpack 到 Snowpack, 编译速度提升十倍以上——TRPG Engine 迁移小记

2020-10-21 09:43:52 +08:00
 moonrailgun

原文链接: http://moonrailgun.com/posts/74598ef5/

动机

TRPG Engine经过长久以来的迭代,项目已经显得非常臃肿了。数分钟的全量编译, 每次按下保存都会触发一次10s1m不等的增量编译让我苦不堪言, 庞大的依赖使其每一次编译都会涉及很多文件和很多包,长时的编译时间大大降低了开发效率与迭代速度。

优化方式

经过一段时间的考察,我选择了Snowpack作为解决方案。与Webpack不同的是,除了第一次的全量编译以外,Snowpack的增量编译不会涉及到庞大的node_modules文件夹, 准确来说只会编译变更文件本身。甚至于如果没有对依赖进行变更,下次的全量编译会直接动用之前编译的文件缓存,不需要花时间等待node_modules的编译。

为什么会这么快?这是由于Snowpack本身的实现与设计哲学有关的。相比Webpack, Snowpack利用了现代浏览器的本身的module系统,跳过复杂的模型之间的组织编译过程而只关注于变更文件本身的编译,这样当然快了。

Snowpack官方的一张图来说:

snowpack的最小编译单位是文件,而webpack的最小编译单位为chunk, 而chunk还需要额外的计算, 不论是编译部分还是编译后的组装部分。snowpack 的设计逻辑天生决定了她的速度。

优化前(使用webpack):

全量编译:

增量编译:

全量请求用时:

优化后(使用snowpack):

全量编译:

增量编译:

(看不到编译用时,但是体感在 1s 内. 而且该效果在电脑运行其他应用时更加显著)

全量请求用时:

以上测试是保证电脑在空闲时间,且保存与操作内容为同一文件

该用时已经是平时操作的最快时间,为此我的 MBR 重启了一次强制清空了 swap 空间, 实际表现会更加显著

因为文件依赖于浏览器的耗时,而浏览器需要串行请求依赖,因此耗时会更加长

但实际使用中使用 snowpack 会更加优秀。因为其相比 webpack 会大大节约电脑资源。在 webpack 编译时会占用大量的电脑资源,会影响到其他操作

遇到的坑与解决方案

TRPG Engine算是非常经典的Webpack应用了, 使用了各种 Loader 。光通用配置就有 250+行,各种优化配置,各种 alias 。等等长时间迭代积攒下来的配置,因此毫不意外的会遇到很多问题与坑。

以下是我遇到的问题与解决方案:

总结

Snowpack 虽然作为一个新兴的打包工具,目前尚不是非常完善, 功能也没有 webpack 这样丰富与齐全。但是它的新的打包设计对于有一定规模的前端应用还是非常优秀的。能极大提升开发效率。不失为一种好的解决方案。当然最后输出还是需要使用 webpack 对其进行一定的优化,毕竟原生的 module 支持目前浏览器的支持度还没有达到覆盖一个理想的地步https://caniuse.com/es6-module

最后这是我最后提交的pr

5073 次点击
所在节点    Node.js
16 条回复
Immortal
2020-10-21 09:58:49 +08:00
说实话看到下面这么多遇到的问题 还是保持观望
不过涨姿势了 之前只知道 esbuild 才知道还有 Snowpack
love
2020-10-21 10:09:07 +08:00
上次我也一顿猛操换成这个,碰到一堆问题,后来又退回去了。印象中还有 commonjs 格式导出的模块也是不能用的。感觉还是要等个一年各个模块兼容性上去之后再换比较合适。
felixin
2020-10-21 10:20:03 +08:00
这个就没有 typescript 类型检查了吧?
codermagefox
2020-10-21 10:50:11 +08:00
Webpack 换 Parcel 那一波已经冲过了.结果很失望.

现在碰到所有新东西都先观望观望了.
moonrailgun
2020-10-21 10:57:04 +08:00
@felixin 有的。可以选择 babel 插件的 ts 模块或者 typescript 插件(只能二选一)

使用 typescript 插件的的话其实就是后台运行一个 tsc 的 watch 模式
moonrailgun
2020-10-21 11:00:05 +08:00
@codermagefox parcel 本质没有太大的变化,反而少了 webpack 的大量配置带来的优势与劣势。

我换 snowpack 目的是为了提升开发体验。我现在按一次保存按钮电脑十几秒不能动 ide 也没有提示。算是比较有目的性的。

生产环境还是会使用 webpack 进行代码的优化与编排。目前尚没有到可以完全替换的地步
codermagefox
2020-10-21 11:05:30 +08:00
@moonrailgun #6 嗯.我一向认同新工具的优势,但是大部分的成熟程度都没有到支撑大型项目的程度.我个人博客用 Gatsby,但是公司项目我连 TS 都没上.不想挖坑给自己填,所以还是算了
moonrailgun
2020-10-21 11:06:14 +08:00
@love 几个月前我也试过。也是一堆问题,改了改源码也没法解决差太多了,就没继续搞。最近重新弄了一下发现还是有点盼头的。虽然遇到一堆问题但是基本上都解决或者找到替代方案。

做大动作前一定要分分支,这样万一搞不成直接扔了就好了
moonrailgun
2020-10-21 11:11:12 +08:00
@codermagefox 公司项目还是谨慎一点比较好。毕竟不同人不断迭代下肯定会出现很多奇奇怪怪的 magic,如果是个人项目能够控制全局,我觉得还是可以考虑实际根据情况尝试一下的。
nnnToTnnn
2020-10-21 13:39:32 +08:00
和 webpack5 比较怎么样?
zy445566
2020-10-21 13:45:41 +08:00
我也是用从 webpack 换成了 rollup,速度也是快了很多,https://github.com/zy445566/before-server/commit/4d61a3b0c8464eb8d08605178fdaebc703db7599
hewelzei
2020-10-21 16:20:32 +08:00
有大量库及其依赖库使用 CommonJS 导入导出,这块是最难解决的。就算有一直活跃的库修改为 ESModule, 保不齐上级深层的某个依赖万年不修,依旧用的 CommonJS,那 Snowpack 就没法用了。
yl14786922106
2020-10-21 16:29:30 +08:00
vue3 的话可以直接 vite 了 不过踩了这么多坑 可以收藏 以后 自己玩的时候 可以来看看
moonrailgun
2020-10-21 17:10:38 +08:00
@hewelzei
snowpack 内部通过 rollup 来实现打包。通过 commonjs-plugin 实现对 commonjs 格式的兼容

具体见: https://github.com/snowpackjs/snowpack/blob/d90a1fb8a080bfe32e7283d87063381cd97f48bb/esinstall/src/index.ts#L383-L387

不过实际使用过程中如果依赖使用了行内 require 会无法正常执行。我的实际 case 中遇到了两处。翻阅代码发现已经被修复了因此升级就解决了
hewelzei
2020-10-22 10:35:06 +08:00
@moonrailgun 我遇到一处行内 require 的问题,查看依赖代码,发现不予解决,那就无解了。有这类问题的肯定不止一个包,,而且这问题看似简单,一旦出现,你的开发环境就起不来了。
https://github.com/antvis/g/pull/598
moonrailgun
2020-10-23 11:20:35 +08:00
@hewelzei 这个不是行内 require 的问题,而是在 esmodule 中使用 commonjs 的语法引入了一个 json 内容的问题。

按照标准来说这种行为属于混用,统一使用 esmodule 或者统一使用 commonjs 都不会出现这个问题。

我觉得不支持标准行为属于正常操作。本质上来说内部的 rollup 没有处理这种情况,snowpack 自身也不会去处理,也就 webpack 这种大而全的会考虑方方面面兼容一切 case——这也是 webpack 显得臃肿的原因

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/716942

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX