当前位置:   article > 正文

文档库开发之-vite打包优化_using dynamic import() to code-split the applicati

using dynamic import() to code-split the application

背景

首次进行组件库文档打包,遇到了一些ts打包报错和css打包警告,记录下处理过程。并且发现打包后的主包的体积过大,有一定优化空间

ts报错处理

当时有好奇为什么开发环境下都不报错,构建才产生这么多ts错误。大致猜想可能vite在dev和build下对ts处理可能有点不一样。

翻查文档得知,vite仅执行.ts文件的转译,并不执行任何类型检查,(可以在构建脚本中运行 tsc --noEmit 或者安装 vue-tsc 然后运行 vue-tsc --noEmit 来对你的 *.vue 文件做类型检查)。详见这里

而项目进行构建时有采用vue-tsc进行类型检查,这才导致的构建下产生的ts检查报错。报错如图下

回到这次的错误,发现都是引用的三方包的.d.ts的报错,也无法进行他的代码修改

后续查阅ts文档得知可以添加配置skipLibCheck。跳过对声明文件(扩展名为 的文件.d.ts)的类型检查

俩种配置方式如下:

一、命令行写法

二、配置文件写法

@chaset规则必须放文件第一位警告

报错原因:css编译,@charset 规则放在第一位,具体的原因与font-family有关

若是项目内的样式文件出来次问题,直接删除掉@charset "UTF-8";就可以了

但是呢,我项目中的报错是由于elementPlus组件库样式内部导致

报错如图下

 考虑到也不能去改内部代码,最后只能在vite构建中进行处理。处理方式如下,在vite.config.js中添加

  1. postcss: {
  2. plugins: [
  3. {
  4. postcssPlugin: 'internal:charset-removal',
  5. AtRule: {
  6. charset: (atRule) => {
  7. // 去除elementPlus内部charset警告
  8. if (atRule.name === 'charset') {
  9. atRule.remove()
  10. }
  11. }
  12. }
  13. }
  14. ]
  15. }

优化处理 

相关工具说明

  1. 目前 vite2.x 是基于 rollup 打包的,而不是 esbuild,详见这里
  2. 使用 rollup-plugin-visualizer 进行打包分析,打包之后,会在根目录默认生成一个 stats.html 文件

 优化前

