如果不想听原理部分,可以直接跳到 开始使用
原理部分讲解
现在 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({
VueImport,
VueRouterImport,
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" />
<script src="https://unpkg.com/vue@3.2.6/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/vue-router@4.0.3/dist/vue-router.global.js"></script>
<link href="https://cdn.jsdelivr.net/npm/ant-design-vue@2.2.5/dist/antd.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/ant-design-vue@2.2.5/dist/antd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.21.1/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({
VueImport,
VueRouterImport,
AntDesignVueImport,
{
importName: "axios",
variableName: "windos.axios"
}
})
等同于
ExternalImport({
{
importName: "vue",
variableName: "windos.Vue"
},
{
importName: "vue-router",
variableName: "windos.VueRouter"
},
{
importName: "ant-design-vue",
variableName: "windos.antd"
},
{
importName: "axios",
variableName: "windos.axios"
}
})
更多的 Api 和详情请移步到 github: https://github.com/enncy/rollup-plugin-external-import
|