vite打包: 体积/速度优化/global/external/终极优化方案
后台系统的 js 体积优化
背景
因为我的大部分项目都是基于
react/react-dom/antd
来实现的,之前一直用 cra,现在是用 vite 来开发。优化方向:
react/react-dom/antd
以全量方式引入项目,并走cdn,不走打包流程。
vite.confg.ts
- 坑1: 网上推荐的方式
build:{ rollupOptions: …}
这种方式并不能使用,react 就报各种错误 - 坑2:
antd
需要dayjs
的依赖
方式1: external
推荐方式,与
webpack
达到类似的效果,完全不用对原有代码进行任何改造项目: https://github.com/aric-tpls/vite-external-pkgs
实际项目中的改进:
- 可以将
external + globals
那部分进一步封装- 将
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" />
<title>Vite + React + TS</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.7/dayjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/5.3.1/antd.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/5.3.1/reset.min.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
external: ["react", "react-dom", "antd"],
output: {
format: "umd",
globals: {
react: "React",
"react-dom": "ReactDOM",
antd: "antd",
},
},
},
},
});
方式2: 需要代码上的改造,与正常写法不一致
- 在
src/vite-env.d.ts
添加配置(这一步不完美,现在没有找到更好的方式) vite.config.ts
: 重点关注这个配置optimizeDeps
- 代码层面做一些改造
- 缺点:这种方式需要对 import ‘react’ 这种代码进行改造,所以不适合已经存在的项目
vite.env.d.ts
/// <reference types="vite/client" />
declare var nx: any;
declare var antd: any
vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
optimizeDeps: {
include: ["react", "react-dom","antd"],
}
});
main.tsx
const { useState } = React;
const { render } = ReactDOM;
const { Button } = antd;
function App() {
const [count, setCount] = useState(0);
function handleClick() {
console.log(nx, antd);
setCount((c) => c + 1);
}
return (
<div onClick={handleClick}>
<p>You clicked {count} times</p>
<Button type="primary">Btn.aric</Button>
</div>
);
}
render(<App />, document.getElementById("root"));
知识点
- integrity:这个属性
sha512
-value,分成这2部分构成 - value的算法是:base64(sha512(file_content_string))
<script
src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"
integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
如何计算 intergrity
import hashlib
import base64
import urllib.request
url = 'https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js'
with urllib.request.urlopen(url) as response:
sha512_hash = hashlib.sha512()
while True:
data = response.read(8192)
if not data:
break
sha512_hash.update(data)
sha512_digest = sha512_hash.digest()
sha512_base64 = base64.b64encode(sha512_digest).decode('utf-8')
print(f"SHA512 hash (Base64 encoded) of {url}: {sha512_base64}")
vite打包出错问题
rollup default.default error
https://www.cnblogs.com/mmykdbc/p/16319498.html
https://www.dianjilingqu.com/669177.html
https://stackoverflow.com/questions/61237208/rollup-error-default-is-not-exported-by-node-modules-react-index-js
最终方案
可以大幅度提是升开发时候的速度 + ci 里的打包速度(因为这些大库,已经不打包了)
- optimizeDeps: 优化开发速度,需要将
React → window.React
对已有项目不友好 - buildOptions 配置,优化esbuild打包速度
- 使用 vite-plugin-externals 插件,自动将 import 语法转化为 window.React 这种形式
安装包
vite-plugin-externals
yarn add --dev vite-plugin-externals
vite.config.ts
极简配置如下:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { viteExternalsPlugin } from "vite-plugin-externals";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
viteExternalsPlugin({
"react": "React",
"react-dom": "ReactDOM",
"antd": "antd",
}),
],
build: {
rollupOptions: {
external: ["react", "react-dom", "antd"],
output: {
format: "umd",
globals: {
"react": "React",
"react-dom": "ReactDOM",
"antd": "antd",
},
},
},
},
});
优化记录 ⚡️
优化过程中的一些参数/效果对比。
优化前后 | vite | .vite 缓存情况 |
---|---|---|
优化前 |
| |
优化后 |
|
参考
- https://developer.aliyun.com/article/1166403
- https://juejin.cn/post/7169962518373203975
- https://cdnjs.com/libraries/dayjs
- https://github.com/vitejs/vite/issues/7588
- https://github.com/vitejs/vite-plugin-react/issues/3
- https://cn.vitejs.dev/config/dep-optimization-options.html#optimizedeps-entries
- https://www.cnblogs.com/givingwu/p/15223160.html