文档库开发之-vite打包优化

news2025/1/25 9:25:25

背景

首次进行组件库文档打包,遇到了一些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中添加

postcss: {
      plugins: [
        {
          postcssPlugin: 'internal:charset-removal',
          AtRule: {
            charset: (atRule) => {
              // 去除elementPlus内部charset警告
              if (atRule.name === 'charset') {
                atRule.remove()
              }
            }
          }
        }
      ]
    }

优化处理 

相关工具说明

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

 优化前

vite.config.js配置如下:

import { defineConfig } from 'vite'
import { resolve } from 'path'
import vue from '@vitejs/plugin-vue'
import mdTovue from './plugins/md-to-vue'
import { visualizer } from 'rollup-plugin-visualizer';

const vuePlugin = vue({
  include: [/\.vue$/, /\.md$/]
})

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: {
      "@": resolve(__dirname, 'src'),
      "@doc": resolve(__dirname, '../doc')
    },
    extensions: ['.js', '.jsx', '.ts', , '.tsx', '.vue', '.json']
  },
  css: {
    postcss: {
      plugins: [
        {
          postcssPlugin: 'internal:charset-removal',
          AtRule: {
            charset: (atRule) => {
              // 去除elementPlus内部charset警告
              if (atRule.name === 'charset') {
                atRule.remove()
              }
            }
          }
        }
      ]
    }
  },
  plugins: [mdTovue(), vuePlugin, visualizer(),
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          //创建一个vendor包含所有依赖项的块node_modules
          if (id.includes('node_modules')) {
            return 'vendor';
          }
        }
      }
    }
  }
})

打包输出信息如下:

dist/index.html                                      0.55 KiB
dist/assets/Home.1a264624.js                         0.56 KiB / gzip: 0.38 KiB
dist/assets/RouterView.1afa8b53.js                   0.21 KiB / gzip: 0.18 KiB
dist/assets/a-b.931af6d1.js                          0.34 KiB / gzip: 0.26 KiB
dist/assets/test-component-config.1499331f.js        4.22 KiB / gzip: 1.23 KiB
dist/assets/button1.demo.c877ed30.js                 0.74 KiB / gzip: 0.45 KiB
dist/assets/index.2f14ab82.js                        15.11 KiB / gzip: 5.19 KiB
dist/assets/test-inlay-component-alert.33174b36.js   1.59 KiB / gzip: 0.60 KiB
dist/assets/test-inlay-component-badge.69bfc1dc.js   1.99 KiB / gzip: 0.58 KiB
dist/assets/test-demo-block.98518de7.js              12.86 KiB / gzip: 2.51 KiB
dist/assets/button3.demo.8c35a108.js                 0.51 KiB / gzip: 0.29 KiB
dist/assets/test-inlay-component-code.bda31783.js    20.53 KiB / gzip: 2.30 KiB
dist/assets/test-inlay-component-embed.fdf24623.js   9.26 KiB / gzip: 1.52 KiB
dist/assets/button3.demo.0ebe20ba.css                0.02 KiB / gzip: 0.04 KiB
dist/assets/test-md-style.ba565816.js                8.15 KiB / gzip: 2.10 KiB
dist/assets/Home.ecf788d2.css                        0.03 KiB / gzip: 0.05 KiB
dist/assets/index.d53f534c.js                        5.37 KiB / gzip: 0.90 KiB
dist/assets/button1.demo.705272a3.css                0.05 KiB / gzip: 0.07 KiB
dist/assets/index.cd1300d0.css                       8.71 KiB / gzip: 2.66 KiB
dist/assets/vendor.7f07dc58.css                      287.55 KiB / gzip: 39.94 KiB
dist/assets/vendor.e3efb8ef.js                       836.15 KiB / gzip: 273.28 KiB

(!) Some chunks are larger than 500 KiB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
Done in 18.47s.
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 打包

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

import()动态导入

把引入方式改成:

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

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

 manualChunks

改回使用原引用方式

vite.config.js添加

build: {
    rollupOptions: {
      output: {
        manualChunks:{
          lodash: ['lodash']
        }
      }
    }
  }

打包时输出

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

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

因此继续优化

把引入方式改成:

export { default as debounce } from 'lodash/debounce'
export { default as throttle } from 'lodash/throttle'
export { default as cloneDeep } from 'lodash/cloneDeep'

打包时输出

dist/index.html                                      0.49 KiB
dist/assets/lodash.71f9f2ff.js                       0.16 KiB / gzip: 0.10 KiB
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 的配置文件中

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}

优化后的打包输出

