问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

让你的Vite应用运行更快一点

创作时间:
作者:
@小白创作中心

让你的Vite应用运行更快一点

引用
1
来源
1.
https://modyqyw.top/blogs/2024/09/make-your-vite-applications-run-a-little-faster

随着项目需求的增长,Vite应用可能会遇到服务器启动慢、页面加载慢、构建慢等问题。本文从浏览器、Vite配置和项目三个方面出发,介绍了多种实用的优化方法,帮助开发者提升Vite应用的运行效率。

背景

虽然Vite默认运行速度很快,但随着项目需求的增长,性能问题可能会悄然出现。这篇文章希望从多个角度出发,介绍不同的优化方式,让你的Vite应用运行更快一点,解决服务器启动慢、页面加载慢、构建慢等问题。

浏览器

插件

大部分情况下,我们都在浏览器中查看我们的Vite应用并开发调试。某些浏览器插件(如去广告插件uBlock、adGuard)可能会干涉请求,导致启动和刷新速度降低。在这种情况下,建议使用不含插件、专门用于开发的配置,也建议使用无痕模式获取更快的速度,见Chrome隐私模式网页加载速度更快。

开发者工具

此外,Vite开发服务器对预打包依赖项进行了强缓存,同时对源代码实现快速的304响应,如果在开发者工具打开的情况下禁用缓存,可能会大幅影响启动速度和全页刷新的时间。因此,建议关闭“禁用缓存”功能,以确保启动速度和全页刷新速度。

Vite配置

插件

Vite官方插件一直在优化性能,比如vitejs/vite-plugin-react就通过动态导入大型依赖来减少Node.js的启动时间。

社区插件对于性能可能没有那么关注,进而影响开发者的体验。举一个例子来说,很多社区文章至今仍然在推荐vite-plugin-eslint,但截至目前为止,它已经两年没有更新了,对于Vite和ESLint新版本支持一般。

另一方面,它强制在buildStart和transform钩子运行ESLint校验,在buildStart中校验会导致开发服务器启动期间等待时间过长,延迟可以在浏览器中访问站点的时间,而在transform钩子中校验会导致一些文件加载速度比其他文件慢,加载站点时在浏览器中的请求瀑布图就会越明显,在开发时能感受到的卡顿也就会越明显。

尽管达到了ESLint校验的目的,但是开发体验下降了,开发速度降低了,值不值得呢?这是一个很值得考量的问题。

有很多种方法可以确认这个性能问题,比如使用vite --debug plugin-transform或vite-plugin-inspect来检查,也可以运行vite --profile后访问站点,在终端中按p + enter记录一个.cpuprofile,接着使用像speedscope这样的工具来检查配置文件并识别瓶颈。

确认到性能问题后,可以考虑分叉并改进相应的插件,或者直接使用替代品。针对上面的例子,你可以考虑将它换成vite-plugin-checker、@nabla/vite-plugin-eslint或者vite-plugin-eslint2,它们都支持异步的ESLint校验,这样就不会特别影响性能和开发体验,同时也能达到ESLint校验的目的。

工具链

精简你的工具链是一个提速的好办法。举一个例子来说,很多人使用SCSS主要是为了变量和嵌套,但是实际上CSS变量和嵌套都已经正式落地了。

如果生产环境要支持稍微老一点、不支持嵌套的版本的浏览器,完全可以在生产构建时使用PostCSS来处理嵌套,这样就不会影响Vite开发服务器的速度。非常非常古老的版本的浏览器既不安全,也不快速,体验也很差,应该逐步引导淘汰这部分内容以提高用户体验和开发体验,感兴趣可以看看browser-update。

而使用更原生化的工具链也是一个提速的好办法。SWC官网显示它的速度是Babel的20到70倍,在复杂的实际应用中也有大量的速度优势,这足以证明原生化对提速的帮助重大。你可以使用@vitejs/plugin-react-swc来替代vite-plugin-react,用LightningCSS来替代PostCSS,用SWC或esbuild来替代Babel,等等等等,以此来实现更好的性能。

依赖预构建

Vite会将以CommonJS或UMD形式提供的依赖项转换为ES模块,还将具有许多内部模块的ESM依赖项转换为单个模块,这就是Vite的依赖预构建。

前者是出于兼容性考虑,我们这里不做详细讨论。而后者是出于性能考虑,如果没有这一步,当我们执行import { debounce } from 'lodash-es'时,浏览器会同时发出600多个HTTP请求,对应lodash-es600多个模块!即使服务器能够轻松处理它们,但大量请求会导致浏览器端的网络拥塞,使页面加载变得明显缓慢。

