最近遇到一个需求,项目快截止了,由于项目太大,而且引入了非常多的库,导致发版速度很慢,而且由于打包时占用内存太大,更可能会导致jenkins的服务器崩溃,于是学到了使用cdn来CDN 优化前端打包体积
前端项目中打包体积过大、首次加载缓慢是常见的性能瓶颈之一。借助 CDN(内容分发网络)将第三方库从打包中剥离出去,是一种简单高效的优化手段。下面将介绍如何通过 CDN 优化打包体积,提高页面加载速度,并结合实际配置举例说明。
一.为什么要用 CDN?
-
减小打包体积:将像
react
、vue
、lodash
、axios
等第三方依赖剥离,不再打进 bundle 中。 -
提升首屏加载速度:CDN 的边缘节点更接近用户,静态资源加载更快。
-
缓存复用:公共库通过 CDN 引入,可被多个站点共享缓存,提升命中率。
什么是bundle?
bundle(打包文件) 是指前端项目构建后生成的 一个或多个包含 HTML、CSS、JavaScript 的压缩合并文件,它们是浏览器加载运行网站所需的最终资源。
更具体地说:
在开发时,我们写了很多模块化的 JS 文件(如 React 组件、Vue 页面、ESM 模块),这些文件可能:
-
使用了模块语法(如
import/export
) -
引入了第三方库(如
axios
、lodash
) -
包含了动态资源(如图片、字体)
但是浏览器不原生支持这些开发格式。于是我们用 打包工具(如 Webpack、Vite、Rollup)将这些源文件:
✅ 转换为浏览器能识别的格式
✅ 合并为一个或多个文件
✅ 压缩体积以优化加载速度
这个输出结果就叫做 bundle。
示例
开发时代码结构可能是这样的:
src/
├─ App.vue
├─ main.js
└─ components/
└─ Navbar.vue
打包后可能生成:
dist/
├─ index.html
├─ bundle.js ← 就是这个:所有 JS 和模板合并压缩后的文件
└─ style.css
总结一句话:
bundle 是前端构建工具将源代码和依赖打包压缩后生成的、供浏览器使用的最终资源文件。
二.配置vite.config.ts使用cdn加速
方式一:全自动
1.安装插件
npm install vite-plugin-cdn-import --save-dev
2. 配置 vite.config.ts
// vite.config.ts
import { defineConfig } from 'vite'
import importToCDN from 'vite-plugin-cdn-import'
export default defineConfig({
plugins: [
importToCDN({
modules: [
{
name: 'vue',
var: 'Vue',
path: 'https://cdn.jsdelivr.net/npm/vue@3.4.0/dist/vue.global.prod.js'
},
{
name: 'axios',
var: 'axios',
path: 'https://cdn.jsdelivr.net/npm/axios@1.6.7/dist/axios.min.js'
}
]
})
],
build: {
rollupOptions: {
external: ['vue', 'axios'] // 不打包这些依赖
}
}
})
3. 项目中照常使用:
import { createApp } from 'vue'
import axios from 'axios'
// 不用担心,虽然写了 import,但实际引用的是 CDN 版本
方法二:手动方式
1. 配置 rollupOptions.external
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
external: ['vue']
}
}
})
2. 修改 index.html
,引入 CDN:
<script src="https://cdn.jsdelivr.net/npm/vue@3.4.0/dist/vue.global.prod.js"></script>
注意:手动方式你需要确保 <script>
标签在 HTML 中写对,并且 CDN 加载顺序正确。
还有一个重要的点,就是虽然我们使用cdn,但是我们也不需要删除本地的依赖,而且使用import来引入使用第三方库时,也不用担心线上环境对库的使用
也就是说,使用cdn,本地开发依然使用本地依赖,线上环境使用cdn上的依赖
还有一个问题,如果我在本地使用import 引入使用库,但是本地依赖包没有打包上去,线上cdn使用库时也是import这个用法吗?
详细解释:
你在本地写的:
import { createApp } from 'vue'
这是 模块化语法,Vite 会在打包阶段处理这个 import
。
🛠 如果配置了 external: ['vue']
意味着:
-
打包的时候 Vite 会认为
vue
是“外部依赖” -
所以不会把
vue
打进 bundle 中 -
同时会把这个
import
替换成对全局变量Vue
的引用
比如你写的:
import { createApp } from 'vue'
Vite 会打包成:
const { createApp } = Vue;
👉 所以浏览器运行这段代码时,它不会再去 import
,而是直接使用了 CDN 提供的全局变量 Vue
external的名字怎么填?
你
import xxx from '模块名'
👉 那你在external
中就填'模块名'
常见库 external 对照表
你写的 import | external 配置 | 全局变量(CDN 上暴露) |
---|---|---|
import Vue from 'vue' | 'vue' | Vue |
import React from 'react' | 'react' | React |
import ReactDOM from 'react-dom' | 'react-dom' | ReactDOM |
import axios from 'axios' | 'axios' | axios |
import dayjs from 'dayjs' | 'dayjs' | dayjs |
import _ from 'lodash' | 'lodash' | _ |
import * as echarts from 'echarts' | 'echarts' | echarts |
⚠️ 注意事项
-
版本一致性:确保本地开发依赖和 CDN 引入的版本一致。
-
CDN 可用性保障:推荐使用稳定的 CDN,如 jsDelivr、UNPKG、CDNJS。
-
要确保 CDN
<script>
标签在你主 JS 文件之前加载
index.html:
<!-- 引入 Vue 的 CDN,暴露 window.Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@3.4.0/dist/vue.global.prod.js"></script>
<!-- 再加载你的打包代码 -->
<script type="module" src="/assets/index.js"></script>