打包相关
2026-03-31•5 min read
Gzip压缩#
安装vite-plugin-compression插件#
TYPESCRIPT
// https://vitejs.dev/config/
import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react-swc";
import path from "path";
import { createHtmlPlugin } from "vite-plugin-html";
import eslintPlugin from "vite-plugin-eslint";
import tailwindcss from "tailwindcss";
import autoprefixer from "autoprefixer";
// import { visualizer } from "rollup-plugin-visualizer";
import compression from "vite-plugin-compression";
// 解析路径
const _resolve = (dir) => path.resolve(__dirname, ".", dir);
const vendorChunkNames = [
"react",
"antd",
"handsontable",
"devextreme-datagrid",
"devextreme-contextmenu",
"devextreme-misc",
"devextreme-plugins",
"visactor",
"dataUtils",
"network",
"router",
"state",
"charts",
"tables",
"utils",
"excel",
"styles",
"vendor",
];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default defineConfig(({ command, mode }) => {
// 加载所有环境变量
const env = loadEnv(mode, "environment", "");
return {
plugins: [
react(),
createHtmlPlugin({
minify: true,
inject: {
data: {
title: env.VITE_SITE_TITLE,
},
},
}),
eslintPlugin({
include: ["src/**/*.ts", "src/!**/!*.tsx"],
}),
// visualizer({ open: false, filename: "dist/stats.html", gzipSize: true }),
compression({
algorithm: "gzip",
ext: ".gz",
threshold: 1024, // 小于 1kb 的文件不压缩
deleteOriginFile: false, // 不要删除原文件,保留 .js 和 .js.gz
}),
],
css: {
postcss: {
plugins: [tailwindcss, autoprefixer],
},
},
resolve: {
alias: {
"@": _resolve("src"),
inferno: command === "build" ? "inferno/dist/index.esm.js" : "inferno/dist/index.dev.esm.js",
},
},
build: {
assetsDir: "assets",
minify: "terser",
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true, // 移除 debugger
},
},
rollupOptions: {
output: {
// 分包配置
manualChunks: {
react: ["react", "react-dom"],
antd: ["antd", "@ant-design/icons", "@ant-design/pro-components"],
handsontable: ["@handsontable/react", "handsontable"],
"devextreme-datagrid": ["devextreme-react/data-grid"],
"devextreme-contextmenu": ["devextreme-react/context-menu"],
"devextreme-misc": [
"devextreme-react/select-box",
"devextreme-react/tree-list",
"devextreme-react/date-box",
],
"devextreme-plugins": [],
visactor: ["@visactor/react-vtable", "@visactor/vtable"],
dataUtils: ["lodash", "dayjs", "decimal.js", "numbro"],
network: ["axios", "rxjs"],
router: ["react-router-dom", "history"],
state: ["zustand"],
charts: ["echarts"],
tables: ["@dnd-kit/core", "@dnd-kit/sortable", "@dnd-kit/utilities"],
utils: ["uuid", "qrcode", "localforage", "ahooks", "classnames"],
excel: ["xlsx"],
styles: ["@emotion/react", "@emotion/styled", "@mui/material"],
vendor: ["@fingerprintjs/fingerprintjs", "normalize.css", "lz-string", "modern-screenshot"],
},
entryFileNames: (chunkInfo) => {
if (vendorChunkNames.includes(chunkInfo.name)) {
return "js/vendor/[name].[hash].js";
}
return `js/[name].[hash].js`;
},
chunkFileNames: (chunkInfo) => {
if (vendorChunkNames.includes(chunkInfo.name)) {
return "js/vendor/[name].[hash].js";
}
return `js/[name].[hash].js`;
},
assetFileNames: (assetInfo) => {
if (assetInfo.name.endsWith(".css")) {
if (
assetInfo.name.includes("vendor") ||
assetInfo.name.includes("antd") ||
assetInfo.name.includes("handsontable") ||
assetInfo.name.includes("devextreme") ||
assetInfo.name.includes("visactor")
) {
return "css/vendor/[name].css";
}
return "css/[name].[hash].css";
}
return "assets/[name].[hash][extname]";
},
},
},
},
envDir: "environment",
};
});
配置nginx#

查看是否生效

content-encoding 为 gzip的时候,代表已经生效
打包产物#


会有js和js.gz两份文件,一般是都留着,为了兼容性,当没有gz的时候,返回原始资源