动机

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

优化方式

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

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

Snowpack官方的一张图来说:

 
1.png

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

优化前(使用webpack):

全量编译:

 
2.jpg

增量编译:

 
3.jpg

全量请求用时:

 
6.jpg

优化后(使用snowpack):

全量编译:

 
4.jpg

增量编译:

 
5.jpg

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

全量请求用时:

  • 使用http1

     
    7.jpg
  • 使用http2

     
    8.jpg

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

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

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

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

遇到的坑与解决方案

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

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

  • 问题1:

    • 入口文件使用的是HtmlwebpackPlugin编译的handlebars文件,而snowpack不支持handlebars文件作为入口
    • 解决方案:重写一个snowpack专用的入口文件。使用handlebars主要解决的是dll的问题,snowpack不需要处理这部分的优化因此直接跳过
  • 问题2:
    • snowpack加载文件策略与node不同。有同名文件和文件夹会优先使用文件夹的index.js作为路径解析。具体看现象可以参考这个讨论: https://github.com/snowpackjs/snowpack/discussions/1320
    • 解决方案:改名字,让文件夹与文件名不会出现重复。包括同名但是大小写不同的问题,因为底层是nodefs.stat实现,在大小写敏感的系统下依旧会视为同名
  • 问题3:
    • TRPG Engine不但有web端,还有react-native端,而react-native是无法被正常解析的。我只想要处理web端的开发环境使用snowpack优化开发体验
    • 解决方案: exclude配置手动过滤
  • 问题4:
    • tspath不支持,虽然有了@snowpack/plugin-typescript但是不支持tspath。
    • 解决方案: 手动写了一个自动解析的逻辑将其变成对应的alias加到配置上
  • 问题5:
    • 在css中引入了字体文件,但是无法正常加载。因为snowpack无法正确识别url指定的资源并将其打包(webpack是使用css-loader来实现的)
    • 解决方案:
      scripts: {
      'mount:font': 'mount src/web/assets/fonts --to /main/fonts',
      },
  • 问题6:
    • 对于一些特殊的写法我不想影响webpack的实现但是snowpack不支持这种写法。比如使用externals实现的配置引入, 比如DefinePlugin实现的process.env(在snowpack中必须使用import.meta.env), 再比如require的使用
    • 解决方案: 我实现了一个snowpack-plugin-replace插件用于将这些东西全部替换成我想要的代码。具体使用如下:
      [
      'snowpack-plugin-replace',
      {
      list: [
      {
      from: /process\.env/g,
      to: 'import.meta.env',
      },
      {
      from: `require("../../package.json").version`,
      to: '"0.0.0"',
      },
      {
      from: `const resBundle = require("i18next-resource-store-loader!./langs/index.js");`,
      to: 'import resBundle from "./langs/zh-CN/translation.json"',
      },
      {
      from: 'import Config from "config";',
      to: `const Config = ${JSON.stringify({
      sentry: require('config').get('sentry'),
      })};`,
      },
      ],
      },
      ],
  • 问题7:
    • rollup抛出无法解析this的警告
    • 解决方案: 使用context指向window来移除警告
      installOptions: {
      rollup: {
      context: 'window',
      },
      },
  • 问题8:
    • snowpack打包目标路径与原有的build文件夹冲突
    • 解决方案: 修改输出目录为.snowpack并在gitignore中添加该文件夹
      devOptions: {
      out: '.snowpack',
      },
  • 问题9:
    • 使用@snowpack/plugin-typescript内部包对全局变量的声明会出现重复声明的报错
    • 解决方案: tsconfig"skipLibCheck": true
  • 问题10:
    • 现有的依赖需要@babel/plugin-transform-runtime提供的helpers作为全局依赖
    • 解决方案: 经检查是用到了regenerator功能,手动安装regenerator-runtime并在包前引入import 'regenerator-runtime/runtime';
  • 问题11:
  • 问题12:
    • 在使用less的import逻辑无法正常运行,这是由于snowpack的具体实现决定的。
    • 暂时无法解决,使用snowpack-plugin-replace将其替换为css文件导入作为临时解决方案, 见讨论: Github 使用@snowpack/plugin-run-script插件将其手动编译后放在公共文件中。可以参考这个commit

总结

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

最后这是我最后提交的pr

