路由懒加载
SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文件,当用户打开首页时,会一次性加载所有的资源,造成首页加载很慢,降低用户体验
列一个实际项目的打包详情:
-
app.js 初始体积:
1175 KB -
app.css 初始体积:
274 KB
将路由全部改成懒加载
js
体验AI代码助手
代码解读
复制代码
// 通过webpackChunkName设置分割后代码块的名字
const Home = () => import(/* webpackChunkName: "home" */ "@/views/home/index.vue");
const MetricGroup = () => import(/* webpackChunkName: "metricGroup" */ "@/views/metricGroup/index.vue");
…………
const routes = [
{
path: "/",
name: "home",
component: Home
},
{
path: "/metricGroup",
name: "metricGroup",
component: MetricGroup
},
…………
]
重新打包后,首页资源拆分为 app.js 和 home.js,以及对应的 css 文件
-
app.js:
244 KB、 home.js:35KB -
app.css:
67 KB、home.css:15KB
通过路由懒加载,该项目的首页资源压缩约 52%
路由懒加载的原理
懒加载前提的实现:ES6的动态地加载模块——import()
调用 import() 之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中
——摘自《webpack——模块方法》的import()小节
要实现懒加载,就得先将进行懒加载的子模块分离出来,打包成一个单独的文件
webpackChunkName 作用是 webpack 在打包的时候,对异步引入的库代码(lodash)进行代码分割时,设置代码块的名字。webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中
externals 提取项目依赖
externals 来提取这些依赖包,告诉 webpack 这些依赖是外部环境提供的,在打包时可以忽略它们,就不会再打到 chunk-vendors.js 中
1、vue.config.js 中配置:
module.exports = {
configureWebpack: {
externals: {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
echarts: 'echarts'
}
}
2)在 index.html 中使用 CDN 引入依赖
xml
体验AI代码助手
代码解读
复制代码
<body>
<script src="http://lib.baomitu.com/vue/2.6.14/vue.min.js"></script>
<script src="http://lib.baomitu.com/vue-router/3.5.1/vue-router.min.js"></script>
<script src="http://lib.baomitu.com/axios/1.2.1/axios.min.js"></script>
<script src="http://lib.baomitu.com/echarts/5.3.2/echarts.min.js"></script>
</body>
验证 externals 的有效性:
重新打包,最新数据如下:
打包体积:1.12M
打包速度:
18879ms
使用 externals 后,包体积压缩50%、打包速度提升26%
2、组件库的按需引入
为什么没有使用 externals 的方式处理组件库呢?
externals缺点:直接在html内引入的,失去了按需引入的功能,只能引入组件库完整的js和css
组件库按需引入的原理:最终只引入指定组件和对应的样式
elementUI 需要借助 babel-plugin-component 插件实现,插件的作用如下:
如按需引入 Button 组件:
import { Button } from 'element-ui'
Vue.component(Button.name, Button)
编译后的文件(自动引入 button.css):
javascript
体验AI代码助手
代码解读
复制代码
import _Button from "element-ui/lib/button";
import _Button2 from "element-ui/lib/theme-chalk/button.css";
// base.css是公共的样式
import "element-ui/lib/theme-chalk/base.css";
Vue.component(_Button.name, _Button);
通过该插件,最终只引入指定组件和样式,来实现减少组件库体积大小
1)安装 babel-plugin-component
体验AI代码助手
代码解读
复制代码
npm install babel-plugin-component -D
2)babel.config.js中引入
css
体验AI代码助手
代码解读
复制代码
module.exports = {
presets: ['@vue/app'],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
};
验证组件库按需引入的有效性:
重新打包,最新数据如下:
打包体积:648KB
打包速度:
15135ms
组件库按需引入后,包体积压缩72%、打包速度提升40%
同时 chunk-vendors.css 的体积也有了明显的减少,从206KB降到了82KB
原始体积:
按需引入后:
3、减小三方依赖的体积
具体参考文章 juejin.cn/post/718631…
在 Vue 项目中,通过配置 externals 并结合按需引入策略来优化第三方包,可以有效减小打包体积,提升应用加载速度。下面我将为你梳理这两种方法的实现步骤和注意事项。
为了让你能快速了解这两种策略的核心配置,这里有一个简单的对比表格:
优化策略 主要手段 适用场景 配置 externals 在 vue.config.js 中声明外部依赖,并通过 CDN 引入 适用于 Vue、Vue-Router、Vuex、Axios 等稳定、通过 CDN 分发的大型库 按需引入 使用 Babel 插件或基于 ES6 模块的 Tree Shaking,或 unplugin-vue-components 等自动导入工具 适用于 Element UI、Ant Design Vue 等提供ES 模块的组件库
🔧 配置 externals
这种方法的核心是让 Webpack 在打包时排除指定的依赖,转而通过 CDN 链接在运行时引入。
- 修改 Vue 配置
在项目根目录下的 vue.config.js 文件中,配置 externals 字段。这里需要指定包名及其对应的全局变量。
// vue.config.js module.exports = { configureWebpack: { externals: { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'axios': 'axios' // 其他需要排除的库... } } } - 引入 CDN 资源 在 public/index.html 中,通过
- (可选)调整代码中的引入方式 配置 externals 后,你通常可以继续使用 import 语句。但有时可能需要改为 require 方式,请根据构建结果调整。
🌿 实现按需引入
对于大型组件库,全量引入会显著增加包体积,按需引入只导入你实际用到的组件。
-
使用 Babel 插件(传统方式) 这种方式适用于很多 UI 库,例如 Element UI。 · 安装插件:例如,对于 Element UI,需要安装 babel-plugin-component。
npm install babel-plugin-component --save-dev· 配置 Babel:在 babel.config.js 或 .babelrc 文件中配置插件。
// babel.config.js module.exports = { plugins: [ [ 'component', { libraryName: 'element-ui', styleLibraryName: 'theme-chalk' } ] ] }· 在代码中按需引入:
import { Button, Select } from 'element-ui' import 'element-ui/lib/theme-chalk/button.css' import 'element-ui/lib/theme-chalk/select.css' Vue.component(Button.name, Button) Vue.component(Select.name, Select) -
使用现代自动导入工具(推荐) 社区提供的 unplugin-vue-components 等插件可以自动按需引入组件,甚至包括样式,大大简化了开发。 · 以 Vite 项目为例: · 安装插件:例如,为 Element Plus 配置自动导入。
bash npm install unplugin-vue-components unplugin-auto-import -D· 配置插件:在 vite.config.js 中配置。 ```javascript // vite.config.js 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()], }), ], } ```配置完成后,你在模板中直接使用 时,插件会自动引入 Button 组件及其样式。
💡 组合使用与进阶优化
· 结合使用:你可以在一个项目中同时使用这两种策略。例如,将 Vue、Vue Router 等核心库通过 externals 和 CDN 引入,同时将 Element UI 这类大型 UI 库通过按需引入的方式处理。 · 路由懒加载:使用 Vue Router 的懒加载功能,将不同路由对应的组件分割成不同的代码块,当路由被访问时才按需加载。
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [{ path: '/foo', component: Foo }]
})
· 注意函数式组件:一些以函数形式调用的组件(如 Message),自动导入工具可能无法自动处理其样式,需要你手动引入样式文件。
import { ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
⚠️ 注意事项
· CDN 的可靠性:使用 externals 方案依赖于 CDN 服务的稳定性。为规避风险,可以考虑使用多个 CDN 提供商备份,或将这些资源部署到自己的静态资源服务器。 · 版本一致性:确保 externals 配置的版本与 CDN 引入的版本一致,避免因版本差异导致运行时错误。 · 优化效果验证:使用 npm run build 并观察打包后文件体积的变化,或使用 webpack-bundle-analyzer 分析打包结果,验证优化效果。
希望这些详细的步骤和说明能帮助你成功优化 Vue 项目的打包体积!如果你能告诉我你项目中主要使用了哪些第三方库,或许我可以给出更具体的配置建议。