dist/index.html                                      0.49 KiB
dist/assets/lodash.71f9f2ff.js                       0.16 KiB / gzip: 0.10 KiB
dist/assets/Home.0fe43fd0.js                         0.56 KiB / gzip: 0.38 KiB
dist/assets/a-b.7a821a35.js                          0.34 KiB / gzip: 0.27 KiB
dist/assets/test-component-config.ce0781d4.js        4.25 KiB / gzip: 1.24 KiB
dist/assets/button1.demo.abac5395.js                 0.73 KiB / gzip: 0.44 KiB
dist/assets/el-radio.fbba7f78.js                     6.30 KiB / gzip: 2.26 KiB
dist/assets/test-inlay-component-alert.36b60dd5.js   1.58 KiB / gzip: 0.60 KiB
dist/assets/test-inlay-component-badge.f317a91a.js   1.98 KiB / gzip: 0.58 KiB
dist/assets/test-demo-block.3829bc4f.js              16.33 KiB / gzip: 4.18 KiB
dist/assets/button3.demo.a5c9d79c.js                 0.53 KiB / gzip: 0.30 KiB
dist/assets/test-inlay-component-embed.3b99ccfc.js   9.28 KiB / gzip: 1.54 KiB
dist/assets/test-inlay-component-code.cc047da1.js    20.55 KiB / gzip: 2.30 KiB
dist/assets/test-md-style.a10278e2.js                8.17 KiB / gzip: 2.11 KiB
dist/assets/Home.ecf788d2.css                        0.03 KiB / gzip: 0.05 KiB
dist/assets/button1.demo.705272a3.css                0.05 KiB / gzip: 0.07 KiB
dist/assets/index.05ba647c.js                        5.39 KiB / gzip: 0.91 KiB
dist/assets/button3.demo.0ebe20ba.css                0.02 KiB / gzip: 0.04 KiB
dist/assets/el-radio.507e2006.css                    4.03 KiB / gzip: 0.90 KiB
dist/assets/index.0a06e46d.css                       29.82 KiB / gzip: 6.20 KiB
dist/assets/index.fb562358.js                        203.61 KiB / gzip: 75.47 KiB
Done in 17.59s.
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%

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407810.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

英雄联盟轮播图自动轮播

六月过去了,七月还会远吗?不知不觉到了六月底的最后一天。你好,七月! 大家好,我是小陈陈呀,上次写了一篇英雄联盟轮播图手动轮播,当天晚上有很多大朋友小朋友私信小陈陈:可以在上次…

【微信小程序】一文读懂页面导航

🎁写在前面: 观众老爷们好呀,这里是前端小刘不怕牛牛频道,小程序系列又更新了呀,今天的内容是微信小程序的页面导航,非常重要,赶紧拿起小本本记起来呀! 文章目录一,页面导…

【项目问题定位】前端请求不到资源报错ERR_CONTENT_LENGTH_MISMATCH的解决

文章目录问题简述问题背景问题定位初始报错定位好像是网络问题ERR_CONTENT_LENGTH_MISMATCH 200 是什么原因?原来是Nginx报错了为何没有权限?nobody的原因问题解决原因总结知识点问题简述 前端页面加载资源时,出现ERR_CONTENT_LENGTH_MISMAT…

前端异常:“Uncaught SyntaxError: missing ) after argument list“真的只是参数列表后面缺少 “)”?

案发现场 我们在写JS的时候,有时候报错"Uncaught SyntaxError: missing ) after argument list",字面翻译过来的意思:语法错误: 参数列表后面缺少 )。 这真的就是缺少括号的意思吗?然而只是真的缺少括号才会出现这样的…

HTML的常见标签及用法

一、注释标签 形如&#xff1a;<!-- -->的格式就叫做注释标签&#xff0c;在代码中起到解释说明的作用。 二、标题标签 在HTML中有六种格式的标题标签类型&#xff0c;分别是h1,h2,h3,h4,h5,h6。对应的形式为&#xff1a; 三、段落标签 当文章需要分段时&#xff0c;使…

js除法取整(js除法向上取整)

Javascript取整问题。要求只要有小数存在就进一位。例如&#xff1a;2.1取3&#xff0c;3.1取4 var a 2.0; function parseNumber(number, splitChar) { var n number ; var s splitChar nullvar a 2.1; var b parseInt(a) 1; // b will be 3 parseInt是截掉尾数&#…

vxe-table表格合并单元格和编辑

//这是在vue上面引用vxe-table插件实现的&#xff0c;主要方法都设置在table中&#xff0c;mergeCells&#xff0c;tableData都是在vue页面的data初使化数据&#xff0c; :footer-method“footerMethod”&#xff1a;尾部数据&#xff0c;:merge-footer-items“mergeCells”&am…

vue通过url方式展示PDF方法总结

最近vue项目中遇到预览pdf出现乱码问题&#xff0c;尝试了各种办法受尽折磨&#xff0c;以此记录一下使用的几种方法 1.使用pdfjs-dist 插件&#xff0c;通过iframe标签显示 首先 npm install pdfjs-dist --save npm直接下载插件 npm install --save pdfjs-dist2.0.943&…

