Browse Source

feat: 打包构建添加可选 `gzip` 与 `brotli` 压缩模式

xiaoxian521 2 years ago
parent
commit
f5a75356df

+ 6 - 1
.env.production

@@ -11,4 +11,9 @@ VITE_PROXY_DOMAIN_REAL = ""
 VITE_LEGACY = false
 
 # 是否在打包时使用cdn替换本地库 替换 true 不替换 false
-VITE_CDN = false
+VITE_CDN = false
+
+# 是否启用gzip压缩或brotli压缩(分两种情况,删除原始文件和不删除原始文件)
+# 压缩时不删除原始文件的配置:gzip、brotli、both(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
+# 压缩时删除原始文件的配置:gzip-clear、brotli-clear、both-clear(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
+VITE_COMPRESSION = "none"

+ 6 - 1
.env.staging

@@ -14,4 +14,9 @@ VITE_PROXY_DOMAIN_REAL = ""
 VITE_LEGACY = false
 
 # 是否在打包时使用cdn替换本地库 替换 true 不替换 false
-VITE_CDN = false
+VITE_CDN = false
+
+# 是否启用gzip压缩或brotli压缩(分两种情况,删除原始文件和不删除原始文件)
+# 压缩时不删除原始文件的配置:gzip、brotli、both(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
+# 压缩时删除原始文件的配置:gzip-clear、brotli-clear、both-clear(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
+VITE_COMPRESSION = "none"

+ 63 - 0
build/compress.ts

@@ -0,0 +1,63 @@
+import type { Plugin } from "vite";
+import { isArray } from "@pureadmin/utils";
+import compressPlugin from "vite-plugin-compression";
+
+export const configCompressPlugin = (
+  compress: ViteCompression
+): Plugin | Plugin[] => {
+  if (compress === "none") return null;
+
+  const gz = {
+    // 生成的压缩包后缀
+    ext: ".gz",
+    // 体积大于threshold才会被压缩
+    threshold: 0,
+    // 默认压缩.js|mjs|json|css|html后缀文件,设置成true,压缩全部文件
+    filter: () => true,
+    // 压缩后是否删除原始文件
+    deleteOriginFile: false
+  };
+  const br = {
+    ext: ".br",
+    algorithm: "brotliCompress",
+    threshold: 0,
+    filter: () => true,
+    deleteOriginFile: false
+  };
+
+  const codeList = [
+    { k: "gzip", v: gz },
+    { k: "brotli", v: br },
+    { k: "both", v: [gz, br] }
+  ];
+
+  const plugins: Plugin[] = [];
+
+  codeList.forEach(item => {
+    if (compress.includes(item.k)) {
+      if (compress.includes("clear")) {
+        if (isArray(item.v)) {
+          item.v.forEach(vItem => {
+            plugins.push(
+              compressPlugin(Object.assign(vItem, { deleteOriginFile: true }))
+            );
+          });
+        } else {
+          plugins.push(
+            compressPlugin(Object.assign(item.v, { deleteOriginFile: true }))
+          );
+        }
+      } else {
+        if (isArray(item.v)) {
+          item.v.forEach(vItem => {
+            plugins.push(compressPlugin(vItem));
+          });
+        } else {
+          plugins.push(compressPlugin(item.v));
+        }
+      }
+    }
+  });
+
+  return plugins;
+};

+ 2 - 1
build/index.ts

@@ -8,7 +8,8 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
     VITE_PROXY_DOMAIN_REAL: "",
     VITE_ROUTER_HISTORY: "",
     VITE_LEGACY: false,
