【vite 4.3 + vue 3.2 项目优化实战】配置 CDN 服务
记录一次 vite 打包体积优化过程,踩了一些坑,分享一下。
参考了这篇文章: Vite 中使用 cdn 来加载需要的库文件-前端/后端-繁花云
本篇将使用两种方式进行 CDN 加速优化项目
- 使用 vite-plugin-cdn-import 插件
- 使用 rollup 自带的 external、output.globals
一. 使用 vite 创建项目
创建项目
pnpm create vite
项目目录结构
安装
- 下载之后进入项目
cd cdn-demo
- 安装依赖
pnpm i
运行
pnpm dev
打开 http://localhost:5173, 可以看到默认的页面
安装 arco-design
# npm
npm install --save-dev @arco-design/web-vue
# yarn
yarn add --dev @arco-design/web-vue
完整引入
注意不能按需引入 arco-design、直接在 main.ts 中使用全局引入的方式,打包后会自动按照 cdn 引入
- 修改
main.js
文件
import { createApp } from 'vue'
import ArcoVue from '@arco-design/web-vue';
import App from './App.vue';
import '@arco-design/web-vue/dist/arco.css';
const app = createApp(App);
app.use(ArcoVue);
app.mount('#app');
使用 arco-design
- 修改
App.vue
文件
<template>
<a-space direction="vertical">
<a-space>
<a-button type="primary" status="success">Primary</a-button>
<a-button status="success">Default</a-button>
<a-button type="dashed" status="success">Dashed</a-button>
<a-button type="outline" status="success">Outline</a-button>
<a-button type="text" status="success">Text</a-button>
</a-space>
<a-space>
<a-button type="primary" status="warning">Primary</a-button>
<a-button status="warning">Default</a-button>
<a-button type="dashed" status="warning">Dashed</a-button>
<a-button type="outline" status="warning">Outline</a-button>
<a-button type="text" status="warning">Text</a-button>
</a-space>
<a-space>
<a-button type="primary" status="danger">Primary</a-button>
<a-button status="danger">Default</a-button>
<a-button type="dashed" status="danger">Dashed</a-button>
<a-button type="outline" status="danger">Outline</a-button>
<a-button type="text" status="danger">Text</a-button>
</a-space>
</a-space>
</template>
然后可以看到页面
二. 分析依赖
这里可以安装 rollup-plugin-visualizer 插件分析依赖视图
安装 rollup-plugin-visualizer
pnpm add rollup-plugin-visualizer -D
使用 rollup-plugin-visualizer
- 修改
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from 'rollup-plugin-visualizer'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), visualizer({ open: true })],
})
打包项目
pnpm build
打包完成后,会自动打开页面:
vite 也会输出:
分析上图,我们发现整个项目依赖为 1.79MB,其中 vue 体积占比 13.57%,248.43KB 大小,其次是@arco-design+web-vue 占比 81.49%, 1.46MB。
三. CDN 加速
1. 安装 vite-plugin-cdn-import(推荐)
pnpm add vite-plugin-cdn-import -D
1.1. 配置需要加速的依赖
- 修改
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from 'rollup-plugin-visualizer'
// 文档的用法会报错, 要这样引入才可以
import { Plugin as importToCDN } from 'vite-plugin-cdn-import'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
visualizer({ open: true }),
importToCDN({
modules: [
{
// 引入时的包名
name: '@arco-design/web-vue',
// app.use(), 全局注册时分配给模块的变量
var: 'ArcoVue',
// 根据自己的版本号找到对应的CDN网址
path: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco-vue.min.js',
// 根据自己的版本号找到对应的CDN网址
css: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco.css',
},
],
}),
],
})
CDN 参数获取方式
-
name:npm 包的名称
-
var:组件(main.ts)引用的名称
比如ArcoVue
import ArcoVue from '@arco-design/web-vue' const app = createApp(App) app.use(ArcoVue)
-
path:cdn 网站存储对应的 js 地址
输入对应名称,会自动跳转到对应的 js 文件,复制粘贴,需要修改版本,和自己项目的 package.json 版本一致允许只写到版本,后面会自动补齐
-
css:对应位置,参考上图 element-plus
需要注意的是,css 可以使用本地的,使用本地的就不要添加 css,使用远程 cdn 的就需要在打包前注释本地的,否则会出现样式重叠。
-
修改
main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import ArcoVue from '@arco-design/web-vue'
// 这里 css 也用 CDN 导入
// import '@arco-design/web-vue/dist/arco.css'
const app = createApp(App)
app.use(ArcoVue)
app.mount('#app')
1.2. 重新打包
pnpm build
可以看到,原先的 arco-design 依赖包和消失了:
这时我们本地预览构建产物
pnpm preview
可以看到页面报错了:
原因是在 element-plus 这个源码中使用了 vue 依赖包里的 ref 变量
1.3. 处理报错
- 我们将 vue 也引入进来,可以使用 vite-plugin-cdn-import 的 autoComplete 自动导入
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from 'rollup-plugin-visualizer'
// 文档的用法会报错, 要这样引入才可以
import { Plugin as importToCDN, autoComplete } from 'vite-plugin-cdn-import'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
visualizer({ open: true }),
importToCDN({
modules: [
autoComplete('vue'), // vue2 使用 autoComplete('vue2')
{
// 引入时的包名
name: '@arco-design/web-vue',
// app.use(), 全局注册时分配给模块的变量
var: 'ArcoVue',
// 根据自己的版本号找到对应的CDN网址
path: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco-vue.min.js',
// 根据自己的版本号找到对应的CDN网址
css: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco.css',
},
],
}),
],
})
重新打包 pnpm build
- 可以发现 vue 依赖包也被排除了
预览构建产物 pnpm preview
- 跟完整引入的效果一样
2. 使用 rollup 自带的 external、output.globals
- 修改
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from 'rollup-plugin-visualizer'
// 文档的用法会报错, 要这样引入才可以
// import { Plugin as importToCDN, autoComplete } from 'vite-plugin-cdn-import'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
visualizer({ open: true }),
// importToCDN({
// modules: [
// autoComplete('vue'), // vue2 使用 autoComplete('vue2')
// {
// // 引入时的包名
// name: '@arco-design/web-vue',
// // app.use(), 全局注册时分配给模块的变量
// var: 'ArcoVue',
// // 根据自己的版本号找到对应的CDN网址
// path: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco-vue.min.js',
// // 根据自己的版本号找到对应的CDN网址
// css: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco.css',
// },
// ],
// }),
],
build: {
rollupOptions: {
external: ['vue', '@arco-design/web-vue'],
},
},
})
external
该选项用于匹配需要保留在 bundle 外部的模块,具体可以查看 官方文档
-
修改
index.html
, 手动引入下 CDN需要注意的是:这个 index.html 不是打包后的,是项目的入口 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 手动引入 vue、arco-design、arco.css -->
<script src="https://unpkg.com/vue@3.3.4/dist/vue.global.js"></script>
<script src="https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco-vue.min.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco.css"
/>
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
重新打包后预览,会出现报错:
具体可以参考这篇文章: Vite 中使用 cdn 来加载需要的库文件-前端/后端-繁花云
2.1. 使用 rollup-plugin-external-globals 插件来解决问题
安装插件
插件地址:rollup-plugin-external-globals
pnpm add rollup-plugin-external-globals -D
使用插件
- 修改
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from 'rollup-plugin-visualizer'
// 文档的用法会报错, 要这样引入才可以
// import { Plugin as importToCDN, autoComplete } from 'vite-plugin-cdn-import'
import externalGlobals from 'rollup-plugin-external-globals'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
visualizer({ open: true }),
// importToCDN({
// modules: [
// autoComplete('vue'), // vue2 使用 autoComplete('vue2')
// {
// // 引入时的包名
// name: '@arco-design/web-vue',
// // app.use(), 全局注册时分配给模块的变量
// var: 'ArcoVue',
// // 根据自己的版本号找到对应的CDN网址
// path: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco-vue.min.js',
// // 根据自己的版本号找到对应的CDN网址
// css: 'https://unpkg.com/@arco-design/web-vue@2.47.1/dist/arco.css',
// },
// ],
// }),
],
build: {
rollupOptions: {
external: ['vue', '@arco-design/web-vue'],
plugins: [
externalGlobals({
vue: 'Vue',
'@arco-design/web-vue': 'ArcoVue',
}) as any,
],
},
},
})
2.2. 编译测试
pnpm build
pnpm preview
- 打开网页发现原先报错已经不存在,问题解决。
四. 注意
使用 CDN 未必会加快速度,只能减小打包体积,因为对应 js 和 css 需要从远程地址读取