【vue 项目】有关cascader任选一级、字段名不同、同时获取value和label值、回显(推父节点)等问题解决

文章目录选择任意一级选项字段名转换最后一级数据为空显示暂无数据问题同时获取cascader的value和label值选择时双击两次才显示被选中&#xff08;单选选择任意一级组件&#xff09;Error in callback for watcher “options“: “TypeError: Cannot read property ‘level‘ o…

表单元素盘点第二弹<form><textarea>元素详细介绍

博主有话说&#xff1a;如果有描述错误之处请大家纠正。让我们可以一起学习一起进步。 个人主页&#xff1a;GUIDM主页 内容专栏&#xff1a;干货 此块内容为纯纯的干货&#xff0c;略显乏味枯燥&#xff0c;是笔记向的blog。如果觉得还不错&#xff0c;希望你可以一键三连&…

Vue2的响应式原理

--------Vue2响应式原理---------- 原理&#xff1a;通过数据劫持 defineProperty 发布订阅者模式&#xff0c;当 vue 实例初始化后 observer 会针对实例中的 data 中的每一个属性进行劫持并通过 defineProperty() 设置值后在 get() 中向发布者添加该属性的订阅者&#xff0c…

基于RuoYi若依vue的数据分页功能的前后端代码详解

目录 1.前端代码 1.1首先在前端会有一个 组件&#xff0c;为分页组件 1.2前端获取列表函数以及访问后端的URL与请求方式 1.3开发者工具查看前端访问后端信息 1.4开发者工具查看前端接收到后端的回应信息 2.后端代码 2.1接口 2.2接口内方法的代码 2.3后端Log输出如下 1.前…

IntersectionObserver API详解

过去&#xff0c;要检测一个元素是否可见或者两个元素是否相交并不容易&#xff0c;比如实现图片懒加载、内容无限滚动等功能时&#xff0c;都需要通过​getBoundingClientRect()​写大量的逻辑计算或者依靠scroll事件监听等性能很差方式来实现。 现在&#xff0c;依靠Interse…

Object.prototype.toString.call()的原理

今天在项目中看到了用Object.prototype.toString.call()这个方法封装的检测数据类型的工具。 但是浏览器搜索相关原理的好回答凤毛麟角&#xff0c;故而想记录一下&#xff0c;万一可以帮助到更多的新手呢&#xff1f;我的文章都是非常通俗易懂的&#xff0c;因为我写文章的时…

HTML页面知识点小总结(巨详细)

HTML基础知识点总结 文章目录HTML基础知识点总结一、 HTML页面主要的三大标签。二、 外部的CSS文件。三、外部的JavaScript文件。四、< body >标签中存放的内容。如果觉得写的不错的话点个赞支持鼓励一下吧&#xff0c;欢迎交流&#xff0c;谢谢啦~~~一、 HTML页面主要的…

前端知识点汇总

HTML介绍 HTML: Hyper Text Markup Language 超文本标记语言&#xff0c;用来做网页. 负责网页的框架结构布局.1993年 html 1.0 Tim Berners-Lee(蒂姆-博纳斯-李)&#xff0c;万维网之父1995年 html 2.0 IETF(互联网工程小组)1997年1月 html 3.2 W3C(万维网联盟)1997年12月 ht…

vue2:elementUI中Form 表单在特定情况下做动态rules添加删除

先看需求&#xff1a;&#xff08;不想看的直接拉到最后&#xff09; 【需求说明】 6、如状态为上架时&#xff0c;库存为必填&#xff0c;下架状态时&#xff0c;库存为可填&#xff0c;前面无星号 实现方法&#xff1a;使用this.$set()和this.$delete() 上代码&#xff1a;…

Vue2 + JSX使用总结

什么是JSX 摘自 React 官方&#xff1a; 它被称为 JSX&#xff0c;是一个 JavaScript 的语法扩展。我们建议在 React 中配合使用 JSX&#xff0c;JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模板语言&#xff0c;但它具有 JavaScript 的全部…

前端人必看的JS面试题汇总

面试是每一个前端人在求职过程中都需要面对的事情。在面试过程中&#xff0c;面试官没有办法通过实践操作去了解应聘者的技能水平&#xff0c;所以他们更多地会通过“八股文”的考察来判断你是否符合公司的招聘要求。所以作为一个前端人&#xff0c;在掌握好前端技能的同时&…

vue导出word

最近的项目中&#xff0c;需要把vue中的部分内容导出为word形式&#xff0c;之前没有做过这方面的&#xff0c;特记录&#xff0c;由于是初学&#xff0c;所以整理了此模板&#xff0c;注意&#xff1a;这是一个模板&#xff0c;并不是相关字段的解析&#xff0c;每个字段都是做…