这也就是为什么我们需要依赖预构建。Vite本身会自动、透明地进行这一步,我们也可以通过配置来明确指定需要预构建的依赖。

// vite.config.ts
import { defineConfig } from 'vite';
import pkg from './package.json';
export default defineConfig({
  optimizeDeps: {
    include: Object.keys(pkg.dependencies),
  },
});

预热

预热是常常被忽视的优化,我在一些介绍Vite的文章里也几乎没有看见,但它却能有效地提升开发体验,减少等待时间。

默认地,Vite开发服务器只按需转换浏览器请求的文件,这使得它能够快速启动,并且只对使用的文件执行转换。

然而这种做法可能让Vite开发服务器闲置,导致切换页面加载需要等待,导致开发体验不佳。如果预计某些文件将被短时间内请求,可以提前转换和缓存,提高页面加载速度。这种做法就是预热。

可以通过运行vite --debug transform并检查日志来找到频繁使用的文件,然后把它添加到Vite配置里面。

vite:transform 28.72ms /@vite/client +1ms
vite:transform 62.95ms /src/components/BigComponent.vue +1ms
vite:transform 102.54ms /src/utils/big-utils.js +1ms
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
  server: {
    warmup: {
      clientFiles: [
        './src/components/BigComponent.vue',
        './src/utils/big-utils.js',
      ],
    },
  },
});

需要注意的是,只应该预热频繁使用的文件,这是为了避免过载Vite开发服务器。但我还是喜欢直接全部预热,主打一个反骨。🤪

Nuxt最新版本已经配置了该功能,你也可以查看Vite / 配置 / server.warmup以获取更多信息。

对于4.3 <= Vite < 5,需要使用vite-plugin-warmup,更低版本没有相关支持。

项目

路径解析

大家可能都难以预料解析导入路径操作的昂贵程度。当你尝试使用import './Component'导入./Component.jsx时,Vite将运行以下步骤来解析:

  • 检查./Component是否存在,不存在。
  • 检查./Component.mjs是否存在,不存在。
  • 检查./Component.js是否存在,不存在。
  • 检查./Component.mts是否存在,不存在。
  • 检查./Component.ts是否存在,不存在。
  • 检查./Component.jsx是否存在,存在!

解析一个简单的导入路径就进行了6次文件系统检查!隐式导入越多,解析路径所需的时间就越多。

因此,通常最好明确导入路径,比如import './Component.jsx',你也可以缩小resolve.extensions的列表以减少一般的文件系统检查,但必须确保它也适用于node_modules中的文件。

如果想要使用ESLint来强制明确导入路径,可以配置import/extensions或import-x/extensions规则,下面是一个示意配置。

"import/extensions": ["warn", "ignorePackages"]
"import-x/extensions": ["warn", "ignorePackages"]

桶文件

桶文件(barrel files)是重新导出同一目录下其他文件API的文件。比如:

// src/utils/index.js
export * from './color.js';
export * from './dom.js';
export * from './slash.js';

当你只导入一个单独的API,例如import { slash } from './utils',仍然需要获取和转换桶文件中的所有文件,因为它们可能包含slash API,也可能包含在初始化时运行的其他副作用。这意味着在初始页面加载时,你加载的文件比所需的要更多,进而导致页面加载速度变慢。当模块越来越多时,加载时间也越来越多,测试表明加载时间随模块数量的增加呈现出接近指数级或类指数级的增长。

如果可能的话,你应该尽量避免使用桶文件,直接导入单独的API。你可以阅读Speeding up the JavaScript ecosystem - The barrel file debacle了解更多细节与数据,上面的图片正是来源于这篇文章。

总结

本文参考了Vite官方文档 / 性能写成,在此对Vite团队表示由衷的感谢。🙏

本文从浏览器、Vite配置以及项目三个方面出发,介绍了不同的优化方式,目的就是让Vite应用运行更快一点,解决服务器启动慢、页面加载慢、构建慢等问题。

但必须注意,这些方法不是万能的,它们不会影响生产环境下的性能。要优化生产环境性能,你需要考虑分割代码、优化静态资源、引入SSR、引入CDN、预加载、预取、优化CSS、缓存、Web Worker、减少DOM操作等等,这些就不在这里详细展开了,感兴趣可以留言叫我写一写。

值得一提的是,Vite也不是万能的,正如Farm文档中所说,开发和生产之间的不一致、拆包优化困难等等问题仍然需要解决,这一切都需要我们耐心等待,或是积极参与其中。如果实在等不及了,推荐看看Farm或者Rsbuild吧。

希望本文能带给你一点启发和帮助!

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号