从 Webpack 到 Snowpack, 编译速度提升十倍以上——TRPG Engine迁移小记的更多相关文章

  1. 如何将 iOS 工程打包速度提升十倍以上

    如何将 iOS 工程打包速度提升十倍以上   过慢的编译速度有非常明显的副作用.一方面,程序员在等待打包的过程中可能会分心,比如刷刷朋友圈,看条新闻等等.这种认知上下文的切换会带来很多隐形的时间浪费. ...

  2. Java动态编译优化——提升编译速度(N倍)

    一.前言 最近一直在研究Java8 的动态编译, 并且也被ZipFileIndex$Entry 内存泄漏所困扰,在无意中,看到一个第三方插件的动态编译.并且编译速度是原来的2-3倍.原本打算直接用这个 ...

  3. 使用Apache Spark 对 mysql 调优 查询速度提升10倍以上

    在这篇文章中我们将讨论如何利用 Apache Spark 来提升 MySQL 的查询性能. 介绍 在我的前一篇文章Apache Spark with MySQL 中介绍了如何利用 Apache Spa ...

  4. 阿里云maven仓库地址,速度提升100倍

    参照:https://www.cnblogs.com/xxt19970908/p/6685777.html maven仓库用过的人都知道,国内有多么的悲催.还好有比较好用的镜像可以使用,尽快记录下来. ...

  5. 多伦多大学&NVIDIA最新成果:图像标注速度提升10倍!

    图像标注速度提升10倍! 这是多伦多大学与英伟达联合公布的一项最新研究:Curve-GCN的应用结果. Curve-GCN是一种高效交互式图像标注方法,其性能优于Polygon-RNN++.在自动模式 ...

  6. numba,让python速度提升百倍

    python由于它动态解释性语言的特性,跑起代码来相比java.c++要慢很多,尤其在做科学计算的时候,十亿百亿级别的运算,让python的这种劣势更加凸显. 办法永远比困难多,numba就是解决py ...

  7. iOS进阶--将项目的编译速度提高5倍

    前言 作为开发团队的负责人,最近因为在快速迭代开发新功能,项目规模急速增长,单个端业务代码约23万行,私有库约6万行,第三方库代码约15万行,单个客户端的代码行数约60万.现在打包一次耗时需要11~1 ...

  8. Elasticsearch聚合优化 | 聚合速度提升5倍

    https://blog.csdn.net/laoyang360/article/details/79253294 1.聚合为什么慢?大多数时候对单个字段的聚合查询还是非常快的, 但是当需要同时聚合多 ...

  9. 使用ccache大幅度加速gcc编译速度至少1倍以上(不需要修改任何编译选项)

    因为我们整个项目都是使用c++开发的,生成的so足有50M,原来编译一遍要三五分钟,一个针对oracle,一个针对mysql,整个轮回下来这部分就要10来分钟,加上代码上传.翻译,一轮配管打包下来二三 ...

随机推荐

  1. go 接口实现

    package main import ( "fmt" ) // 定义接口 type Beahavior interface { Run() string Eat(thing st ...

  2. 干掉hao123的第n+1种方法

    最近看见我小弟无精打采的样子,问他怎么了,他说所有浏览器主页被hao123流氓劫持了,嚯,这回流氓碰同行--没辙. 我说这多大点事,百毒一下,以毒攻毒.于是便有了下面的这些方法: 适合小白: 第一种: ...

  3. 1024|推荐一个开源免费的Spring Boot教程

    2020-1024=996! 今天,星期六,你们是否加班了?我反正加了!早上去公司开了一早上会,中午回家写下了这篇文章. 今天,我要推荐一个开源免费的Spring Boot项目,就是我最近日更的Spr ...

  4. c++ 获取当前时间周初凌晨时间戳(获取当前时间周一凌晨时间戳)

    UINT64 GetWeekBeginTime(){ time_t t; t = time(0); tm* t_tm = localtime(&t); t_tm->tm_hour = 0 ...

  5. 2020-2021-1 20209306 《linux内核原理与分析》第三周作业

    目录 一.实验:完成一个简单的时间片轮转多道程序内核代码 二.学习总结 1.堆栈相关的寄存器 2.堆栈操作 3.其他关键寄存器 4.用堆栈来传递函数的参数 5.了解了函数如何传递返回值,堆栈还提供局部 ...

  6. Kitty基于Spring Boot、Spring Cloud、Vue.js、Element实现前后端分离的权限管理系统

    源码地址:https://gitee.com/liuge1988/kitty 软件架构 后端架构 开发环境 IDE : eclipse 4.x JDK : JDK1.8.x Maven : Maven ...

  7. 痞子衡嵌入式:基于恩智浦i.MXRT1010的MP3音乐播放器(RT-Mp3Player)设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1011的MP3播放器参考设计. i.MXRT1011是恩智浦i.MXRT四位数系列的入门型号,虽然是入门级,可也是50 ...

  8. Redis缓存雪崩和穿透的解决方法

    转载自: https://blog.csdn.net/qq_35433716/article/details/86375506 如何解决缓存雪崩?如何解决缓存穿透?如何保证缓存与数据库双写时一致的问题 ...

  9. win10 hyper-v的开启和关闭

    一.开启: 1. 控制面板->程序->启用或关闭Windows功能,Windows功能中勾选hyper-v功能 2. powershell中使用管理员权限运行下面的命令 bcdedit / ...

  10. C# 实现十六进制Unicode编码字符串转换为汉字

    网上找了几个方法,但是运行之后会报错,提示要解析的字符串格式不正确.然后我猜想可能是传入的字符串 \u60a8\u4eca\u65e5\u5df2\u7b7e\u5230 中带"\" ...