Commit 5e99463cd0d6f7a642a8e06624a7de7ad4b79fac

Authored by vben
1 parent 5e4be0ad

perf: Refactor vite configuration

Showing 56 changed files with 645 additions and 456 deletions

Too many changes to show.

To preserve performance only 56 of 65 files are displayed.

.env.analyze 0 → 100644
  1 +# Whether to open mock
  2 +VITE_USE_MOCK = true
  3 +
  4 +# public path
  5 +VITE_PUBLIC_PATH = /
  6 +
  7 +# Whether to enable gzip or brotli compression
  8 +# Optional: gzip | brotli | none
  9 +# If you need multiple forms, you can use `,` to separate
  10 +VITE_BUILD_COMPRESS = 'none'
  11 +
  12 +
  13 +# Basic interface address SPA
  14 +VITE_GLOB_API_URL=/basic-api
  15 +
  16 +# File upload address, optional
  17 +# It can be forwarded by nginx or write the actual address directly
  18 +VITE_GLOB_UPLOAD_URL=/upload
  19 +
  20 +# Interface prefix
  21 +VITE_GLOB_API_URL_PREFIX=
  22 +
  23 +VITE_ENABLE_ANALYZE = true
.env.development
@@ -7,7 +7,6 @@ VITE_PUBLIC_PATH = / @@ -7,7 +7,6 @@ VITE_PUBLIC_PATH = /
7 # Cross-domain proxy, you can configure multiple 7 # Cross-domain proxy, you can configure multiple
8 # Please note that no line breaks 8 # Please note that no line breaks
9 VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]] 9 VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]]
10 -# VITE_PROXY=[["/api","https://vvbin.cn/test"]]  
11 10
12 # Basic interface address SPA 11 # Basic interface address SPA
13 VITE_GLOB_API_URL=/basic-api 12 VITE_GLOB_API_URL=/basic-api
.env.production
@@ -9,8 +9,6 @@ VITE_PUBLIC_PATH = / @@ -9,8 +9,6 @@ VITE_PUBLIC_PATH = /
9 # If you need multiple forms, you can use `,` to separate 9 # If you need multiple forms, you can use `,` to separate
10 VITE_BUILD_COMPRESS = 'none' 10 VITE_BUILD_COMPRESS = 'none'
11 11
12 -# Whether to delete origin files when using compress, default false  
13 -VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false  
14 12
15 # Basic interface address SPA 13 # Basic interface address SPA
16 VITE_GLOB_API_URL=/basic-api 14 VITE_GLOB_API_URL=/basic-api
.env.test
@@ -10,9 +10,6 @@ VITE_PUBLIC_PATH = / @@ -10,9 +10,6 @@ VITE_PUBLIC_PATH = /
10 # If you need multiple forms, you can use `,` to separate 10 # If you need multiple forms, you can use `,` to separate
11 VITE_BUILD_COMPRESS = 'none' 11 VITE_BUILD_COMPRESS = 'none'
12 12
13 -# Whether to delete origin files when using compress, default false  
14 -VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false  
15 -  
16 # Basic interface address SPA 13 # Basic interface address SPA
17 VITE_GLOB_API_URL=/basic-api 14 VITE_GLOB_API_URL=/basic-api
18 15
apps/portal-view/.gitkeep 0 → 100644
tests/server/README.md renamed to apps/test-server/README.md
tests/server/controller/FileController.ts renamed to apps/test-server/controller/FileController.ts
tests/server/controller/UserController.ts renamed to apps/test-server/controller/UserController.ts
tests/server/ecosystem.config.js renamed to apps/test-server/ecosystem.config.js
tests/server/index.ts renamed to apps/test-server/index.ts
tests/server/nodemon.json renamed to apps/test-server/nodemon.json
tests/server/package.json renamed to apps/test-server/package.json
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "license": "MIT", 4 "license": "MIT",
5 "scripts": { 5 "scripts": {
6 - "build": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ", 6 + "compile": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ",
7 "prod": "npx pm2 start ecosystem.config.js --env production", 7 "prod": "npx pm2 start ecosystem.config.js --env production",
8 "restart": "pm2 restart ecosystem.config.js --env production", 8 "restart": "pm2 restart ecosystem.config.js --env production",
9 "start": "nodemon", 9 "start": "nodemon",
tests/server/routes.ts renamed to apps/test-server/routes.ts
tests/server/service/FileService.ts renamed to apps/test-server/service/FileService.ts
tests/server/service/UserService.ts renamed to apps/test-server/service/UserService.ts
apps/test-server/tsconfig.json 0 → 100644
  1 +{
  2 + "$schema": "https://json.schemastore.org/tsconfig",
  3 + "extends": "@vben/ts-config/node-server.json",
  4 + "compilerOptions": {
  5 + "noImplicitAny": false
  6 + }
  7 +}
tests/server/utils.ts renamed to apps/test-server/utils.ts
build/config/themeConfig.ts deleted 100644 → 0
1 -import { generate } from '@ant-design/colors';  
2 -  
3 -export const primaryColor = '#0960bd';  
4 -  
5 -export const darkMode = 'light';  
6 -  
7 -type Fn = (...arg: any) => any;  
8 -  
9 -type GenerateTheme = 'default' | 'dark';  
10 -  
11 -export interface GenerateColorsParams {  
12 - mixLighten: Fn;  
13 - mixDarken: Fn;  
14 - tinycolor: any;  
15 - color?: string;  
16 -}  
17 -  
18 -export function generateAntColors(color: string, theme: GenerateTheme = 'default') {  
19 - return generate(color, {  
20 - theme,  
21 - });  
22 -}  
23 -  
24 -export function getThemeColors(color?: string) {  
25 - const tc = color || primaryColor;  
26 - const lightColors = generateAntColors(tc);  
27 - const primary = lightColors[5];  
28 - const modeColors = generateAntColors(primary, 'dark');  
29 -  
30 - return [...lightColors, ...modeColors];  
31 -}  
32 -  
33 -export function generateColors({  
34 - color = primaryColor,  
35 - mixLighten,  
36 - mixDarken,  
37 - tinycolor,  
38 -}: GenerateColorsParams) {  
39 - const arr = new Array(19).fill(0);  
40 - const lightens = arr.map((_t, i) => {  
41 - return mixLighten(color, i / 5);  
42 - });  
43 -  
44 - const darkens = arr.map((_t, i) => {  
45 - return mixDarken(color, i / 5);  
46 - });  
47 -  
48 - const alphaColors = arr.map((_t, i) => {  
49 - return tinycolor(color)  
50 - .setAlpha(i / 20)  
51 - .toRgbString();  
52 - });  
53 -  
54 - const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.'));  
55 -  
56 - const tinycolorLightens = arr  
57 - .map((_t, i) => {  
58 - return tinycolor(color)  
59 - .lighten(i * 5)  
60 - .toHexString();  
61 - })  
62 - .filter((item) => item !== '#ffffff');  
63 -  
64 - const tinycolorDarkens = arr  
65 - .map((_t, i) => {  
66 - return tinycolor(color)  
67 - .darken(i * 5)  
68 - .toHexString();  
69 - })  
70 - .filter((item) => item !== '#000000');  
71 - return [  
72 - ...lightens,  
73 - ...darkens,  
74 - ...alphaColors,  
75 - ...shortAlphaColors,  
76 - ...tinycolorDarkens,  
77 - ...tinycolorLightens,  
78 - ].filter((item) => !item.includes('-'));  
79 -}  
build/constant.ts deleted 100644 → 0
1 -/**  
2 - * The name of the configuration file entered in the production environment  
3 - */  
4 -export const GLOB_CONFIG_FILE_NAME = '_app.config.js';  
5 -  
6 -export const OUTPUT_DIR = 'dist';  
build/generate/icon/index.ts deleted 100644 → 0
1 -import path from 'path';  
2 -import fs from 'fs-extra';  
3 -import inquirer from 'inquirer';  
4 -import colors from 'picocolors';  
5 -import pkg from '../../../package.json';  
6 -  
7 -async function generateIcon() {  
8 - const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json');  
9 -  
10 - const raw = await fs.readJSON(path.join(dir, 'collections.json'));  
11 -  
12 - const collections = Object.entries(raw).map(([id, v]) => ({  
13 - ...(v as any),  
14 - id,  
15 - }));  
16 -  
17 - const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name }));  
18 -  
19 - inquirer  
20 - .prompt([  
21 - {  
22 - type: 'list',  
23 - name: 'useType',  
24 - choices: [  
25 - { key: 'local', value: 'local', name: 'Local' },  
26 - { key: 'onLine', value: 'onLine', name: 'OnLine' },  
27 - ],  
28 - message: 'How to use icons?',  
29 - },  
30 - {  
31 - type: 'list',  
32 - name: 'iconSet',  
33 - choices: choices,  
34 - message: 'Select the icon set that needs to be generated?',  
35 - },  
36 - {  
37 - type: 'input',  
38 - name: 'output',  
39 - message: 'Select the icon set that needs to be generated?',  
40 - default: 'src/components/Icon/data',  
41 - },  
42 - ])  
43 - .then(async (answers) => {  
44 - const { iconSet, output, useType } = answers;  
45 - const outputDir = path.resolve(process.cwd(), output);  
46 - fs.ensureDir(outputDir);  
47 - const genCollections = collections.filter((item) => [iconSet].includes(item.id));  
48 - const prefixSet: string[] = [];  
49 - for (const info of genCollections) {  
50 - const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`));  
51 - if (data) {  
52 - const { prefix } = data;  
53 - const isLocal = useType === 'local';  
54 - const icons = Object.keys(data.icons).map(  
55 - (item) => `${isLocal ? prefix + ':' : ''}${item}`,  
56 - );  
57 -  
58 - await fs.writeFileSync(  
59 - path.join(output, `icons.data.ts`),  
60 - `export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,  
61 - );  
62 - prefixSet.push(prefix);  
63 - }  
64 - }  
65 - fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));  
66 - console.log(  
67 - `✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,  
68 - );  
69 - });  
70 -}  
71 -  
72 -generateIcon();  
build/getConfigFileName.ts deleted 100644 → 0
1 -/**  
2 - * Get the configuration file variable name  
3 - * @param env  
4 - */  
5 -export const getConfigFileName = (env: Record<string, any>) => {  
6 - return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`  
7 - .toUpperCase()  
8 - .replace(/\s/g, '');  
9 -};  
build/script/buildConf.ts deleted 100644 → 0
1 -/**  
2 - * Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging  
3 - */  
4 -import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';  
5 -import fs, { writeFileSync } from 'fs-extra';  
6 -import colors from 'picocolors';  
7 -  
8 -import { getEnvConfig, getRootPath } from '../utils';  
9 -import { getConfigFileName } from '../getConfigFileName';  
10 -  
11 -import pkg from '../../package.json';  
12 -  
13 -interface CreateConfigParams {  
14 - configName: string;  
15 - config: any;  
16 - configFileName?: string;  
17 -}  
18 -  
19 -function createConfig(params: CreateConfigParams) {  
20 - const { configName, config, configFileName } = params;  
21 - try {  
22 - const windowConf = `window.${configName}`;  
23 - // Ensure that the variable will not be modified  
24 - let configStr = `${windowConf}=${JSON.stringify(config)};`;  
25 - configStr += `  
26 - Object.freeze(${windowConf});  
27 - Object.defineProperty(window, "${configName}", {  
28 - configurable: false,  
29 - writable: false,  
30 - });  
31 - `.replace(/\s/g, '');  
32 -  
33 - fs.mkdirp(getRootPath(OUTPUT_DIR));  
34 - writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);  
35 -  
36 - console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);  
37 - console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');  
38 - } catch (error) {  
39 - console.log(colors.red('configuration file configuration file failed to package:\n' + error));  
40 - }  
41 -}  
42 -  
43 -export function runBuildConfig() {  
44 - const config = getEnvConfig();  
45 - const configFileName = getConfigFileName(config);  
46 - createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME });  
47 -}  
build/script/postBuild.ts deleted 100644 → 0
1 -// #!/usr/bin/env node  
2 -  
3 -import { runBuildConfig } from './buildConf';  
4 -import colors from 'picocolors';  
5 -  
6 -import pkg from '../../package.json';  
7 -  
8 -export const runBuild = async () => {  
9 - try {  
10 - const argvList = process.argv.splice(2);  
11 -  
12 - // Generate configuration file  
13 - if (!argvList.includes('disabled-config')) {  
14 - runBuildConfig();  
15 - }  
16 -  
17 - console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');  
18 - } catch (error) {  
19 - console.log(colors.red('vite build error:\n' + error));  
20 - process.exit(1);  
21 - }  
22 -};  
23 -runBuild();  
build/vite/plugin/html.ts deleted 100644 → 0
1 -/**  
2 - * Plugin to minimize and use ejs template syntax in index.html.  
3 - * https://github.com/anncwb/vite-plugin-html  
4 - */  
5 -import type { PluginOption } from 'vite';  
6 -import { createHtmlPlugin } from 'vite-plugin-html';  
7 -import pkg from '../../../package.json';  
8 -import { GLOB_CONFIG_FILE_NAME } from '../../constant';  
9 -  
10 -export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {  
11 - const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;  
12 -  
13 - const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;  
14 -  
15 - const getAppConfigSrc = () => {  
16 - return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;  
17 - };  
18 -  
19 - const htmlPlugin: PluginOption[] = createHtmlPlugin({  
20 - minify: isBuild,  
21 - inject: {  
22 - // Inject data into ejs template  
23 - data: {  
24 - title: VITE_GLOB_APP_TITLE,  
25 - },  
26 - // Embed the generated app.config.js file  
27 - tags: isBuild  
28 - ? [  
29 - {  
30 - tag: 'script',  
31 - attrs: {  
32 - src: getAppConfigSrc(),  
33 - },  
34 - },  
35 - ]  
36 - : [],  
37 - },  
38 - });  
39 - return htmlPlugin;  
40 -}  
build/vite/proxy.ts deleted 100644 → 0
1 -/**  
2 - * Used to parse the .env.development proxy configuration  
3 - */  
4 -import type { ProxyOptions } from 'vite';  
5 -  
6 -type ProxyItem = [string, string];  
7 -  
8 -type ProxyList = ProxyItem[];  
9 -  
10 -type ProxyTargetList = Record<string, ProxyOptions>;  
11 -  
12 -const httpsRE = /^https:\/\//;  
13 -  
14 -/**  
15 - * Generate proxy  
16 - * @param list  
17 - */  
18 -export function createProxy(list: ProxyList = []) {  
19 - const ret: ProxyTargetList = {};  
20 - for (const [prefix, target] of list) {  
21 - const isHttps = httpsRE.test(target);  
22 -  
23 - // https://github.com/http-party/node-http-proxy#options  
24 - ret[prefix] = {  
25 - target: target,  
26 - changeOrigin: true,  
27 - ws: true,  
28 - rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),  
29 - // https is require secure=false  
30 - ...(isHttps ? { secure: false } : {}),  
31 - };  
32 - }  
33 - return ret;  
34 -}  
index.html
@@ -8,20 +8,10 @@ @@ -8,20 +8,10 @@
8 name="viewport" 8 name="viewport"
9 content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" 9 content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
10 /> 10 />
11 - <title><%= title %></title> 11 + <title><%= VITE_GLOB_APP_TITLE %></title>
12 <link rel="icon" href="/favicon.ico" /> 12 <link rel="icon" href="/favicon.ico" />
13 </head> 13 </head>
14 <body> 14 <body>
15 - <script>  
16 - (() => {  
17 - var htmlRoot = document.getElementById('htmlRoot');  
18 - var theme = window.localStorage.getItem('__APP__DARK__MODE__');  
19 - if (htmlRoot && theme) {  
20 - htmlRoot.setAttribute('data-theme', theme);  
21 - theme = htmlRoot = null;  
22 - }  
23 - })();  
24 - </script>  
25 <div id="app"> 15 <div id="app">
26 <style> 16 <style>
27 html[data-theme='dark'] .app-loading { 17 html[data-theme='dark'] .app-loading {
@@ -150,11 +140,11 @@ @@ -150,11 +140,11 @@
150 </style> 140 </style>
151 <div class="app-loading"> 141 <div class="app-loading">
152 <div class="app-loading-wrap"> 142 <div class="app-loading-wrap">
153 - <img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" /> 143 + <img src="/logo.png" class="app-loading-logo" alt="Logo" />
154 <div class="app-loading-dots"> 144 <div class="app-loading-dots">
155 <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span> 145 <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
156 </div> 146 </div>
157 - <div class="app-loading-title"><%= title %></div> 147 + <div class="app-loading-title"><%= VITE_GLOB_APP_TITLE %></div>
158 </div> 148 </div>
159 </div> 149 </div>
160 </div> 150 </div>
internal/eslint-config/package.json
@@ -2,6 +2,15 @@ @@ -2,6 +2,15 @@
2 "name": "@vben/eslint-config", 2 "name": "@vben/eslint-config",
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "private": true, 4 "private": true,
  5 + "homepage": "https://github.com/vbenjs/vue-vben-admin",
  6 + "bugs": {
  7 + "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  8 + },
  9 + "repository": {
  10 + "type": "git",
  11 + "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
  12 + "directory": "internal/eslint-config"
  13 + },
5 "license": "MIT", 14 "license": "MIT",
6 "exports": { 15 "exports": {
7 ".": { 16 ".": {
internal/stylelint-config/package.json
@@ -2,6 +2,15 @@ @@ -2,6 +2,15 @@
2 "name": "@vben/stylelint-config", 2 "name": "@vben/stylelint-config",
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "private": true, 4 "private": true,
  5 + "homepage": "https://github.com/vbenjs/vue-vben-admin",
  6 + "bugs": {
  7 + "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  8 + },
  9 + "repository": {
  10 + "type": "git",
  11 + "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
  12 + "directory": "internal/stylelint-config"
  13 + },
5 "license": "MIT", 14 "license": "MIT",
6 "exports": { 15 "exports": {
7 ".": { 16 ".": {
tests/server/tsconfig.json renamed to internal/ts-config/node-server.json
1 { 1 {
  2 + "$schema": "https://json.schemastore.org/tsconfig",
  3 + "display": "Node Server Config",
  4 + "extends": "./base.json",
2 "compilerOptions": { 5 "compilerOptions": {
3 "module": "commonjs", 6 "module": "commonjs",
4 "declaration": false, 7 "declaration": false,
internal/ts-config/node.json
@@ -4,9 +4,9 @@ @@ -4,9 +4,9 @@
4 "extends": "./base.json", 4 "extends": "./base.json",
5 "compilerOptions": { 5 "compilerOptions": {
6 "lib": ["ESNext"], 6 "lib": ["ESNext"],
7 - "types": ["vite/client"],  
8 "noImplicitAny": true, 7 "noImplicitAny": true,
9 "sourceMap": true, 8 "sourceMap": true,
10 - "noEmit": true 9 + "noEmit": true,
  10 + "baseUrl": "./"
11 } 11 }
12 } 12 }
internal/ts-config/package.json
@@ -2,11 +2,23 @@ @@ -2,11 +2,23 @@
2 "name": "@vben/ts-config", 2 "name": "@vben/ts-config",
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "private": true, 4 "private": true,
  5 + "homepage": "https://github.com/vbenjs/vue-vben-admin",
  6 + "bugs": {
  7 + "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  8 + },
  9 + "repository": {
  10 + "type": "git",
  11 + "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
  12 + "directory": "internal/ts-config"
  13 + },
5 "license": "MIT", 14 "license": "MIT",
6 "files": [ 15 "files": [
7 "base.json", 16 "base.json",
8 "node.json", 17 "node.json",
9 - "vue.json" 18 + "vue.json",
  19 + "node-server.json"
10 ], 20 ],
11 - "devDependencies": {} 21 + "dependencies": {
  22 + "@types/node": "^18.15.11"
  23 + }
12 } 24 }
internal/vite-config/.commitlintrc.js 0 → 100644
  1 +const fs = require('fs');
  2 +const path = require('path');
  3 +const { execSync } = require('child_process');
  4 +
  5 +const scopes = fs
  6 + .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
  7 + .filter((dirent) => dirent.isDirectory())
  8 + .map((dirent) => dirent.name.replace(/s$/, ''));
  9 +
  10 +// precomputed scope
  11 +const scopeComplete = execSync('git status --porcelain || true')
  12 + .toString()
  13 + .trim()
  14 + .split('\n')
  15 + .find((r) => ~r.indexOf('M src'))
  16 + ?.replace(/(\/)/g, '%%')
  17 + ?.match(/src%%((\w|-)*)/)?.[1]
  18 + ?.replace(/s$/, '');
  19 +
  20 +/** @type {import('cz-git').UserConfig} */
  21 +module.exports = {
  22 + ignores: [(commit) => commit.includes('init')],
  23 + extends: ['@commitlint/config-conventional'],
  24 + rules: {
  25 + 'body-leading-blank': [2, 'always'],
  26 + 'footer-leading-blank': [1, 'always'],
  27 + 'header-max-length': [2, 'always', 108],
  28 + 'subject-empty': [2, 'never'],
  29 + 'type-empty': [2, 'never'],
  30 + 'subject-case': [0],
  31 + 'type-enum': [
  32 + 2,
  33 + 'always',
  34 + [
  35 + 'feat',
  36 + 'fix',
  37 + 'perf',
  38 + 'style',
  39 + 'docs',
  40 + 'test',
  41 + 'refactor',
  42 + 'build',
  43 + 'ci',
  44 + 'chore',
  45 + 'revert',
  46 + 'wip',
  47 + 'workflow',
  48 + 'types',
  49 + 'release',
  50 + ],
  51 + ],
  52 + },
  53 + prompt: {
  54 + /** @use `yarn commit :f` */
  55 + alias: {
  56 + f: 'docs: fix typos',
  57 + r: 'docs: update README',
  58 + s: 'style: update code format',
  59 + b: 'build: bump dependencies',
  60 + c: 'chore: update config',
  61 + },
  62 + customScopesAlign: !scopeComplete ? 'top' : 'bottom',
  63 + defaultScope: scopeComplete,
  64 + scopes: [...scopes, 'mock'],
  65 + allowEmptyIssuePrefixs: false,
  66 + allowCustomIssuePrefixs: false,
  67 +
  68 + // English
  69 + typesAppend: [
  70 + { value: 'wip', name: 'wip: work in process' },
  71 + { value: 'workflow', name: 'workflow: workflow improvements' },
  72 + { value: 'types', name: 'types: type definition file changes' },
  73 + ],
  74 +
  75 + // 中英文对照版
  76 + // messages: {
  77 + // type: '选择你要提交的类型 :',
  78 + // scope: '选择一个提交范围 (可选):',
  79 + // customScope: '请输入自定义的提交范围 :',
  80 + // subject: '填写简短精炼的变更描述 :\n',
  81 + // body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
  82 + // breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
  83 + // footerPrefixsSelect: '选择关联issue前缀 (可选):',
  84 + // customFooterPrefixs: '输入自定义issue前缀 :',
  85 + // footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
  86 + // confirmCommit: '是否提交或修改commit ?',
  87 + // },
  88 + // types: [
  89 + // { value: 'feat', name: 'feat: 新增功能' },
  90 + // { value: 'fix', name: 'fix: 修复缺陷' },
  91 + // { value: 'docs', name: 'docs: 文档变更' },
  92 + // { value: 'style', name: 'style: 代码格式' },
  93 + // { value: 'refactor', name: 'refactor: 代码重构' },
  94 + // { value: 'perf', name: 'perf: 性能优化' },
  95 + // { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
  96 + // { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
  97 + // { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
  98 + // { value: 'revert', name: 'revert: 回滚 commit' },
  99 + // { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
  100 + // { value: 'wip', name: 'wip: 正在开发中' },
  101 + // { value: 'workflow', name: 'workflow: 工作流程改进' },
  102 + // { value: 'types', name: 'types: 类型定义文件修改' },
  103 + // ],
  104 + // emptyScopesAlias: 'empty: 不填写',
  105 + // customScopesAlias: 'custom: 自定义',
  106 + },
  107 +};
internal/vite-config/.eslintignore 0 → 100644
  1 +
  2 +*.sh
  3 +node_modules
  4 +*.md
  5 +*.woff
  6 +*.ttf
  7 +.vscode
  8 +.idea
  9 +dist
  10 +/public
  11 +/docs
  12 +.husky
  13 +.local
  14 +/bin
  15 +Dockerfile
internal/vite-config/.eslintrc.js 0 → 100644
  1 +module.exports = {
  2 + root: true,
  3 + extends: ['@vben'],
  4 +};
internal/vite-config/.prettierignore 0 → 100644
  1 +dist
  2 +.local
  3 +.output.js
  4 +node_modules
  5 +
  6 +**/*.svg
  7 +**/*.sh
  8 +
  9 +public
  10 +.npmrc
internal/vite-config/.prettierrc.js 0 → 100644
  1 +module.exports = {
  2 + printWidth: 100,
  3 + semi: true,
  4 + vueIndentScriptAndStyle: true,
  5 + singleQuote: true,
  6 + trailingComma: 'all',
  7 + proseWrap: 'never',
  8 + htmlWhitespaceSensitivity: 'strict',
  9 + endOfLine: 'auto',
  10 + plugins: ['prettier-plugin-packagejson'],
  11 + overrides: [
  12 + {
  13 + files: '.*rc',
  14 + options: {
  15 + parser: 'json',
  16 + },
  17 + },
  18 + ],
  19 +};
internal/vite-config/.stylelintignore 0 → 100644
  1 +dist
  2 +public
internal/vite-config/.stylelintrc.js 0 → 100644
  1 +module.exports = {
  2 + root: true,
  3 + extends: ['@vben/stylelint-config'],
  4 +};
internal/vite-config/build.config.ts 0 → 100644
  1 +import { defineBuildConfig } from 'unbuild';
  2 +
  3 +export default defineBuildConfig({
  4 + clean: true,
  5 + entries: ['src/index'],
  6 + declaration: true,
  7 + rollup: {
  8 + emitCJS: true,
  9 + },
  10 +});
internal/vite-config/package.json 0 → 100644
  1 +{
  2 + "name": "@vben/vite-config",
  3 + "version": "1.0.0",
  4 + "private": true,
  5 + "homepage": "https://github.com/vbenjs/vue-vben-admin",
  6 + "bugs": {
  7 + "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  8 + },
  9 + "repository": {
  10 + "type": "git",
  11 + "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
  12 + "directory": "internal/vite-config"
  13 + },
  14 + "license": "MIT",
  15 + "exports": {
  16 + ".": {
  17 + "types": "./dist/index.d.ts",
  18 + "import": "./dist/index.mjs",
  19 + "require": "./dist/index.cjs"
  20 + }
  21 + },
  22 + "main": "./dist/index.cjs",
  23 + "module": "./dist/index.mjs",
  24 + "types": "./dist/index.d.ts",
  25 + "files": [
  26 + "dist"
  27 + ],
  28 + "scripts": {
  29 + "clean": "pnpm rimraf .turbo node_modules dist",
  30 + "lint": "pnpm eslint .",
  31 + "stub": "pnpm unbuild --stub"
  32 + },
  33 + "dependencies": {
  34 + "vite": "^4.3.0-beta.1"
  35 + },
  36 + "devDependencies": {
  37 + "@types/fs-extra": "^11.0.1",
  38 + "ant-design-vue": "^3.2.16",
  39 + "dayjs": "^1.11.7",
  40 + "dotenv": "^16.0.3",
  41 + "fs-extra": "^11.1.1",
  42 + "less": "^4.1.3",
  43 + "picocolors": "^1.0.0",
  44 + "pkg-types": "^1.0.2",
  45 + "rollup-plugin-visualizer": "^5.9.0",
  46 + "sass": "^1.60.0",
  47 + "vite-plugin-compression": "^0.5.1",
  48 + "vite-plugin-html": "^3.2.0",
  49 + "vite-plugin-mock": "^2.9.6",
  50 + "vite-plugin-purge-icons": "^0.9.2",
  51 + "vite-plugin-svg-icons": "^2.0.1",
  52 + "vite-plugin-windicss": "^1.8.10"
  53 + }
  54 +}
internal/vite-config/src/config/application.ts 0 → 100644
  1 +import { type UserConfig, defineConfig, mergeConfig, loadEnv } from 'vite';
  2 +import { resolve } from 'node:path';
  3 +import { readPackageJSON } from 'pkg-types';
  4 +import { generateModifyVars } from '../utils/modifyVars';
  5 +import { commonConfig } from './common';
  6 +import { createPlugins } from '../plugins';
  7 +import dayjs from 'dayjs';
  8 +
  9 +interface DefineOptions {
  10 + overrides?: UserConfig;
  11 + options?: {};
  12 +}
  13 +
  14 +function defineApplicationConfig(defineOptions: DefineOptions = {}) {
  15 + const { overrides = {} } = defineOptions;
  16 +
  17 + return defineConfig(async ({ command, mode }) => {
  18 + const root = process.cwd();
  19 + const isBuild = command === 'build';
  20 + const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv(mode, root);
  21 +
  22 + const defineData = await createDefineData(root);
  23 + const plugins = await createPlugins({
  24 + isBuild,
  25 + root,
  26 + enableAnalyze: VITE_ENABLE_ANALYZE === 'true',
  27 + enableMock: VITE_USE_MOCK === 'true',
  28 + compress: VITE_BUILD_COMPRESS,
  29 + });
  30 +
  31 + const pathResolve = (pathname: string) => resolve(root, '.', pathname);
  32 +
  33 + const applicationConfig: UserConfig = {
  34 + optimizeDeps: {
  35 + include: [
  36 + '@iconify/iconify',
  37 + 'ant-design-vue/es/locale/zh_CN',
  38 + 'ant-design-vue/es/locale/en_US',
  39 + ],
  40 + },
  41 + resolve: {
  42 + alias: [
  43 + {
  44 + find: 'vue-i18n',
  45 + replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
  46 + },
  47 + // /@/xxxx => src/xxxx
  48 + {
  49 + find: /\/@\//,
  50 + replacement: pathResolve('src') + '/',
  51 + },
  52 + // /#/xxxx => types/xxxx
  53 + {
  54 + find: /\/#\//,
  55 + replacement: pathResolve('types') + '/',
  56 + },
  57 + // @/xxxx => src/xxxx
  58 + {
  59 + find: /@\//,
  60 + replacement: pathResolve('src') + '/',
  61 + },
  62 + // #/xxxx => types/xxxx
  63 + {
  64 + find: /#\//,
  65 + replacement: pathResolve('types') + '/',
  66 + },
  67 + ],
  68 + },
  69 + define: defineData,
  70 + build: {
  71 + target: 'es2015',
  72 + cssTarget: 'chrome80',
  73 + rollupOptions: {
  74 + output: {
  75 + manualChunks: {
  76 + vue: ['vue', 'pinia', 'vue-router'],
  77 + antdv: ['ant-design-vue', '@ant-design/icons-vue'],
  78 + },
  79 + },
  80 + },
  81 + },
  82 + css: {
  83 + preprocessorOptions: {
  84 + less: {
  85 + modifyVars: generateModifyVars(),
  86 + javascriptEnabled: true,
  87 + },
  88 + },
  89 + },
  90 + plugins,
  91 + };
  92 +
  93 + const mergedConfig = mergeConfig(commonConfig, applicationConfig);
  94 +
  95 + return mergeConfig(mergedConfig, overrides);
  96 + });
  97 +}
  98 +
  99 +async function createDefineData(root: string) {
  100 + try {
  101 + const pkgJson = await readPackageJSON(root);
  102 + const { dependencies, devDependencies, name, version } = pkgJson;
  103 +
  104 + const __APP_INFO__ = {
  105 + pkg: { dependencies, devDependencies, name, version },
  106 + lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
  107 + };
  108 + return {
  109 + __APP_INFO__: JSON.stringify(__APP_INFO__),
  110 + };
  111 + } catch (error) {
  112 + return {};
  113 + }
  114 +}
  115 +
  116 +export { defineApplicationConfig };
internal/vite-config/src/config/common.ts 0 → 100644
  1 +import { type UserConfig } from 'vite';
  2 +
  3 +const commonConfig: UserConfig = {
  4 + server: {
  5 + host: true,
  6 + },
  7 + esbuild: {
  8 + drop: ['console', 'debugger'],
  9 + },
  10 + build: {
  11 + reportCompressedSize: false,
  12 + chunkSizeWarningLimit: 1500,
  13 + rollupOptions: {
  14 + // TODO: Prevent memory overflow
  15 + maxParallelFileOps: 3,
  16 + },
  17 + },
  18 +};
  19 +
  20 +export { commonConfig };
internal/vite-config/src/config/package.ts 0 → 100644
  1 +function definePackageConfig() {
  2 + // TODO:
  3 +}
  4 +
  5 +export { definePackageConfig };
internal/vite-config/src/index.ts 0 → 100644
  1 +export * from './config/application';
internal/vite-config/src/plugins/appConfig.ts 0 → 100644
  1 +import { type PluginOption } from 'vite';
  2 +import { getEnvConfig } from '../utils/env';
  3 +import { createContentHash } from '../utils/hash';
  4 +import { readPackageJSON } from 'pkg-types';
  5 +import colors from 'picocolors';
  6 +
  7 +const GLOBAL_CONFIG_FILE_NAME = '_app.config.js';
  8 +const PLUGIN_NAME = 'app-config';
  9 +
  10 +async function createAppConfigPlugin({
  11 + root,
  12 + isBuild,
  13 +}: {
  14 + root: string;
  15 + isBuild: boolean;
  16 +}): Promise<PluginOption> {
  17 + let publicPath: string;
  18 + let source: string;
  19 + if (!isBuild) {
  20 + return {
  21 + name: PLUGIN_NAME,
  22 + };
  23 + }
  24 + const { version = '' } = await readPackageJSON(root);
  25 +
  26 + return {
  27 + name: PLUGIN_NAME,
  28 + async configResolved(_config) {
  29 + const appTitle = _config?.env?.VITE_GLOB_APP_SHORT_NAME ?? '';
  30 + publicPath = _config.base;
  31 + source = await getConfigSource(appTitle);
  32 + },
  33 + async transformIndexHtml(html) {
  34 + publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
  35 +
  36 + const appConfigSrc = `${
  37 + publicPath || '/'
  38 + }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}}`;
  39 +
  40 + return {
  41 + html,
  42 + tags: [
  43 + {
  44 + tag: 'script',
  45 + attrs: {
  46 + src: appConfigSrc,
  47 + },
  48 + },
  49 + ],
  50 + };
  51 + },
  52 + async generateBundle() {
  53 + try {
  54 + this.emitFile({
  55 + type: 'asset',
  56 + fileName: GLOBAL_CONFIG_FILE_NAME,
  57 + source,
  58 + });
  59 +
  60 + console.log(colors.cyan(`✨configuration file is build successfully!`));
  61 + } catch (error) {
  62 + console.log(
  63 + colors.red('configuration file configuration file failed to package:\n' + error),
  64 + );
  65 + }
  66 + },
  67 + };
  68 +}
  69 +
  70 +/**
  71 + * Get the configuration file variable name
  72 + * @param env
  73 + */
  74 +const getVariableName = (title: string) => {
  75 + return `__PRODUCTION__${title || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
  76 +};
  77 +
  78 +async function getConfigSource(appTitle: string) {
  79 + const config = await getEnvConfig();
  80 + const variableName = getVariableName(appTitle);
  81 + const windowVariable = `window.${variableName}`;
  82 + // Ensure that the variable will not be modified
  83 + let source = `${windowVariable}=${JSON.stringify(config)};`;
  84 + source += `
  85 + Object.freeze(${windowVariable});
  86 + Object.defineProperty(window, "${variableName}", {
  87 + configurable: false,
  88 + writable: false,
  89 + });
  90 + `.replace(/\s/g, '');
  91 + return source;
  92 +}
  93 +
  94 +export { createAppConfigPlugin };
build/vite/plugin/compress.ts renamed to internal/vite-config/src/plugins/compress.ts
@@ -5,10 +5,13 @@ @@ -5,10 +5,13 @@
5 import type { PluginOption } from 'vite'; 5 import type { PluginOption } from 'vite';
6 import compressPlugin from 'vite-plugin-compression'; 6 import compressPlugin from 'vite-plugin-compression';
7 7
8 -export function configCompressPlugin(  
9 - compress: 'gzip' | 'brotli' | 'none', 8 +export function configCompressPlugin({
  9 + compress,
10 deleteOriginFile = false, 10 deleteOriginFile = false,
11 -): PluginOption | PluginOption[] { 11 +}: {
  12 + compress: string;
  13 + deleteOriginFile?: boolean;
  14 +}): PluginOption[] {
12 const compressList = compress.split(','); 15 const compressList = compress.split(',');
13 16
14 const plugins: PluginOption[] = []; 17 const plugins: PluginOption[] = [];
internal/vite-config/src/plugins/html.ts 0 → 100644
  1 +/**
  2 + * Plugin to minimize and use ejs template syntax in index.html.
  3 + * https://github.com/anncwb/vite-plugin-html
  4 + */
  5 +import type { PluginOption } from 'vite';
  6 +import { createHtmlPlugin } from 'vite-plugin-html';
  7 +
  8 +export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) {
  9 + const htmlPlugin: PluginOption[] = createHtmlPlugin({
  10 + minify: isBuild,
  11 + });
  12 + return htmlPlugin;
  13 +}
build/vite/plugin/index.ts renamed to internal/vite-config/src/plugins/index.ts
1 -import { PluginOption } from 'vite';  
2 -import vue from '@vitejs/plugin-vue';  
3 -import vueJsx from '@vitejs/plugin-vue-jsx';  
4 -import purgeIcons from 'vite-plugin-purge-icons';  
5 -import windiCSS from 'vite-plugin-windicss'; 1 +import { type PluginOption } from 'vite';
6 import { configHtmlPlugin } from './html'; 2 import { configHtmlPlugin } from './html';
7 import { configMockPlugin } from './mock'; 3 import { configMockPlugin } from './mock';
8 import { configCompressPlugin } from './compress'; 4 import { configCompressPlugin } from './compress';
9 import { configVisualizerConfig } from './visualizer'; 5 import { configVisualizerConfig } from './visualizer';
10 import { configSvgIconsPlugin } from './svgSprite'; 6 import { configSvgIconsPlugin } from './svgSprite';
  7 +import { createAppConfigPlugin } from './appConfig';
  8 +import vue from '@vitejs/plugin-vue';
  9 +import vueJsx from '@vitejs/plugin-vue-jsx';
  10 +import purgeIcons from 'vite-plugin-purge-icons';
  11 +import windiCSS from 'vite-plugin-windicss';
11 12
12 -export async function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {  
13 - const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv; 13 +interface Options {
  14 + isBuild: boolean;
  15 + root: string;
  16 + compress: string;
  17 + enableMock?: boolean;
  18 + enableAnalyze?: boolean;
  19 +}
14 20
15 - const vitePlugins: (PluginOption | PluginOption[])[] = [  
16 - // have to  
17 - vue(),  
18 - // have to  
19 - vueJsx(),  
20 - ]; 21 +async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) {
  22 + const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()];
  23 +
  24 + const appConfigPlugin = await createAppConfigPlugin({ root, isBuild });
  25 + vitePlugins.push(appConfigPlugin);
21 26
22 // vite-plugin-windicss 27 // vite-plugin-windicss
23 vitePlugins.push(windiCSS()); 28 vitePlugins.push(windiCSS());
24 29
25 // vite-plugin-html 30 // vite-plugin-html
26 - vitePlugins.push(configHtmlPlugin(viteEnv, isBuild)); 31 + vitePlugins.push(configHtmlPlugin({ isBuild }));
27 32
28 // vite-plugin-svg-icons 33 // vite-plugin-svg-icons
29 - vitePlugins.push(configSvgIconsPlugin(isBuild));  
30 -  
31 - // vite-plugin-mock  
32 - VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild)); 34 + vitePlugins.push(configSvgIconsPlugin({ isBuild }));
33 35
34 // vite-plugin-purge-icons 36 // vite-plugin-purge-icons
35 vitePlugins.push(purgeIcons()); 37 vitePlugins.push(purgeIcons());
36 38
37 - // rollup-plugin-visualizer  
38 - vitePlugins.push(configVisualizerConfig());  
39 -  
40 // The following plugins only work in the production environment 39 // The following plugins only work in the production environment
41 if (isBuild) { 40 if (isBuild) {
42 // rollup-plugin-gzip 41 // rollup-plugin-gzip
43 vitePlugins.push( 42 vitePlugins.push(
44 - configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE), 43 + configCompressPlugin({
  44 + compress,
  45 + }),
45 ); 46 );
46 } 47 }
47 48
  49 + // rollup-plugin-visualizer
  50 + if (enableAnalyze) {
  51 + vitePlugins.push(configVisualizerConfig());
  52 + }
  53 +
  54 + // vite-plugin-mock
  55 + if (enableMock) {
  56 + vitePlugins.push(configMockPlugin({ isBuild }));
  57 + }
  58 +
48 return vitePlugins; 59 return vitePlugins;
49 } 60 }
  61 +
  62 +export { createPlugins };
build/vite/plugin/mock.ts renamed to internal/vite-config/src/plugins/mock.ts
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 */ 4 */
5 import { viteMockServe } from 'vite-plugin-mock'; 5 import { viteMockServe } from 'vite-plugin-mock';
6 6
7 -export function configMockPlugin(isBuild: boolean) { 7 +export function configMockPlugin({ isBuild }: { isBuild: boolean }) {
8 return viteMockServe({ 8 return viteMockServe({
9 ignore: /^_/, 9 ignore: /^_/,
10 mockPath: 'mock', 10 mockPath: 'mock',
build/vite/plugin/svgSprite.ts renamed to internal/vite-config/src/plugins/svgSprite.ts
@@ -4,15 +4,13 @@ @@ -4,15 +4,13 @@
4 */ 4 */
5 5
6 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; 6 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
7 -import path from 'path'; 7 +import { resolve } from 'node:path';
8 import type { PluginOption } from 'vite'; 8 import type { PluginOption } from 'vite';
9 9
10 -export function configSvgIconsPlugin(isBuild: boolean) { 10 +export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) {
11 const svgIconsPlugin = createSvgIconsPlugin({ 11 const svgIconsPlugin = createSvgIconsPlugin({
12 - iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')], 12 + iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
13 svgoOptions: isBuild, 13 svgoOptions: isBuild,
14 - // default  
15 - symbolId: 'icon-[dir]-[name]',  
16 }); 14 });
17 return svgIconsPlugin as PluginOption; 15 return svgIconsPlugin as PluginOption;
18 } 16 }
build/vite/plugin/visualizer.ts renamed to internal/vite-config/src/plugins/visualizer.ts
1 /** 1 /**
2 * Package file volume analysis 2 * Package file volume analysis
3 */ 3 */
  4 +import { type PluginOption } from 'vite';
4 import visualizer from 'rollup-plugin-visualizer'; 5 import visualizer from 'rollup-plugin-visualizer';
5 6
6 export function configVisualizerConfig() { 7 export function configVisualizerConfig() {
7 - if (process.env.REPORT === 'true') {  
8 - return visualizer({  
9 - filename: './node_modules/.cache/visualizer/stats.html',  
10 - open: true,  
11 - gzipSize: true,  
12 - brotliSize: true,  
13 - }) as Plugin;  
14 - }  
15 - return []; 8 + return visualizer({
  9 + filename: './node_modules/.cache/visualizer/stats.html',
  10 + open: true,
  11 + gzipSize: true,
  12 + brotliSize: true,
  13 + }) as PluginOption;
16 } 14 }
build/utils.ts renamed to internal/vite-config/src/utils/env.ts
1 -import fs from 'fs';  
2 -import path from 'path';  
3 import dotenv from 'dotenv'; 1 import dotenv from 'dotenv';
4 -  
5 -// Read all environment variable configuration files to process.env  
6 -export function wrapperEnv(envConf: Recordable): ViteEnv {  
7 - const ret: any = {};  
8 -  
9 - for (const envName of Object.keys(envConf)) {  
10 - let realName = envConf[envName].replace(/\\n/g, '\n');  
11 - realName = realName === 'true' ? true : realName === 'false' ? false : realName;  
12 - if (envName === 'VITE_PROXY' && realName) {  
13 - try {  
14 - realName = JSON.parse(realName.replace(/'/g, '"'));  
15 - } catch (error) {  
16 - realName = '';  
17 - }  
18 - }  
19 - ret[envName] = realName;  
20 - // if (typeof realName === 'string') {  
21 - // process.env[envName] = realName;  
22 - // } else if (typeof realName === 'object') {  
23 - // process.env[envName] = JSON.stringify(realName);  
24 - // }  
25 - }  
26 - return ret;  
27 -} 2 +import { readFile } from 'fs-extra';
  3 +import { join } from 'node:path';
28 4
29 /** 5 /**
30 * 获取当前环境下生效的配置文件名 6 * 获取当前环境下生效的配置文件名
31 */ 7 */
32 function getConfFiles() { 8 function getConfFiles() {
33 - const script = process.env.npm_lifecycle_script; 9 + const script = process.env.npm_lifecycle_script as string;
34 const reg = new RegExp('--mode ([a-z_\\d]+)'); 10 const reg = new RegExp('--mode ([a-z_\\d]+)');
35 - const result = reg.exec(script as string) as any; 11 + const result = reg.exec(script);
36 if (result) { 12 if (result) {
37 - const mode = result[1] as string; 13 + const mode = result[1];
38 return ['.env', `.env.${mode}`]; 14 return ['.env', `.env.${mode}`];
39 } 15 }
40 return ['.env', '.env.production']; 16 return ['.env', '.env.production'];
@@ -45,16 +21,18 @@ function getConfFiles() { @@ -45,16 +21,18 @@ function getConfFiles() {
45 * @param match prefix 21 * @param match prefix
46 * @param confFiles ext 22 * @param confFiles ext
47 */ 23 */
48 -export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) { 24 +export async function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
49 let envConfig = {}; 25 let envConfig = {};
50 - confFiles.forEach((item) => { 26 +
  27 + for (const confFile of confFiles) {
51 try { 28 try {
52 - const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item))); 29 + const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' });
  30 + const env = dotenv.parse(envPath);
53 envConfig = { ...envConfig, ...env }; 31 envConfig = { ...envConfig, ...env };
54 } catch (e) { 32 } catch (e) {
55 - console.error(`Error in parsing ${item}`, e); 33 + console.error(`Error in parsing ${confFile}`, e);
56 } 34 }
57 - }); 35 + }
58 const reg = new RegExp(`^(${match})`); 36 const reg = new RegExp(`^(${match})`);
59 Object.keys(envConfig).forEach((key) => { 37 Object.keys(envConfig).forEach((key) => {
60 if (!reg.test(key)) { 38 if (!reg.test(key)) {
@@ -63,11 +41,3 @@ export function getEnvConfig(match = &#39;VITE_GLOB_&#39;, confFiles = getConfFiles()) { @@ -63,11 +41,3 @@ export function getEnvConfig(match = &#39;VITE_GLOB_&#39;, confFiles = getConfFiles()) {
63 }); 41 });
64 return envConfig; 42 return envConfig;
65 } 43 }
66 -  
67 -/**  
68 - * Get user root directory  
69 - * @param dir file path  
70 - */  
71 -export function getRootPath(...dir: string[]) {  
72 - return path.resolve(process.cwd(), ...dir);  
73 -}  
internal/vite-config/src/utils/hash.ts 0 → 100644
  1 +import { createHash } from 'node:crypto';
  2 +
  3 +function createContentHash(content: string, hashLSize = 12) {
  4 + const hash = createHash('sha256').update(content);
  5 + return hash.digest('hex').slice(0, hashLSize);
  6 +}
  7 +
  8 +export { createContentHash };
build/generate/generateModifyVars.ts renamed to internal/vite-config/src/utils/modifyVars.ts
1 -import { generateAntColors, primaryColor } from '../config/themeConfig'; 1 +import { generate } from '@ant-design/colors';
  2 +import { resolve } from 'node:path';
  3 +// @ts-ignore
2 import { getThemeVariables } from 'ant-design-vue/dist/theme'; 4 import { getThemeVariables } from 'ant-design-vue/dist/theme';
3 -import { resolve } from 'path'; 5 +
  6 +const primaryColor = '#0960bd';
  7 +
  8 +function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') {
  9 + return generate(color, {
  10 + theme,
  11 + });
  12 +}
4 13
5 /** 14 /**
6 * less global variable 15 * less global variable
7 */ 16 */
8 -export function generateModifyVars(dark = false) { 17 +export function generateModifyVars() {
9 const palettes = generateAntColors(primaryColor); 18 const palettes = generateAntColors(primaryColor);
10 const primary = palettes[5]; 19 const primary = palettes[5];
11 20
@@ -15,10 +24,9 @@ export function generateModifyVars(dark = false) { @@ -15,10 +24,9 @@ export function generateModifyVars(dark = false) {
15 primaryColorObj[`primary-${index + 1}`] = palettes[index]; 24 primaryColorObj[`primary-${index + 1}`] = palettes[index];
16 } 25 }
17 26
18 - const modifyVars = getThemeVariables({ dark }); 27 + const modifyVars = getThemeVariables();
19 return { 28 return {
20 ...modifyVars, 29 ...modifyVars,
21 - // Used for global import to avoid the need to import each style file separately  
22 // reference: Avoid repeated references 30 // reference: Avoid repeated references
23 hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`, 31 hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`,
24 'primary-color': primary, 32 'primary-color': primary,
@@ -28,7 +36,6 @@ export function generateModifyVars(dark = false) { @@ -28,7 +36,6 @@ export function generateModifyVars(dark = false) {
28 'success-color': '#55D187', // Success color 36 'success-color': '#55D187', // Success color
29 'error-color': '#ED6F6F', // False color 37 'error-color': '#ED6F6F', // False color
30 'warning-color': '#EFBD47', // Warning color 38 'warning-color': '#EFBD47', // Warning color
31 - //'border-color-base': '#EEEEEE',  
32 'font-size-base': '14px', // Main font size 39 'font-size-base': '14px', // Main font size
33 'border-radius-base': '2px', // Component/float fillet 40 'border-radius-base': '2px', // Component/float fillet
34 'link-color': primary, // Link color 41 'link-color': primary, // Link color
internal/vite-config/tsconfig.json 0 → 100644
  1 +{
  2 + "$schema": "https://json.schemastore.org/tsconfig",
  3 + "extends": "@vben/ts-config/node.json",
  4 + "include": ["src"]
  5 +}
package.json
1 { 1 {
2 "name": "vben-admin", 2 "name": "vben-admin",
3 "version": "2.9.0", 3 "version": "2.9.0",
4 - "homepage": "https://github.com/anncwb/vue-vben-admin", 4 + "homepage": "https://github.com/vbenjs/vue-vben-admin",
5 "bugs": { 5 "bugs": {
6 - "url": "https://github.com/anncwb/vue-vben-admin/issues" 6 + "url": "https://github.com/vbenjs/vue-vben-admin/issues"
7 }, 7 },
8 "repository": { 8 "repository": {
9 "type": "git", 9 "type": "git",
10 - "url": "git+https://github.com/anncwb/vue-vben-admin.git" 10 + "url": "git+https://github.com/vbenjs/vue-vben-admin.git"
11 }, 11 },
12 "license": "MIT", 12 "license": "MIT",
13 "author": { 13 "author": {
@@ -17,29 +17,23 @@ @@ -17,29 +17,23 @@
17 }, 17 },
18 "scripts": { 18 "scripts": {
19 "bootstrap": "pnpm install", 19 "bootstrap": "pnpm install",
20 - "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=production vite build && esno ./build/script/postBuild.ts", 20 + "build": "NODE_ENV=production pnpm vite build",
  21 + "build:analyze": "pnpm vite build --mode analyze",
21 "build:no-cache": "pnpm clean:cache && npm run build", 22 "build:no-cache": "pnpm clean:cache && npm run build",
22 - "build:test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build --mode test && esno ./build/script/postBuild.ts",  
23 - "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",  
24 - "clean:lib": "rimraf node_modules", 23 + "build:test": "pnpm vite build --mode test",
25 "commit": "czg", 24 "commit": "czg",
26 - "dev": "vite",  
27 - "gen:icon": "esno ./build/generate/icon/index.ts", 25 + "dev": "pnpm vite",
28 "preinstall": "npx only-allow pnpm", 26 "preinstall": "npx only-allow pnpm",
29 "postinstall": "turbo run stub", 27 "postinstall": "turbo run stub",
30 "lint": "turbo run lint", 28 "lint": "turbo run lint",
31 "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", 29 "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
32 - "lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", 30 + "lint:prettier": "prettier --write .",
33 "lint:stylelint": "stylelint \"**/*.{vue,css,less.scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/", 31 "lint:stylelint": "stylelint \"**/*.{vue,css,less.scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/",
34 "prepare": "husky install", 32 "prepare": "husky install",
35 "preview": "npm run build && vite preview", 33 "preview": "npm run build && vite preview",
36 - "preview:dist": "vite preview",  
37 "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", 34 "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
38 - "report": "cross-env REPORT=true npm run build",  
39 "serve": "npm run dev", 35 "serve": "npm run dev",
40 - "test:br": "npx http-server dist --cors --brotli -c-1",  
41 "test:gzip": "npx http-server dist --cors --gzip -c-1", 36 "test:gzip": "npx http-server dist --cors --gzip -c-1",
42 - "test:unit": "jest",  
43 "type:check": "vue-tsc --noEmit --skipLibCheck" 37 "type:check": "vue-tsc --noEmit --skipLibCheck"
44 }, 38 },
45 "lint-staged": { 39 "lint-staged": {
@@ -82,7 +76,7 @@ @@ -82,7 +76,7 @@
82 "@vueuse/core": "^9.13.0", 76 "@vueuse/core": "^9.13.0",
83 "@vueuse/shared": "^9.13.0", 77 "@vueuse/shared": "^9.13.0",
84 "@zxcvbn-ts/core": "^2.2.1", 78 "@zxcvbn-ts/core": "^2.2.1",
85 - "ant-design-vue": "^3.2.16", 79 + "ant-design-vue": "^3.2.17",
86 "axios": "^1.3.4", 80 "axios": "^1.3.4",
87 "codemirror": "^5.65.12", 81 "codemirror": "^5.65.12",
88 "cropperjs": "^1.5.13", 82 "cropperjs": "^1.5.13",
@@ -121,12 +115,9 @@ @@ -121,12 +115,9 @@
121 "@purge-icons/generated": "^0.9.0", 115 "@purge-icons/generated": "^0.9.0",
122 "@types/codemirror": "^5.60.7", 116 "@types/codemirror": "^5.60.7",
123 "@types/crypto-js": "^4.1.1", 117 "@types/crypto-js": "^4.1.1",
124 - "@types/fs-extra": "^11.0.1",  
125 - "@types/inquirer": "^8.2.6",  
126 "@types/intro.js": "^5.1.1", 118 "@types/intro.js": "^5.1.1",
127 "@types/lodash-es": "^4.17.7", 119 "@types/lodash-es": "^4.17.7",
128 "@types/mockjs": "^1.0.7", 120 "@types/mockjs": "^1.0.7",
129 - "@types/node": "^18.15.11",  
130 "@types/nprogress": "^0.2.0", 121 "@types/nprogress": "^0.2.0",
131 "@types/qrcode": "^1.5.0", 122 "@types/qrcode": "^1.5.0",
132 "@types/qs": "^6.9.7", 123 "@types/qs": "^6.9.7",
@@ -135,6 +126,7 @@ @@ -135,6 +126,7 @@
135 "@vben/eslint-config": "workspace:*", 126 "@vben/eslint-config": "workspace:*",
136 "@vben/stylelint-config": "workspace:*", 127 "@vben/stylelint-config": "workspace:*",
137 "@vben/ts-config": "workspace:*", 128 "@vben/ts-config": "workspace:*",
  129 + "@vben/vite-config": "workspace:*",
138 "@vitejs/plugin-vue": "^4.1.0", 130 "@vitejs/plugin-vue": "^4.1.0",
139 "@vitejs/plugin-vue-jsx": "^3.0.1", 131 "@vitejs/plugin-vue-jsx": "^3.0.1",
140 "@vue/compiler-sfc": "^3.2.47", 132 "@vue/compiler-sfc": "^3.2.47",
@@ -142,32 +134,16 @@ @@ -142,32 +134,16 @@
142 "cross-env": "^7.0.3", 134 "cross-env": "^7.0.3",
143 "cz-git": "^1.6.1", 135 "cz-git": "^1.6.1",
144 "czg": "^1.6.1", 136 "czg": "^1.6.1",
145 - "dotenv": "^16.0.3",  
146 - "esno": "^0.16.3",  
147 - "fs-extra": "^11.1.1",  
148 "husky": "^8.0.3", 137 "husky": "^8.0.3",
149 - "inquirer": "^9.1.5",  
150 - "less": "^4.1.3",  
151 "lint-staged": "13.2.0", 138 "lint-staged": "13.2.0",
152 - "picocolors": "^1.0.0",  
153 - "postcss": "^8.4.21",  
154 - "postcss-html": "^1.5.0",  
155 - "postcss-less": "^6.0.0",  
156 "prettier": "^2.8.7", 139 "prettier": "^2.8.7",
157 "prettier-plugin-packagejson": "^2.4.3", 140 "prettier-plugin-packagejson": "^2.4.3",
158 "rimraf": "^4.4.1", 141 "rimraf": "^4.4.1",
159 - "rollup-plugin-visualizer": "^5.9.0",  
160 - "sass": "^1.60.0",  
161 "turbo": "^1.8.8", 142 "turbo": "^1.8.8",
162 "typescript": "^5.0.3", 143 "typescript": "^5.0.3",
163 "unbuild": "^1.2.0", 144 "unbuild": "^1.2.0",
164 "vite": "^4.3.0-beta.1", 145 "vite": "^4.3.0-beta.1",
165 - "vite-plugin-compression": "^0.5.1",  
166 - "vite-plugin-html": "^3.2.0",  
167 "vite-plugin-mock": "^2.9.6", 146 "vite-plugin-mock": "^2.9.6",
168 - "vite-plugin-purge-icons": "^0.9.2",  
169 - "vite-plugin-svg-icons": "^2.0.1",  
170 - "vite-plugin-windicss": "^1.8.10",  
171 "vue-tsc": "^1.2.0" 147 "vue-tsc": "^1.2.0"
172 }, 148 },
173 "packageManager": "pnpm@8.1.0", 149 "packageManager": "pnpm@8.1.0",