动机

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. 每天一个linux命令:ps命令

      Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进 ...

  2. Centos6.X 手动升级gcc

    操作环境 CentOS6.5 64bit,gcc原版本为4.4.7,不能支持C++11的特性,所以需要升级 [root@zengxj ~]# wget http://ftp.gnu.org/gnu/g ...

  3. 第三章 TCP/IP 模型

    一.产生背景 1.伴随着计算机网络的飞跃发展,各大厂商根据自己的协议生产出了不同的硬件和软件 2.为了实现网络设备间的互相通讯,ISO和IEEE相继提出了OSI参考模型及其TCP/IP模型 二.TCP ...

  4. linux硬盘分区及挂载

    今天买的一台服务器发现其硬盘容量与购买界面的描述不符,于是我去问了客服才知道有一块硬盘需要自己挂载,所以记录自己硬盘分区以及挂载操作得此文. 测试环境 ​ 由于时间限制,本人仅在centos 8下测试 ...

  5. # ThreeJS学习7_裁剪平面(clipping)

    ThreeJS学习7_裁剪平面(clipping) 目录 ThreeJS学习7_裁剪平面(clipping) 1. 裁剪平面简介 2. 全局裁剪和局部裁剪 3. 被多个裁剪平面裁剪后 4. 被多个裁剪 ...

  6. 刷题不应该刷leecode 应该刷oj

    因为leecode有很多题目 表述不清 意义不明 最关键的是 leecode压根不规定输入输出的格式 这个完全不是竞赛的风格 这样会养成很多坏习惯

  7. 论文解读《ImageNet Classification with Deep Convolutional Neural Networks》

    这篇论文提出了AlexNet,奠定了深度学习在CV领域中的地位. 1. ReLu激活函数 2. Dropout 3. 数据增强 网络的架构如图所示 包含八个学习层:五个卷积神经网络和三个全连接网络,并 ...

  8. 一路踩坑,被迫聊聊 C# 代码调试技巧和远程调试

    一:背景 1. 讲故事 每次项目预交付的时候,总会遇到各种奇葩的坑,我觉得有必要梳理一下以及如何快速解决的,让后来人避避坑,这篇就聊聊自己的所闻所遇: 我去,本地环境代码跑的哧溜,上了测试环境出问题 ...

  9. [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)

    题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...

  10. NER的数据处理

    import os class TransferData: def __init__(self): cur = '/'.join(os.path.abspath(__file__).split('/' ...