瀏覽代碼

refactor: add vite-plugin-html. Delete updateHtml related logic

vben 4 年之前
父節點
當前提交
173d402162

+ 14 - 1
CHANGELOG.zh_CN.md

@@ -1,4 +1,17 @@
-## # 2.0.0-rc.5 (2020-10-26)
+## Wip
+
+### 🎫 Chores
+
+- 升级 vite 版本为`v1.0.0.rc8`
+- vite.config.ts 内部 plugins 抽取
+- build 目录结构调整
+- 依赖更新
+
+### ✨ Refactor
+
+- 独立出`vite-plugin-html`,并修改相关插入 html 的逻辑
+
+## 2.0.0-rc.5 (2020-10-26)
 
 ### ✨ Features
 

+ 8 - 0
README.en-US.md

@@ -31,6 +31,7 @@
 - [Finished features](#finished-features)
 - [Developing features](#developing-features)
 - [Browser support](#browser-support)
+- [Plugins](#plugins)
 
 ## Introduction
 
@@ -250,3 +251,10 @@ Support modern browsers, Not currently supported ie11,Follow-up consideration
 | not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
 
 More browsers can view [Can I Use Es Module](https://caniuse.com/?search=ES%20Module)
+
+## Plugins
+
+If these plugins are helpful to you, you can give a star
+
+- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock)
+- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html)

+ 8 - 0
README.md

@@ -31,6 +31,7 @@
 - [已完成功能](#已完成功能)
 - [正在开发的功能](#正在开发的功能)
 - [浏览器支持](#浏览器支持)
+- [插件](#插件-1)
 - [加入我们](#加入我们)
 
 ## 介绍
@@ -249,6 +250,13 @@ yarn clean:lib # 删除node_modules,兼容window系统
 
 更多浏览器可以查看 [Can I Use Es Module](https://caniuse.com/?search=ES%20Module)
 
+## 插件
+
+如果这些插件对你有帮助,可以给一个 star 支持下
+
+- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock)
+- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html)
+
 ## 加入我们
 
 `Vue-Vben-Aadmin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群(项目刚起步,人数较少,有兴趣的可以加群一起讨论),使用问题欢迎在群内提问。

+ 0 - 0
build/config/glob/lessModifyVars.ts → build/config/lessModifyVars.ts


+ 4 - 4
build/script/postBuild.ts

@@ -4,15 +4,15 @@ import { sh } from 'tasksfile';
 
 import { argv } from 'yargs';
 import { runBuildConfig } from './buildConf';
-import { runUpdateHtml } from './updateHtml';
+// import { runUpdateHtml } from './updateHtml';
 import { errorConsole, successConsole } from '../utils';
-import { startGzipStyle } from '../plugin/gzip/compress';
+import { startGzipStyle } from '../vite/plugin/gzip/compress';
 
 export const runBuild = async (preview = false) => {
   try {
     const argvList = argv._;
     if (preview) {
-      let cmd = `npm run build`;
+      let cmd = `cross-env NODE_ENV=production vite build`;
       await sh(cmd, {
         async: true,
         nopipe: true,
@@ -23,7 +23,7 @@ export const runBuild = async (preview = false) => {
     if (!argvList.includes('no-conf')) {
       await runBuildConfig();
     }
-    await runUpdateHtml();
+    // await runUpdateHtml();
     if (!preview) {
       await startGzipStyle();
     }

+ 0 - 103
build/script/updateHtml.ts

@@ -1,103 +0,0 @@
-import { readFileSync, writeFileSync, existsSync } from 'fs-extra';
-import viteConfig, { htmlConfig } from '../../vite.config';
-import { getCwdPath, successConsole, errorConsole } from '../utils';
-import { GLOB_CONFIG_FILE_NAME } from '../constant';
-import { hmScript } from './hm';
-import HtmlMinifier from 'html-minifier';
-const pkg = require('../../package.json');
-
-const { title, addHm, cdnConf, useCdn, minify } = htmlConfig;
-
-function injectTitle(html: string, htmlTitle: string) {
-  if (/<\/title>/.test(html)) {
-    return html.replace(/<\/title>/, `${htmlTitle}</title>`);
-  }
-  return html;
-}
-
-function injectConfigScript(html: string) {
-  const tag = `\t\t<script  src='${viteConfig.base || './'}${GLOB_CONFIG_FILE_NAME}?v=${
-    pkg.version
-  }-${new Date().getTime()}'></script>`;
-
-  if (/<\/head>/.test(html)) {
-    return html.replace(/<\/head>/, `${tag}\n\t\t</head>`);
-  }
-  return html;
-}
-
-function injectHmScript(html: string) {
-  if (/<head>/.test(html)) {
-    return html.replace(/<head>/, `<head>\n${hmScript}`);
-  }
-  return html;
-}
-
-function injectCdnCss(html: string) {
-  if (!cdnConf) return html;
-  const { css } = cdnConf;
-  if (!css || css.length === 0) return html;
-
-  let cdnCssTag = '';
-  for (const cssLink of css) {
-    cdnCssTag += `<link rel="stylesheet" href="${cssLink}">`;
-  }
-  if (/<\/head>/.test(html)) {
-    return html.replace(/<\/head>/, `${cdnCssTag}\n\t\t</head>`);
-  }
-  return html;
-}
-
-function injectCdnjs(html: string) {
-  if (!cdnConf) return html;
-  const { js } = cdnConf;
-  if (!js || js.length === 0) return html;
-
-  let cdnJsTag = '';
-  for (const src of js) {
-    // TODO
-    // <script type="importmap">
-    // { "imports": {
-    //   "vue":        "https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0/vue.esm-browser.js",
-    //   "vue-router": "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.0-alpha.13/vue-router.esm.js",
-    //   "vuex":       "https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.0-beta.2/vuex.esm-browser.js"
-    // } }
-    // </script>
-    cdnJsTag += `\t<script type="text/javascript" src="${src}"></script>\n`;
-  }
-  if (/<\/body>/.test(html)) {
-    return html.replace(/<\/body>/, `${cdnJsTag}\n</body>`);
-  }
-  return html;
-}
-
-export async function runUpdateHtml() {
-  const outDir = viteConfig.outDir || 'dist';
-  const indexPath = getCwdPath(outDir, 'index.html');
-  if (!existsSync(indexPath)) return;
-  try {
-    let processedHtml = '';
-    const rawHtml = readFileSync(indexPath, 'utf-8');
-    processedHtml = rawHtml;
-    processedHtml = injectTitle(processedHtml, title);
-    processedHtml = injectConfigScript(processedHtml);
-    if (addHm) {
-      processedHtml = injectHmScript(processedHtml);
-    }
-    if (useCdn) {
-      processedHtml = injectCdnCss(processedHtml);
-      processedHtml = injectCdnjs(processedHtml);
-    }
-    if (minify) {
-      const { enable, ...miniOpt } = minify;
-      if (enable) {
-        processedHtml = HtmlMinifier.minify(processedHtml, miniOpt);
-      }
-    }
-
-    writeFileSync(indexPath, processedHtml);
-    successConsole('Update Html Successfully!');
-  } catch (error) {
-    errorConsole('Update Html Error\n' + error);
-  }
-}

+ 0 - 0
build/config/vite/cdn.ts → build/vite/cdn.ts


+ 0 - 0
build/script/hm.ts → build/vite/hm.ts


+ 0 - 1
build/plugin/vite-plugin-context/transform.ts → build/vite/plugin/context/transform.ts

@@ -2,7 +2,6 @@
 // https://github.com/luxueyan/vite-transform-globby-import/blob/master/src/index.ts
 
 // TODO 目前还不能监听文件新增及删除 内容已经改变,缓存问题?
-// 可以使用,先不打算集成
 import { join } from 'path';
 import { lstatSync } from 'fs';
 import glob from 'glob';

+ 2 - 2
build/plugin/gzip/compress.ts → build/vite/plugin/gzip/compress.ts

@@ -1,8 +1,8 @@
 import { gzip } from 'zlib';
 import { readFileSync, writeFileSync } from 'fs';
 import { GzipPluginOptions } from './types';
-import viteConfig from '../../../vite.config';
-import { readAllFile, getCwdPath, isBuildGzip, isSiteMode } from '../../utils';
+import viteConfig from '../../../../vite.config';
+import { readAllFile, getCwdPath, isBuildGzip, isSiteMode } from '../../../utils';
 
 export function startGzip(
   fileContent: string | Buffer,

+ 0 - 0
build/plugin/gzip/index.ts → build/vite/plugin/gzip/index.ts


+ 0 - 0
build/plugin/gzip/types.ts → build/vite/plugin/gzip/types.ts


+ 76 - 0
build/vite/plugin/index.ts

@@ -0,0 +1,76 @@
+import type { Plugin as VitePlugin } from 'vite';
+import type { Plugin as rollupPlugin } from 'rollup';
+
+import { createMockServer } from 'vite-plugin-mock';
+import ViteHtmlPlugin from 'vite-plugin-html';
+import PurgeIcons from 'vite-plugin-purge-icons';
+
+import visualizer from 'rollup-plugin-visualizer';
+import gzipPlugin from './gzip/index';
+
+import { hmScript } from '../hm';
+
+const pkg = require('../../../package.json');
+
+import { isDevFn, isProdFn, isSiteMode, ViteEnv, isReportMode, isBuildGzip } from '../../utils';
+import { GLOB_CONFIG_FILE_NAME } from '../../constant';
+
+// gen vite plugins
+export function createVitePlugins(viteEnv: ViteEnv) {
+  const { VITE_USE_MOCK, VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = viteEnv;
+
+  const vitePlugins: VitePlugin[] = [];
+
+  // vite-plugin-html
+  vitePlugins.push(
+    ViteHtmlPlugin({
+      // html title
+      title: VITE_GLOB_APP_TITLE,
+      minify: isProdFn(),
+      options: {
+        // Package and insert additional configuration files
+        injectConfig: isProdFn()
+          ? `<script src='${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${
+              pkg.version
+            }-${new Date().getTime()}'></script>`
+          : '',
+        // Insert Baidu statistics code
+        hmScript: isSiteMode() ? hmScript : '',
+      },
+    })
+  );
+
+  // vite-plugin-purge-icons
+  vitePlugins.push(PurgeIcons());
+
+  // vite-plugin-mock
+  if (isDevFn() && VITE_USE_MOCK) {
+    // open mock
+    vitePlugins.push(
+      createMockServer({
+        ignore: /^\_/,
+        mockPath: 'mock',
+      })
+    );
+  }
+  return vitePlugins;
+}
+
+// gen rollup plugins
+export function createRollupPlugin() {
+  const rollupPlugins: rollupPlugin[] = [];
+
+  if (isProdFn()) {
+    if (isReportMode()) {
+      // rollup-plugin-visualizer
+      rollupPlugins.push(
+        visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin
+      );
+    }
+    if (isBuildGzip() || isSiteMode()) {
+      // rollup-plugin-gizp
+      rollupPlugins.push(gzipPlugin());
+    }
+  }
+  return rollupPlugins;
+}

+ 0 - 0
build/config/vite/proxy.ts → build/vite/proxy.ts


+ 2 - 0
index.html

@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
   <head>
+    <%= viteHtmlPluginOptions.hmScript %>
     <meta charset="UTF-8" />
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
     <meta name="renderer" content="webkit" />
@@ -10,6 +11,7 @@
     />
     <title></title>
     <link rel="icon" href="/favicon.ico" />
+    <%= viteHtmlPluginOptions.injectConfig %>
   </head>
   <body>
     <div id="app">

+ 2 - 3
package.json

@@ -4,7 +4,7 @@
   "scripts": {
     "bootstrap": "yarn install",
     "serve": "esno ./build/script/preserve.ts && cross-env NODE_ENV=development vite",
-    "build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
+    "build": "rimraf dist && cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
     "build:site": "cross-env SITE=true npm run build ",
     "build:no-cache": "yarn  clean:cache && npm run build",
     "report": "cross-env REPORT=true npm run build ",
@@ -48,7 +48,6 @@
     "@purge-icons/generated": "^0.4.1",
     "@types/echarts": "^4.8.3",
     "@types/fs-extra": "^9.0.2",
-    "@types/html-minifier": "^4.0.0",
     "@types/koa-static": "^4.0.1",
     "@types/lodash-es": "^4.17.3",
     "@types/mockjs": "^1.0.3",
@@ -72,7 +71,6 @@
     "eslint-plugin-vue": "^7.1.0",
     "esno": "^0.2.4",
     "fs-extra": "^9.0.1",
-    "html-minifier": "^4.0.0",
     "husky": "^4.3.0",
     "koa-static": "^5.0.0",
     "less": "^3.12.2",
@@ -90,6 +88,7 @@
     "tasksfile": "^5.1.1",
     "ts-node": "^9.0.0",
     "typescript": "^4.0.5",
+    "vite-plugin-html": "^1.0.0-beta.2",
     "vite-plugin-mock": "^1.0.4",
     "vite-plugin-purge-icons": "^0.4.4",
     "vue-eslint-parser": "^7.1.1",

+ 1 - 1
src/settings/projectSetting.ts

@@ -2,7 +2,7 @@ import type { ProjectConfig } from '/@/types/config';
 
 import { MenuTypeEnum, MenuThemeEnum, MenuModeEnum } from '/@/enums/menuEnum';
 import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
-import { primaryColor } from '../../build/config/glob/lessModifyVars';
+import { primaryColor } from '../../build/config/lessModifyVars';
 import { isProdMode } from '/@/utils/env';
 // ! 改动后需要清空浏览器缓存
 const setting: ProjectConfig = {

+ 13 - 85
vite.config.ts

@@ -1,63 +1,31 @@
+import type { UserConfig } from 'vite';
+
 import { resolve } from 'path';
 
-import type { UserConfig, Plugin as VitePlugin } from 'vite';
+import { modifyVars } from './build/config/lessModifyVars';
+import { createProxy } from './build/vite/proxy';
+import globbyTransform from './build/vite/plugin/context/transform';
+
+import { isDevFn, loadEnv } from './build/utils';
 
-import visualizer from 'rollup-plugin-visualizer';
-import { modifyVars } from './build/config/glob/lessModifyVars';
-import {
-  // externals,
-  cdnConf,
-} from './build/config/vite/cdn';
-import { createProxy } from './build/config/vite/proxy';
-import { createMockServer } from 'vite-plugin-mock';
-import PurgeIcons from 'vite-plugin-purge-icons';
-import gzipPlugin from './build/plugin/gzip/index';
-import globbyTransform from './build/plugin/vite-plugin-context/transform';
+import { createRollupPlugin, createVitePlugins } from './build/vite/plugin';
 
-import { isDevFn, isReportMode, isProdFn, loadEnv, isBuildGzip, isSiteMode } from './build/utils';
 const pkg = require('./package.json');
 
+const viteEnv = loadEnv();
+
 const {
-  VITE_USE_MOCK,
   VITE_PORT,
   VITE_PUBLIC_PATH,
   VITE_PROXY,
-  VITE_GLOB_APP_TITLE,
   VITE_DROP_CONSOLE,
   // VITE_USE_CDN,
-} = loadEnv();
+} = viteEnv;
 
 function pathResolve(dir: string) {
   return resolve(__dirname, '.', dir);
 }
 
-const rollupPlugins: any[] = [];
-const vitePlugins: VitePlugin[] = [];
-
-(() => {
-  if (isProdFn()) {
-    if (isReportMode()) {
-      // report
-      rollupPlugins.push(
-        visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin
-      );
-    }
-    if (isBuildGzip() || isSiteMode()) {
-      rollupPlugins.push(gzipPlugin());
-    }
-  }
-
-  if (isDevFn() && VITE_USE_MOCK) {
-    // open mock
-    vitePlugins.push(
-      createMockServer({
-        ignore: /^\_/,
-        mockPath: 'mock',
-      })
-    );
-  }
-})();
-
 const viteConfig: UserConfig = {
   /**
    * Entry. Use this to specify a js entry file in use cases where an
@@ -152,54 +120,14 @@ const viteConfig: UserConfig = {
 
   // 本地跨域代理
   proxy: createProxy(VITE_PROXY),
-
-  plugins: [PurgeIcons(), ...vitePlugins],
-  rollupOutputOptions: {},
+  plugins: createVitePlugins(viteEnv),
   rollupInputOptions: {
     // TODO
     // external: VITE_USE_CDN ? externals : [],
-    plugins: rollupPlugins,
+    plugins: createRollupPlugin(),
   },
 };
 
-// 扩展配置, 往打包后的html注入内容
-// 只针对生产环境
-// TODO 目前只是简单手动注入实现,后续vite应该会提供配置项
-export const htmlConfig: {
-  title: string;
-  addHm?: boolean;
-  cdnConf?: {
-    css?: string[];
-    js?: string[];
-  };
-  useCdn: boolean;
-  minify: {
-    enable: boolean;
-    removeComments: boolean;
-    collapseWhitespace: boolean;
-    minifyJS: boolean;
-    minifyCSS: boolean;
-  };
-} = {
-  // html title
-  title: VITE_GLOB_APP_TITLE,
-  // 百度统计,不需要可以删除
-  // 用于打包部署站点使用。实际项目可以删除
-  addHm: isSiteMode(),
-  // 使用cdn打包
-  // TODO Cdn esm使用方式需要只能支持google,暂时关闭,后续查询更好的方式
-  useCdn: false,
-  // useCdn: VITE_USE_CDN,
-  // cdn列表
-  cdnConf,
-  minify: {
-    enable: true,
-    removeComments: true,
-    collapseWhitespace: true,
-    minifyJS: true,
-    minifyCSS: true,
-  },
-};
 export default {
   ...viteConfig,
   transforms: [globbyTransform(viteConfig)],

+ 94 - 86
yarn.lock

@@ -352,10 +352,10 @@
   resolved "https://registry.npmjs.org/@commitlint/types/-/types-11.0.0.tgz#719cf05fcc1abb6533610a2e0f5dd1e61eac14fe"
   integrity sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ==
 
-"@eslint/eslintrc@^0.2.0":
-  version "0.2.0"
-  resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.0.tgz#bc7e3c4304d4c8720968ccaee793087dfb5fe6b4"
-  integrity sha512-+cIGPCBdLCzqxdtwppswP+zTsH9BOIGzAeKfBIbtb4gW/giMlfMwP0HUSFfhzh20f9u8uZ8hOp62+4GPquTbwQ==
+"@eslint/eslintrc@^0.2.1":
+  version "0.2.1"
+  resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c"
+  integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==
   dependencies:
     ajv "^6.12.4"
     debug "^4.1.1"
@@ -496,11 +496,10 @@
     picomatch "^2.2.2"
 
 "@rollup/pluginutils@^4.0.0":
-  version "4.0.0"
-  resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.0.0.tgz#e18e9f5a3925779fc15209dd316c1bd260d195ef"
-  integrity sha512-b5QiJRye4JlSg29bKNEECoKbLuPXZkPEHSgEjjP1CJV1CPdDBybfYHfm6kyq8yK51h/Zsyl8OvWUrp0FUBukEQ==
+  version "4.1.0"
+  resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz#0dcc61c780e39257554feb7f77207dceca13c838"
+  integrity sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==
   dependencies:
-    "@types/estree" "0.0.45"
     estree-walker "^2.0.1"
     picomatch "^2.2.2"
 
@@ -542,13 +541,6 @@
     "@types/connect" "*"
     "@types/node" "*"
 
-"@types/clean-css@*":
-  version "4.2.2"
-  resolved "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.2.tgz#99fd79f6939c2b325938a1c569712e07dd97d709"
-  integrity sha512-xiTJn3bmDh1lA8c6iVJs4ZhHw+pcmxXlJQXOB6G1oULaak8rmarIeFKI4aTJ7849dEhaO612wgIualZfbxTJwA==
-  dependencies:
-    "@types/node" "*"
-
 "@types/connect@*":
   version "3.4.33"
   resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
@@ -578,7 +570,7 @@
   dependencies:
     "@types/zrender" "*"
 
-"@types/estree@*", "@types/estree@0.0.45":
+"@types/estree@*":
   version "0.0.45"
   resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
   integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
@@ -614,15 +606,6 @@
   dependencies:
     "@types/node" "*"
 
-"@types/html-minifier@^4.0.0":
-  version "4.0.0"
-  resolved "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-4.0.0.tgz#2065cb9944f2d1b241146707c6935aa7b947d279"
-  integrity sha512-eFnGhrKmjWBlnSGNtunetE3UU2Tc/LUl92htFslSSTmpp9EKHQVcYQadCyYfnzUEFB5G/3wLWo/USQS/mEPKrA==
-  dependencies:
-    "@types/clean-css" "*"
-    "@types/relateurl" "*"
-    "@types/uglify-js" "*"
-
 "@types/http-assert@*":
   version "1.5.1"
   resolved "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b"
@@ -712,9 +695,9 @@
   integrity sha512-OlwyyyoY81P8f7FU0zILUPxqQQ3/W+CwbqI6dWvOxaH8w948fAl1+hOG9C9ZgJcwzG+aloJcsastY4c4p91R1Q==
 
 "@types/node@*":
-  version "14.14.3"
-  resolved "https://registry.npmjs.org/@types/node/-/node-14.14.3.tgz#e1c09064121f894baaad2bd9f12ce4a41bffb274"
-  integrity sha512-33/L34xS7HVUx23e0wOT2V1qPF1IrHgQccdJVm9uXGTB9vFBrrzBtkQymT8VskeKOxjz55MSqMv0xuLq+u98WQ==
+  version "14.14.5"
+  resolved "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz#e92d3b8f76583efa26c1a63a21c9d3c1143daa29"
+  integrity sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw==
 
 "@types/normalize-package-data@^2.4.0":
   version "2.4.0"
@@ -748,11 +731,6 @@
   resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
   integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
 
-"@types/relateurl@*":
-  version "0.2.28"
-  resolved "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"
-  integrity sha1-a9p9uGU/piZD9e5p6facEaOS46Y=
-
 "@types/resolve@1.17.1":
   version "1.17.1"
   resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
@@ -776,13 +754,6 @@
     "@types/mime" "*"
     "@types/node" "*"
 
-"@types/uglify-js@*":
-  version "3.11.0"
-  resolved "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.0.tgz#2868d405cc45cd9dc3069179052103032c33afbc"
-  integrity sha512-I0Yd8TUELTbgRHq2K65j8rnDPAzAP+DiaF/syLem7yXwYLsHZhPd+AM2iXsWmf9P2F2NlFCgl5erZPQx9IbM9Q==
-  dependencies:
-    source-map "^0.6.1"
-
 "@types/unist@^2.0.0", "@types/unist@^2.0.2":
   version "2.0.3"
   resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
@@ -1422,13 +1393,13 @@ callsites@^3.0.0:
   resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
   integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
 
-camel-case@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
-  integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
+camel-case@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547"
+  integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==
   dependencies:
-    no-case "^2.2.0"
-    upper-case "^1.1.1"
+    pascal-case "^3.1.1"
+    tslib "^1.10.0"
 
 camelcase-keys@^2.0.0:
   version "2.1.0"
@@ -1571,7 +1542,7 @@ class-utils@^0.3.5:
     isobject "^3.0.0"
     static-extend "^0.1.1"
 
-clean-css@^4.2.1, clean-css@^4.2.3:
+clean-css@^4.2.3:
   version "4.2.3"
   resolved "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
   integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==
@@ -1724,11 +1695,16 @@ commander@*, commander@^6.0.0:
   resolved "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75"
   integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==
 
-commander@^2.19.0, commander@^2.20.0:
+commander@^2.20.0:
   version "2.20.3"
   resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
 
+commander@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
+  integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+
 commander@~2.14.1:
   version "2.14.1"
   resolved "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
@@ -2318,6 +2294,14 @@ domutils@^1.5.1:
     dom-serializer "0"
     domelementtype "1"
 
+dot-case@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa"
+  integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==
+  dependencies:
+    no-case "^3.0.3"
+    tslib "^1.10.0"
+
 dot-prop@^5.1.0:
   version "5.3.0"
   resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
@@ -2500,12 +2484,12 @@ eslint-visitor-keys@^2.0.0:
   integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
 
 eslint@^7.12.0:
-  version "7.12.0"
-  resolved "https://registry.npmjs.org/eslint/-/eslint-7.12.0.tgz#7b6a85f87a9adc239e979bb721cde5ce0dc27da6"
-  integrity sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA==
+  version "7.12.1"
+  resolved "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801"
+  integrity sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==
   dependencies:
     "@babel/code-frame" "^7.0.0"
-    "@eslint/eslintrc" "^0.2.0"
+    "@eslint/eslintrc" "^0.2.1"
     ajv "^6.10.0"
     chalk "^4.0.0"
     cross-spawn "^7.0.2"
@@ -3265,18 +3249,18 @@ hosted-git-info@^2.1.4:
   resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
   integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
 
-html-minifier@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz#cca9aad8bce1175e02e17a8c33e46d8988889f56"
-  integrity sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==
+html-minifier-terser@^5.1.1:
+  version "5.1.1"
+  resolved "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054"
+  integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==
   dependencies:
-    camel-case "^3.0.0"
-    clean-css "^4.2.1"
-    commander "^2.19.0"
+    camel-case "^4.1.1"
+    clean-css "^4.2.3"
+    commander "^4.1.1"
     he "^1.2.0"
-    param-case "^2.1.1"
+    param-case "^3.0.3"
     relateurl "^0.2.7"
-    uglify-js "^3.5.1"
+    terser "^4.6.3"
 
 html-tags@^3.1.0:
   version "3.1.0"
@@ -4298,10 +4282,12 @@ loud-rejection@^1.0.0:
     currently-unhandled "^0.4.1"
     signal-exit "^3.0.0"
 
-lower-case@^1.1.1:
-  version "1.1.4"
-  resolved "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
-  integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
+lower-case@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7"
+  integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==
+  dependencies:
+    tslib "^1.10.0"
 
 lru-cache@^5.1.1:
   version "5.1.1"
@@ -4650,12 +4636,13 @@ neo-async@^2.6.0:
   resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
   integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
 
-no-case@^2.2.0:
-  version "2.3.2"
-  resolved "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
-  integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
+no-case@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8"
+  integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==
   dependencies:
-    lower-case "^1.1.1"
+    lower-case "^2.0.1"
+    tslib "^1.10.0"
 
 node-emoji@^1.10.0:
   version "1.10.0"
@@ -4902,12 +4889,13 @@ p-try@^2.0.0:
   resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
-param-case@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
-  integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
+param-case@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.npmjs.org/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238"
+  integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==
   dependencies:
-    no-case "^2.2.0"
+    dot-case "^3.0.3"
+    tslib "^1.10.0"
 
 parent-module@^1.0.0:
   version "1.0.1"
@@ -4968,6 +4956,14 @@ parseurl@^1.3.2:
   resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
   integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
 
+pascal-case@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f"
+  integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==
+  dependencies:
+    no-case "^3.0.3"
+    tslib "^1.10.0"
+
 pascalcase@^0.1.1:
   version "0.1.1"
   resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
@@ -5807,9 +5803,9 @@ run-async@^2.2.0:
   integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
 
 run-parallel@^1.1.9:
-  version "1.1.9"
-  resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679"
-  integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==
+  version "1.1.10"
+  resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef"
+  integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==
 
 rxjs@^6.4.0, rxjs@^6.6.2:
   version "6.6.3"
@@ -6025,7 +6021,7 @@ source-map-resolve@^0.5.0:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.5.17, source-map-support@^0.5.19, source-map-support@~0.5.19:
+source-map-support@^0.5.17, source-map-support@^0.5.19, source-map-support@~0.5.12, source-map-support@~0.5.19:
   version "0.5.19"
   resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
   integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
@@ -6043,7 +6039,7 @@ source-map@^0.5.0, source-map@^0.5.6:
   resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
 
-source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0:
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
   version "0.6.1"
   resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -6507,6 +6503,15 @@ tempfile@^3.0.0:
     temp-dir "^2.0.0"
     uuid "^3.3.2"
 
+terser@^4.6.3:
+  version "4.8.0"
+  resolved "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17"
+  integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==
+  dependencies:
+    commander "^2.20.0"
+    source-map "~0.6.1"
+    source-map-support "~0.5.12"
+
 terser@^5.0.0:
   version "5.3.8"
   resolved "https://registry.npmjs.org/terser/-/terser-5.3.8.tgz#991ae8ba21a3d990579b54aa9af11586197a75dd"
@@ -6711,7 +6716,7 @@ typescript@^4.0.5:
   resolved "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
   integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
 
-uglify-js@^3.1.4, uglify-js@^3.5.1:
+uglify-js@^3.1.4:
   version "3.11.4"
   resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.4.tgz#b47b7ae99d4bd1dca65b53aaa69caa0909e6fadf"
   integrity sha512-FyYnoxVL1D6+jDGQpbK5jW6y/2JlVfRfEeQ67BPCUg5wfCjaKOpr2XeceE4QL+MkhxliLtf5EbrMDZgzpt2CNw==
@@ -6817,11 +6822,6 @@ unset-value@^1.0.0:
     has-value "^0.3.1"
     isobject "^3.0.0"
 
-upper-case@^1.1.1:
-  version "1.1.3"
-  resolved "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
-  integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
-
 uri-js@^4.2.2:
   version "4.4.0"
   resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602"
@@ -6898,6 +6898,14 @@ vfile@^4.0.0:
     unist-util-stringify-position "^2.0.0"
     vfile-message "^2.0.0"
 
+vite-plugin-html@^1.0.0-beta.2:
+  version "1.0.0-beta.2"
+  resolved "https://registry.npmjs.org/vite-plugin-html/-/vite-plugin-html-1.0.0-beta.2.tgz#f30cdba4ca70469e62b770e32c407ce5d7f9b544"
+  integrity sha512-8d/jMcs4tI4Oyf7mG8VAArT9afJhbRbw/jljRutHBluUWgr4rzZsVpEsQIqnqbuElU5AECdovlLI52D50pE/OQ==
+  dependencies:
+    html-minifier-terser "^5.1.1"
+    lodash "^4.17.20"
+
 vite-plugin-mock@^1.0.4:
   version "1.0.4"
   resolved "https://registry.npmjs.org/vite-plugin-mock/-/vite-plugin-mock-1.0.4.tgz#56631559afcd77046b058f162b2b5e8f5aaa7b17"