vite.config.js配置如下:

  1. import { defineConfig } from 'vite'
  2. import { resolve } from 'path'
  3. import vue from '@vitejs/plugin-vue'
  4. import mdTovue from './plugins/md-to-vue'
  5. import { visualizer } from 'rollup-plugin-visualizer';
  6. const vuePlugin = vue({
  7. include: [/\.vue$/, /\.md$/]
  8. })
  9. // https://vitejs.dev/config/
  10. export default defineConfig({
  11. resolve: {
  12. alias: {
  13. "@": resolve(__dirname, 'src'),
  14. "@doc": resolve(__dirname, '../doc')
  15. },
  16. extensions: ['.js', '.jsx', '.ts', , '.tsx', '.vue', '.json']
  17. },
  18. css: {
  19. postcss: {
  20. plugins: [
  21. {
  22. postcssPlugin: 'internal:charset-removal',
  23. AtRule: {
  24. charset: (atRule) => {
  25. // 去除elementPlus内部charset警告
  26. if (atRule.name === 'charset') {
  27. atRule.remove()
  28. }
  29. }
  30. }
  31. }
  32. ]
  33. }
  34. },
  35. plugins: [mdTovue(), vuePlugin, visualizer(),
  36. build: {
  37. rollupOptions: {
  38. output: {
  39. manualChunks(id) {
  40. //创建一个vendor包含所有依赖项的块node_modules
  41. if (id.includes('node_modules')) {
  42. return 'vendor';
  43. }
  44. }
  45. }
  46. }
  47. }
  48. })

打包输出信息如下:

  1. dist/index.html 0.55 KiB
  2. dist/assets/Home.1a264624.js 0.56 KiB / gzip: 0.38 KiB
  3. dist/assets/RouterView.1afa8b53.js 0.21 KiB / gzip: 0.18 KiB
  4. dist/assets/a-b.931af6d1.js 0.34 KiB / gzip: 0.26 KiB
  5. dist/assets/test-component-config.1499331f.js 4.22 KiB / gzip: 1.23 KiB
  6. dist/assets/button1.demo.c877ed30.js 0.74 KiB / gzip: 0.45 KiB
  7. dist/assets/index.2f14ab82.js 15.11 KiB / gzip: 5.19 KiB
  8. dist/assets/test-inlay-component-alert.33174b36.js 1.59 KiB / gzip: 0.60 KiB
  9. dist/assets/test-inlay-component-badge.69bfc1dc.js 1.99 KiB / gzip: 0.58 KiB
  10. dist/assets/test-demo-block.98518de7.js 12.86 KiB / gzip: 2.51 KiB
  11. dist/assets/button3.demo.8c35a108.js 0.51 KiB / gzip: 0.29 KiB
  12. dist/assets/test-inlay-component-code.bda31783.js 20.53 KiB / gzip: 2.30 KiB
  13. dist/assets/test-inlay-component-embed.fdf24623.js 9.26 KiB / gzip: 1.52 KiB
  14. dist/assets/button3.demo.0ebe20ba.css 0.02 KiB / gzip: 0.04 KiB
  15. dist/assets/test-md-style.ba565816.js 8.15 KiB / gzip: 2.10 KiB
  16. dist/assets/Home.ecf788d2.css 0.03 KiB / gzip: 0.05 KiB
  17. dist/assets/index.d53f534c.js 5.37 KiB / gzip: 0.90 KiB
  18. dist/assets/button1.demo.705272a3.css 0.05 KiB / gzip: 0.07 KiB
  19. dist/assets/index.cd1300d0.css 8.71 KiB / gzip: 2.66 KiB
  20. dist/assets/vendor.7f07dc58.css 287.55 KiB / gzip: 39.94 KiB
  21. dist/assets/vendor.e3efb8ef.js 836.15 KiB / gzip: 273.28 KiB
  22. (!) Some chunks are larger than 500 KiB after minification. Consider:
  23. - Using dynamic import() to code-split the application
  24. - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks
  25. - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
  26. Done in 18.47s.
  27. Done in 18.71s.

 优化目的一般针对打包体积和打包时间进行优化,

从输出信息来看:

  1. vendor.e3efb8ef.js打包后有836.15 KiB,过大

注:ventor文件是从主包分离出node_modules中有引入的包,index.html依然会引入.因此后续的文章都放入主包中,不会有ventor文件。有较大的包单独抽离,如后续会说到的lodash

 打包优化

打包之后生成 stats.html,可以看到以下的图表

 注意,图表中显示的包大小,是分了 chunk 但还没有压缩的时候的大小

分析图表得

  1. lodash只用到了几个函数,却引入了全量包
  2. elementPlus无使用的组件也都打包进来了

 优化lodash

原引入方式

export { cloneDeep, throttle, debounce } from 'lodash'

 看到打包时vite的警告,有俩个方案可以实现lodash作为独立的 chunk 打包

  1. (!) Some chunks are larger than 500 KiB after minification. Consider:
  2. - Using dynamic import() to code-split the application
  3. - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks
  4. - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.

import()动态导入

把引入方式改成:

export const { cloneDeep, throttle, debounce } = import('lodash/debounce')

 确导致了ts报错,报错如下,所以排除这种方式

 manualChunks

改回使用原引用方式

vite.config.js添加

  1. build: {
  2. rollupOptions: {
  3. output: {
  4. manualChunks:{
  5. lodash: ['lodash']
  6. }
  7. }
  8. }
  9. }

打包时输出

  1. dist/assets/button3.demo.0ebe20ba.css 0.02 KiB / gzip: 0.04 KiB
  2. dist/assets/lodash.7fef2bd5.js 71.15 KiB / gzip: 25.74 KiB
  3. dist/assets/index.43bdfbd6.css 296.26 KiB / gzip: 42.19 KiB
  4. dist/assets/index.0ed6b04b.js 773.51 KiB / gzip: 250.64 KiB

可以看到,vendor的内容添加进index包,并且lodash被单独出来了,可是loadsh的还是引入了全量包体积

因此继续优化

把引入方式改成:

  1. export { default as debounce } from 'lodash/debounce'
  2. export { default as throttle } from 'lodash/throttle'
  3. export { default as cloneDeep } from 'lodash/cloneDeep'

打包时输出

  1. dist/index.html 0.49 KiB
  2. dist/assets/lodash.71f9f2ff.js 0.16 KiB / gzip: 0.10 KiB
  3. dist/assets/Home.55980fa6.js 0.56 KiB / gzip: 0.38 KiB

可以看出从原先的71.15KiB减少至0.16KiB,我们的优化目的达到

另一种优化方案

也可以将lodash替换成lodash-es,就可以一行引入方式

export { cloneDeep, throttle, debounce } from 'lodash'

lodash-es为ES modules版本的库,可以依赖tree-shake优化,只打包使用到的函数

优化elementPlus

elementPlus的优化比较简单了,官方已提供优化方案

将原本的全量引入改为以下引入方式

首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件

npm install -D unplugin-vue-components unplugin-auto-import

 然后把下列代码插入到你的 Vite 的配置文件中

  1. // vite.config.ts
  2. import AutoImport from 'unplugin-auto-import/vite'
  3. import Components from 'unplugin-vue-components/vite'
  4. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  5. export default {
  6. plugins: [
  7. // ...
  8. AutoImport({
  9. resolvers: [ElementPlusResolver()],
  10. }),
  11. Components({
  12. resolvers: [ElementPlusResolver()],
  13. }),
  14. ],
  15. }

优化后的打包输出

  1. dist/index.html 0.49 KiB
  2. dist/assets/lodash.71f9f2ff.js 0.16 KiB / gzip: 0.10 KiB
  3. dist/assets/Home.0fe43fd0.js 0.56 KiB / gzip: 0.38 KiB
  4. dist/assets/a-b.7a821a35.js 0.34 KiB / gzip: 0.27 KiB
  5. dist/assets/test-component-config.ce0781d4.js 4.25 KiB / gzip: 1.24 KiB
  6. dist/assets/button1.demo.abac5395.js 0.73 KiB / gzip: 0.44 KiB
  7. dist/assets/el-radio.fbba7f78.js 6.30 KiB / gzip: 2.26 KiB
  8. dist/assets/test-inlay-component-alert.36b60dd5.js 1.58 KiB / gzip: 0.60 KiB
  9. dist/assets/test-inlay-component-badge.f317a91a.js 1.98 KiB / gzip: 0.58 KiB
  10. dist/assets/test-demo-block.3829bc4f.js 16.33 KiB / gzip: 4.18 KiB
  11. dist/assets/button3.demo.a5c9d79c.js 0.53 KiB / gzip: 0.30 KiB
  12. dist/assets/test-inlay-component-embed.3b99ccfc.js 9.28 KiB / gzip: 1.54 KiB
  13. dist/assets/test-inlay-component-code.cc047da1.js 20.55 KiB / gzip: 2.30 KiB
  14. dist/assets/test-md-style.a10278e2.js 8.17 KiB / gzip: 2.11 KiB
  15. dist/assets/Home.ecf788d2.css 0.03 KiB / gzip: 0.05 KiB
  16. dist/assets/button1.demo.705272a3.css 0.05 KiB / gzip: 0.07 KiB
  17. dist/assets/index.05ba647c.js 5.39 KiB / gzip: 0.91 KiB
  18. dist/assets/button3.demo.0ebe20ba.css 0.02 KiB / gzip: 0.04 KiB
  19. dist/assets/el-radio.507e2006.css 4.03 KiB / gzip: 0.90 KiB
  20. dist/assets/index.0a06e46d.css 29.82 KiB / gzip: 6.20 KiB
  21. dist/assets/index.fb562358.js 203.61 KiB / gzip: 75.47 KiB
  22. Done in 17.59s.
  23. Done in 17.84s.

可以看出主包(index.fb562358.js) 从原先的773.51KiB减少至203.61KiB,

就连主样式包(index.0a06e46d.css )也从原先的296.26 KiB减少至29.82 KiBKiB

总结

通过打包分析,确认了以下因素导致vendor包过大(实际优化后,vendor包已移到主包中)

  1. lodash引入了全量函数
  2. elementPlus组件库引入了全量组件

解决方案:

  1. 通过 manualChunks 方案,将lodash单独打包并通过按需引入减少主包体积
  2. 使用 unplugin-vue-components 和 unplugin-auto-import 这两款插件按需引入elementPlus组件库

成果:

        主包从844.66KiB 减少到 203.61KiB,体积减少了 75.8%

        主样式包从296.26KiB 减少到 29.82KiB,体积减少了89.9%

        构建过程耗时从 18.71S 减少到 17.84S,耗时减少了 4.6%

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/86504
推荐阅读
相关标签
  

闽ICP备14008679号