-    VITE_CDN: false
+    VITE_CDN: false,
+    VITE_COMPRESSION: "none"
   };
 
   for (const envName of Object.keys(envConf)) {

+ 4 - 1
build/plugins.ts

@@ -6,6 +6,7 @@ import svgLoader from "vite-svg-loader";
 import legacy from "@vitejs/plugin-legacy";
 import vueJsx from "@vitejs/plugin-vue-jsx";
 import { viteMockServe } from "vite-plugin-mock";
+import { configCompressPlugin } from "./compress";
 import VueI18n from "@intlify/vite-plugin-vue-i18n";
 import { visualizer } from "rollup-plugin-visualizer";
 import removeConsole from "vite-plugin-remove-console";
@@ -16,7 +17,8 @@ import DefineOptions from "unplugin-vue-define-options/vite";
 export function getPluginsList(
   command: string,
   VITE_LEGACY: boolean,
-  VITE_CDN: boolean
+  VITE_CDN: boolean,
+  VITE_COMPRESSION: ViteCompression
 ) {
   const prodMock = true;
   const lifecycle = process.env.npm_lifecycle_event;
@@ -31,6 +33,7 @@ export function getPluginsList(
     // jsx、tsx语法支持
     vueJsx(),
     VITE_CDN ? cdn : null,
+    configCompressPlugin(VITE_COMPRESSION),
     DefineOptions(),
     // 线上环境删除console
     removeConsole({ external: ["src/assets/iconfont/iconfont.js"] }),

+ 1 - 0
package.json

@@ -148,6 +148,7 @@
     "unplugin-vue-define-options": "0.7.3",
     "vite": "^3.1.8",
     "vite-plugin-cdn-import": "^0.3.5",
+    "vite-plugin-compression": "^0.5.1",
     "vite-plugin-mock": "^2.9.6",
     "vite-plugin-remove-console": "^1.1.0",
     "vite-svg-loader": "^3.6.0",

+ 18 - 0
pnpm-lock.yaml

@@ -106,6 +106,7 @@ specifiers:
   v-contextmenu: 3.0.0
   vite: ^3.1.8
   vite-plugin-cdn-import: ^0.3.5
+  vite-plugin-compression: ^0.5.1
   vite-plugin-mock: ^2.9.6
   vite-plugin-remove-console: ^1.1.0
   vite-svg-loader: ^3.6.0
@@ -246,6 +247,7 @@ devDependencies:
   unplugin-vue-define-options: 0.7.3_vite@3.1.8+vue@3.2.40
   vite: 3.1.8_sass@1.55.0+terser@5.15.1
   vite-plugin-cdn-import: 0.3.5
+  vite-plugin-compression: 0.5.1_vite@3.1.8
   vite-plugin-mock: 2.9.6_mockjs@1.1.0+vite@3.1.8
   vite-plugin-remove-console: 1.1.0
   vite-svg-loader: 3.6.0
@@ -8736,6 +8738,22 @@ packages:
       - rollup
     dev: true
 
+  /vite-plugin-compression/0.5.1_vite@3.1.8:
+    resolution:
+      {
+        integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==
+      }
+    peerDependencies:
+      vite: ">=2.0.0"
+    dependencies:
+      chalk: 4.1.2
+      debug: 4.3.4
+      fs-extra: 10.1.0
+      vite: 3.1.8_sass@1.55.0+terser@5.15.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /vite-plugin-mock/2.9.6_mockjs@1.1.0+vite@3.1.8:
     resolution:
       {

+ 7 - 12
src/views/permission/button/index.vue

@@ -6,20 +6,21 @@ defineOptions({
   name: "PermissionButton"
 });
 
-let width = computed((): CSSProperties => {
+let elStyle = computed((): CSSProperties => {
   return {
-    width: "85vw"
+    width: "85vw",
+    justifyContent: "start"
   };
 });
 </script>
 
 <template>
   <el-space direction="vertical" size="large">
-    <el-tag :style="width" size="large" effect="dark">
+    <el-tag :style="elStyle" size="large" effect="dark">
       当前拥有的code列表:{{ getAuths() }}
     </el-tag>
 
-    <el-card shadow="never" :style="width">
+    <el-card shadow="never" :style="elStyle">
       <template #header>
         <div class="card-header">组件方式判断权限</div>
       </template>
@@ -36,7 +37,7 @@ let width = computed((): CSSProperties => {
       </Auth>
     </el-card>
 
-    <el-card shadow="never" :style="width">
+    <el-card shadow="never" :style="elStyle">
       <template #header>
         <div class="card-header">函数方式判断权限</div>
       </template>
@@ -54,7 +55,7 @@ let width = computed((): CSSProperties => {
       </el-button>
     </el-card>
 
-    <el-card shadow="never" :style="width">
+    <el-card shadow="never" :style="elStyle">
       <template #header>
         <div class="card-header">
           指令方式判断权限(该方式不能动态修改权限)
@@ -72,9 +73,3 @@ let width = computed((): CSSProperties => {
     </el-card>
   </el-space>
 </template>
-
-<style lang="scss" scoped>
-:deep(.el-tag) {
-  justify-content: start;
-}
-</style>

+ 5 - 10
src/views/permission/page/index.vue

@@ -8,9 +8,10 @@ defineOptions({
   name: "PermissionPage"
 });
 
-let width = computed((): CSSProperties => {
+let elStyle = computed((): CSSProperties => {
   return {
-    width: "85vw"
+    width: "85vw",
+    justifyContent: "start"
   };
 });
 
@@ -41,10 +42,10 @@ function onChange() {
 
 <template>
   <el-space direction="vertical" size="large">
-    <el-tag :style="width" size="large" effect="dark">
+    <el-tag :style="elStyle" size="large" effect="dark">
       模拟后台根据不同角色返回对应路由,观察左侧菜单变化(管理员角色可查看系统管理菜单、普通角色不可查看系统管理菜单)
     </el-tag>
-    <el-card shadow="never" :style="width">
+    <el-card shadow="never" :style="elStyle">
       <template #header>
         <div class="card-header">
           <span>当前角色:{{ username }}</span>
@@ -61,9 +62,3 @@ function onChange() {
     </el-card>
   </el-space>
 </template>
-
-<style lang="scss" scoped>
-:deep(.el-tag) {
-  justify-content: start;
-}
-</style>

+ 10 - 0
types/global.d.ts

@@ -74,6 +74,15 @@ declare global {
     __: unknown;
   }
 
+  type ViteCompression =
+    | "none"
+    | "gzip"
+    | "brotli"
+    | "both"
+    | "gzip-clear"
+    | "brotli-clear"
+    | "both-clear";
+
   declare interface ViteEnv {
     VITE_PORT: number;
     VITE_PUBLIC_PATH: string;
@@ -82,6 +91,7 @@ declare global {
     VITE_ROUTER_HISTORY: string;
     VITE_LEGACY: boolean;
     VITE_CDN: boolean;
+    VITE_COMPRESSION: ViteCompression;
   }
 
   declare interface ServerConfigs {

+ 2 - 1
vite.config.ts

@@ -30,6 +30,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
     VITE_CDN,
     VITE_PORT,
     VITE_LEGACY,
+    VITE_COMPRESSION,
     VITE_PUBLIC_PATH,
     VITE_PROXY_DOMAIN,
     VITE_PROXY_DOMAIN_REAL
@@ -60,7 +61,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
             }
           : null
     },
-    plugins: getPluginsList(command, VITE_LEGACY, VITE_CDN),
+    plugins: getPluginsList(command, VITE_LEGACY, VITE_CDN, VITE_COMPRESSION),
     optimizeDeps: {
       include: ["pinia", "vue-i18n", "lodash-es", "@vueuse/core", "dayjs"],
       exclude: ["@pureadmin/theme/dist/browser-utils"]