vue3 + vite 项目打包体积优化
如果不想听原理部分,可以直接跳到 开始使用
原理部分讲解
现在 vue3 已经逐渐成熟,所以想做几个 vue3 + vite 项目练练手
入口文件如下
import App from './App.vue'
import { router } from './route';
import {createApp} from 'vue';
import antd from 'ant-design-vue';
import "ant-design-vue/dist/antd.css"
const app = createApp(App)
app.use(router)
app.use(antd)
app.mount('#app')
就在我打算打包部署的时候,看到下面这张图的时候我直接傻了
1MB 多的 vendor 文件
然后我的项目打包体积优化之旅就开始了 …
在百度了一个下午之后,我放弃了。。。 根本没有人发布 vite 或者 vue3 应该如何优化体积的相关文章。
只能自己解决了,这里我想了很久才想到一个解决办法,因为 vue3 采用的是组合式Api,不可能单独的在 main.ts 删除引用,其他文件也会有引用,然后被打包进去,所以唯一的解决方法只能是对每个文件进行 import 修改, 吧
import xxx from 'xxx'
改成var xxx = xxx
这样才能引入外部 cdn 进行使用。
原理如下 :
- 写一个 vite 插件,对每个打包的文件进行处理
- 对每个文件的导入依赖进行判断,是否需要修改成 cdn 引入
- 进行依赖修改,吧所有
import
改成变量声明
,然后返回给 vite 进行打包处理, 由于没有import
所以 vite 不会打包相关的依赖,这样就实现了体积压缩 - 浏览器访问打包后的文件,因为 cdn 已经将全局变量挂载到
window
上,所以每个文件可以直接运行。
例子如下:
import _vue , {defineComponent as _d , ref as _ref , reactive} from 'vue'
import router from 'vue-router'
我们需要转换成如下语句 :
var _vue = window.Vue
var {defineComponent,ref,reactive} = window.Vue
var _d = defineComponent ;
var _ref = ref;
var router = window.VueRouter
这里必须着重讲一下为什么要加 window
在变量前,因为 ts 和 js 模块中的 this 指向并不是一样的,所以必须要在 window
变量中去访问 CDN 的全局变量,否则 Vue
或者 VueRouter
等变量将会是 undefined
开始使用
我写了一个 vite 插件
rollup-plugin-external-import
来解决 vue3 + ts 的体积优化问题
安装
# 安装
npm install rollup-plugin-external-import -D
在 vite.config.ts
中配置
import { ExternalImport, VueImport, VueRouterImport, AntDesignVueImport } from 'rollup-plugin-external-import';
export default defineConfig({
plugins: [
vue(),
// 配置外部导入处理
ExternalImport({
// vue
VueImport,
// vue-router
VueRouterImport,
// ant-design-vue
AntDesignVueImport,
// 自定义处理
{
importName: "axios",
variableName: "windos.axios"
}
})
],
})
引入CDN
unpkg
和jsdelivr
都是很好的 CDN 资源平台,按照自己的需求导入,唯一需要注意的就是variableName
要和 CDN 的全局变量名一致,并且带有window
前缀
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- vue -->
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
<!-- vue router -->
<script src="https://unpkg.com/[email protected]/dist/vue-router.global.js"></script>
<!-- ant desgin vue css-->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/antd.min.css" rel="stylesheet">
<!-- ant desgin vue js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/antd.min.js"></script>
<!-- axios -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
<title>xxxx</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
运行打包即可**
你不需要修改任何代码。
npm run build
打包后 1MB
压缩到了 26KB
将近优化了 50倍
解析
VueImport
VueRouterImport
AntDesignVueImport
…等等是默认提供的处理器,
ExternalImport({
// vue
VueImport,
// vue-router
VueRouterImport,
// ant-design-vue
AntDesignVueImport,
// 自定义处理
{
importName: "axios",
variableName: "windos.axios"
}
})
等同于
ExternalImport({
// vue
{
importName: "vue",
variableName: "windos.Vue"
},
// vue-router
{
importName: "vue-router",
variableName: "windos.VueRouter"
},
// ant-design-vue
{
importName: "ant-design-vue",
variableName: "windos.antd"
},
// 自定义处理
{
importName: "axios",
variableName: "windos.axios"
}
})
更多的 Api 和详情请移步到 github: https://github.com/enncy/rollup-plugin-external-import