Rodney Chen
2024-06-18 d40e59205eeabf112af3dcd5780b7943d454e8d6
干净版internal
已修改1个文件
已添加37个文件
1131 ■■■■■ 文件已修改
.gitignore 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/.eslintignore 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/.eslintrc.cjs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/build.config.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/package.json 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/src/index.ts 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/src/strict.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/eslint-config/tsconfig.json 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/stylelint-config/.eslintignore 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/stylelint-config/.eslintrc.cjs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/stylelint-config/build.config.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/stylelint-config/package.json 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/stylelint-config/src/index.ts 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/stylelint-config/tsconfig.json 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/ts-config/base.json 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/ts-config/node-server.json 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/ts-config/node.json 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/ts-config/package.json 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/ts-config/vue-app.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/.eslintignore 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/.eslintrc.cjs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/build.config.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/package.json 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/config/application.ts 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/config/common.ts 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/config/package.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/appConfig.ts 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/compress.ts 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/html.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/index.ts 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/mock.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/svgSprite.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/plugins/visualizer.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/utils/env.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/utils/hash.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/src/utils/modifyVars.ts 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
internal/vite-config/tsconfig.json 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -43,4 +43,4 @@
.history
.vscode/extensions.json
.vscode/settings.json
internal/
internal/eslint-config/.eslintignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.turbo
dist
package.json
internal/eslint-config/.eslintrc.cjs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
module.exports = {
  root: true,
  extends: ['@vben/eslint-config/strict'],
};
internal/eslint-config/build.config.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
  clean: true,
  entries: ['src/index', 'src/strict'],
  declaration: true,
  rollup: {
    emitCJS: true,
  },
});
internal/eslint-config/package.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
{
  "name": "@vben/eslint-config",
  "version": "1.0.0",
  "private": true,
  "homepage": "https://github.com/vbenjs/vue-vben-admin",
  "bugs": {
    "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
    "directory": "internal/eslint-config"
  },
  "license": "MIT",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    },
    "./strict": {
      "types": "./dist/strict.d.ts",
      "import": "./dist/strict.mjs",
      "require": "./dist/strict.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "dist"
  ],
  "scripts": {
    "clean": "pnpm rimraf .turbo node_modules dist",
    "lint": "pnpm eslint .",
    "stub": "pnpm unbuild --stub"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^7.0.1",
    "@typescript-eslint/parser": "^7.0.1",
    "eslint": "^8.56.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-prettier": "^5.1.3",
    "eslint-plugin-simple-import-sort": "^12.0.0",
    "eslint-plugin-vue": "^9.21.1",
    "vue-eslint-parser": "^9.4.2"
  }
}
internal/eslint-config/src/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
export default {
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2020,
    sourceType: 'module',
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true,
    },
    project: './tsconfig.*?.json',
    createDefaultProgram: false,
    extraFileExtensions: ['.vue'],
  },
  plugins: ['vue', '@typescript-eslint', 'import'],
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  rules: {
    'no-unused-vars': 'off',
    'no-case-declarations': 'off',
    'no-use-before-define': 'off',
    'space-before-function-paren': 'off',
    'import/first': 'error',
    'import/newline-after-import': 'error',
    'import/no-duplicates': 'error',
    '@typescript-eslint/no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      },
    ],
    '@typescript-eslint/ban-ts-ignore': 'off',
    '@typescript-eslint/ban-ts-comment': 'off',
    '@typescript-eslint/ban-types': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-var-requires': 'off',
    '@typescript-eslint/no-empty-function': 'off',
    '@typescript-eslint/no-use-before-define': 'off',
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    'vue/script-setup-uses-vars': 'error',
    'vue/no-reserved-component-names': 'off',
    'vue/custom-event-name-casing': 'off',
    'vue/attributes-order': 'off',
    'vue/one-component-per-file': 'off',
    'vue/html-closing-bracket-newline': 'off',
    'vue/max-attributes-per-line': 'off',
    'vue/multiline-html-element-content-newline': 'off',
    'vue/singleline-html-element-content-newline': 'off',
    'vue/attribute-hyphenation': 'off',
    'vue/require-default-prop': 'off',
    'vue/require-explicit-emits': 'off',
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'always',
          normal: 'never',
          component: 'always',
        },
        svg: 'always',
        math: 'always',
      },
    ],
    'vue/multi-word-component-names': 'off',
    // 'sort-imports': [
    //   'error',
    //   {
    //     ignoreCase: true,
    //     ignoreDeclarationSort: false,
    //     ignoreMemberSort: false,
    //     memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
    //     allowSeparatedGroups: false,
    //   },
    // ],
  },
  globals: { defineOptions: 'readonly' },
};
internal/eslint-config/src/strict.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
export default {
  extends: ['@vben'],
  plugins: ['simple-import-sort'],
  rules: {
    'simple-import-sort/imports': 'error',
    'simple-import-sort/exports': 'error',
    '@typescript-eslint/ban-ts-comment': [
      'error',
      {
        'ts-expect-error': 'allow-with-description',
        'ts-ignore': 'allow-with-description',
        'ts-nocheck': 'allow-with-description',
        'ts-check': false,
      },
    ],
    /**
     * ã€å¼ºåˆ¶ã€‘关键字前后有一个空格
     * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/keyword-spacing.md
     */
    'keyword-spacing': 'off',
    '@typescript-eslint/keyword-spacing': [
      'error',
      {
        before: true,
        after: true,
        overrides: {
          return: { after: true },
          throw: { after: true },
          case: { after: true },
        },
      },
    ],
    /**
     * ç¦æ­¢å‡ºçŽ°ç©ºå‡½æ•°ï¼Œæ™®é€šå‡½æ•°ï¼ˆéž async/await/generator)、箭头函数、类上的方法除外
     * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-function.md
     */
    'no-empty-function': 'off',
    '@typescript-eslint/no-empty-function': [
      'error',
      {
        allow: ['arrowFunctions', 'functions', 'methods'],
      },
    ],
    /**
     * ä¼˜å…ˆä½¿ç”¨ interface è€Œä¸æ˜¯ type å®šä¹‰å¯¹è±¡ç±»åž‹
     * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-definitions.md
     */
    '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
    'vue/attributes-order': 'error',
    'vue/require-default-prop': 'error',
  },
};
internal/eslint-config/tsconfig.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": "@vben/ts-config/node.json",
  "include": ["src"]
}
internal/stylelint-config/.eslintignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.turbo
dist
package.json
internal/stylelint-config/.eslintrc.cjs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
module.exports = {
  root: true,
  extends: ['@vben/eslint-config/strict'],
};
internal/stylelint-config/build.config.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
  clean: true,
  entries: ['src/index'],
  declaration: true,
  rollup: {
    emitCJS: true,
  },
});
internal/stylelint-config/package.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
{
  "name": "@vben/stylelint-config",
  "version": "1.0.0",
  "private": true,
  "homepage": "https://github.com/vbenjs/vue-vben-admin",
  "bugs": {
    "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
    "directory": "internal/stylelint-config"
  },
  "license": "MIT",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "dist"
  ],
  "scripts": {
    "clean": "pnpm rimraf .turbo node_modules dist",
    "lint": "pnpm eslint .",
    "stub": "pnpm unbuild --stub"
  },
  "devDependencies": {
    "postcss": "^8.4.38",
    "postcss-html": "^1.6.0",
    "postcss-less": "^6.0.0",
    "postcss-scss": "^4.0.9",
    "prettier": "^3.2.5",
    "stylelint": "^16.4.0",
    "stylelint-config-property-sort-order-smacss": "^10.0.0",
    "stylelint-config-recommended-scss": "^14.0.0",
    "stylelint-config-recommended-vue": "^1.5.0",
    "stylelint-config-standard": "^36.0.0",
    "stylelint-config-standard-scss": "^13.1.0",
    "stylelint-order": "^6.0.4",
    "stylelint-prettier": "^5.0.0"
  }
}
internal/stylelint-config/src/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
export default {
  extends: ['stylelint-config-standard', 'stylelint-config-property-sort-order-smacss'],
  plugins: ['stylelint-order', 'stylelint-prettier'],
  // customSyntax: 'postcss-html',
  overrides: [
    {
      files: ['**/*.(css|html|vue)'],
      customSyntax: 'postcss-html',
    },
    {
      files: ['*.less', '**/*.less'],
      customSyntax: 'postcss-less',
      extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
    },
    {
      files: ['*.scss', '**/*.scss'],
      customSyntax: 'postcss-scss',
      extends: ['stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'],
      rule: {
        'scss/percent-placeholder-pattern': null,
      },
    },
  ],
  rules: {
    'prettier/prettier': true,
    'media-feature-range-notation': null,
    'selector-not-notation': null,
    'import-notation': null,
    'function-no-unknown': null,
    'selector-class-pattern': null,
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['global', 'deep'],
      },
    ],
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep'],
      },
    ],
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          'tailwind',
          'apply',
          'variants',
          'responsive',
          'screen',
          'function',
          'if',
          'each',
          'include',
          'mixin',
          'extend',
        ],
      },
    ],
    'no-empty-source': null,
    'named-grid-areas-no-invalid': null,
    'no-descending-specificity': null,
    'font-family-no-missing-generic-family-keyword': null,
    'rule-empty-line-before': [
      'always',
      {
        ignore: ['after-comment', 'first-nested'],
      },
    ],
    'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
    'order/order': [
      [
        'dollar-variables',
        'custom-properties',
        'at-rules',
        'declarations',
        {
          type: 'at-rule',
          name: 'supports',
        },
        {
          type: 'at-rule',
          name: 'media',
        },
        'rules',
      ],
      { severity: 'error' },
    ],
  },
  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
};
internal/stylelint-config/tsconfig.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": "@vben/ts-config/node.json",
  "include": ["src"]
}
internal/ts-config/base.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Base",
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "declaration": true,
    "noImplicitOverride": true,
    "noUnusedLocals": true,
    "esModuleInterop": true,
    "useUnknownInCatchVariables": false,
    "composite": false,
    "declarationMap": false,
    "forceConsistentCasingInFileNames": true,
    "inlineSources": false,
    "isolatedModules": true,
    "skipLibCheck": true,
    "noUnusedParameters": false,
    "preserveWatchOutput": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "removeComments": true
  },
  "exclude": ["**/node_modules/**", "**/dist/**"]
}
internal/ts-config/node-server.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node Server  Config",
  "extends": "./base.json",
  "compilerOptions": {
    "module": "commonjs",
    "declaration": false,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es6",
    "sourceMap": false,
    "esModuleInterop": true,
    "outDir": "./dist",
    "baseUrl": "./"
  },
  "exclude": ["node_modules"]
}
internal/ts-config/node.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node Config",
  "extends": "./base.json",
  "compilerOptions": {
    "lib": ["ESNext"],
    "noImplicitAny": true,
    "sourceMap": true,
    "noEmit": true,
    "baseUrl": "./"
  }
}
internal/ts-config/package.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
{
  "name": "@vben/ts-config",
  "version": "1.0.0",
  "private": true,
  "homepage": "https://github.com/vbenjs/vue-vben-admin",
  "bugs": {
    "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
    "directory": "internal/ts-config"
  },
  "license": "MIT",
  "type": "module",
  "files": [
    "base.json",
    "node.json",
    "vue-app.json",
    "node-server.json"
  ],
  "dependencies": {
    "@types/node": "^20.12.7",
    "vite": "^5.2.10"
  }
}
internal/ts-config/vue-app.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Vue Application",
  "extends": "./base.json",
  "compilerOptions": {
    "jsx": "preserve",
    "lib": ["ESNext", "DOM"],
    "noImplicitAny": false
  }
}
internal/vite-config/.eslintignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.turbo
dist
package.json
internal/vite-config/.eslintrc.cjs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
module.exports = {
  root: true,
  extends: ['@vben/eslint-config/strict'],
};
internal/vite-config/build.config.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
  clean: true,
  entries: ['src/index'],
  declaration: true,
  rollup: {
    emitCJS: true,
  },
});
internal/vite-config/package.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
{
  "name": "@vben/vite-config",
  "version": "1.0.0",
  "private": true,
  "homepage": "https://github.com/vbenjs/vue-vben-admin",
  "bugs": {
    "url": "https://github.com/vbenjs/vue-vben-admin/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
    "directory": "internal/vite-config"
  },
  "license": "MIT",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "dist"
  ],
  "scripts": {
    "clean": "pnpm rimraf .turbo node_modules dist",
    "lint": "pnpm eslint .",
    "stub": "pnpm unbuild --stub"
  },
  "dependencies": {
    "@ant-design/colors": "^7.0.2",
    "vite": "^5.2.10"
  },
  "devDependencies": {
    "@types/fs-extra": "^11.0.4",
    "@vitejs/plugin-vue": "^5.0.4",
    "@vitejs/plugin-vue-jsx": "^3.1.0",
    "ant-design-vue": "^4.2.1",
    "dayjs": "^1.11.10",
    "dotenv": "^16.4.5",
    "fs-extra": "^11.2.0",
    "less": "^4.2.0",
    "picocolors": "^1.0.0",
    "pkg-types": "^1.1.0",
    "rollup-plugin-visualizer": "^5.12.0",
    "sass": "^1.75.0",
    "unocss": "0.59.4",
    "vite-plugin-compression": "^0.5.1",
    "vite-plugin-dts": "^3.9.0",
    "vite-plugin-html": "^3.2.2",
    "vite-plugin-mock": "^2.9.6",
    "vite-plugin-purge-icons": "^0.10.0",
    "vite-plugin-svg-icons": "^2.0.1"
  }
}
internal/vite-config/src/config/application.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
import { resolve } from 'node:path';
import dayjs from 'dayjs';
import { readPackageJSON } from 'pkg-types';
import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite';
import { createPlugins } from '../plugins';
import { generateModifyVars } from '../utils/modifyVars';
import { commonConfig } from './common';
interface DefineOptions {
  overrides?: UserConfig;
  options?: {
    //
  };
}
function defineApplicationConfig(defineOptions: DefineOptions = {}) {
  const { overrides = {} } = defineOptions;
  return defineConfig(async ({ command, mode }) => {
    const root = process.cwd();
    const isBuild = command === 'build';
    const { VITE_PUBLIC_PATH, VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv(
      mode,
      root,
    );
    const defineData = await createDefineData(root);
    const plugins = await createPlugins({
      isBuild,
      root,
      enableAnalyze: VITE_ENABLE_ANALYZE === 'true',
      enableMock: VITE_USE_MOCK === 'true',
      compress: VITE_BUILD_COMPRESS,
    });
    const pathResolve = (pathname: string) => resolve(root, '.', pathname);
    const applicationConfig: UserConfig = {
      base: VITE_PUBLIC_PATH,
      resolve: {
        alias: [
          {
            find: 'vue-i18n',
            replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
          },
          // @/xxxx => src/xxxx
          {
            find: /@\//,
            replacement: pathResolve('src') + '/',
          },
          // #/xxxx => types/xxxx
          {
            find: /#\//,
            replacement: pathResolve('types') + '/',
          },
        ],
      },
      define: defineData,
      build: {
        target: 'es2015',
        cssTarget: 'chrome80',
        rollupOptions: {
          output: {
            // å…¥å£æ–‡ä»¶å
            entryFileNames: 'assets/entry/[name]-[hash].js',
            manualChunks: {
              vue: ['vue', 'pinia', 'vue-router'],
              antd: ['ant-design-vue', '@ant-design/icons-vue'],
            },
          },
        },
      },
      css: {
        preprocessorOptions: {
          less: {
            modifyVars: generateModifyVars(),
            javascriptEnabled: true,
          },
        },
      },
      plugins,
    };
    const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig);
    return mergeConfig(mergedConfig, overrides);
  });
}
async function createDefineData(root: string) {
  try {
    const pkgJson = await readPackageJSON(root);
    const { dependencies, devDependencies, name, version } = pkgJson;
    const __APP_INFO__ = {
      pkg: { dependencies, devDependencies, name, version },
      lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
    };
    return {
      __APP_INFO__: JSON.stringify(__APP_INFO__),
    };
  } catch (error) {
    return {};
  }
}
export { defineApplicationConfig };
internal/vite-config/src/config/common.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
import UnoCSS from 'unocss/vite';
import { type UserConfig } from 'vite';
const commonConfig: (mode: string) => UserConfig = (mode) => ({
  server: {
    host: true,
  },
  esbuild: {
    drop: mode === 'production' ? ['console', 'debugger'] : [],
  },
  build: {
    reportCompressedSize: false,
    chunkSizeWarningLimit: 1500,
    rollupOptions: {
      // TODO: Prevent memory overflow
      maxParallelFileOps: 3,
    },
  },
  plugins: [UnoCSS()],
});
export { commonConfig };
internal/vite-config/src/config/package.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
import { readPackageJSON } from 'pkg-types';
import { defineConfig, mergeConfig, type UserConfig } from 'vite';
import dts from 'vite-plugin-dts';
import { commonConfig } from './common';
interface DefineOptions {
  overrides?: UserConfig;
  options?: {
    //
  };
}
function definePackageConfig(defineOptions: DefineOptions = {}) {
  const { overrides = {} } = defineOptions;
  const root = process.cwd();
  return defineConfig(async ({ mode }) => {
    const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root);
    const packageConfig: UserConfig = {
      build: {
        lib: {
          entry: 'src/index.ts',
          formats: ['es'],
          fileName: () => 'index.mjs',
        },
        rollupOptions: {
          external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)],
        },
      },
      plugins: [
        dts({
          logLevel: 'error',
        }),
      ],
    };
    const mergedConfig = mergeConfig(commonConfig(mode), packageConfig);
    return mergeConfig(mergedConfig, overrides);
  });
}
export { definePackageConfig };
internal/vite-config/src/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,2 @@
export * from './config/application';
export * from './config/package';
internal/vite-config/src/plugins/appConfig.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@
import colors from 'picocolors';
import { readPackageJSON } from 'pkg-types';
import { type PluginOption } from 'vite';
import { getEnvConfig } from '../utils/env';
import { createContentHash } from '../utils/hash';
const GLOBAL_CONFIG_FILE_NAME = '_app.config.js';
const PLUGIN_NAME = 'app-config';
async function createAppConfigPlugin({
  root,
  isBuild,
}: {
  root: string;
  isBuild: boolean;
}): Promise<PluginOption> {
  let publicPath: string;
  let source: string;
  if (!isBuild) {
    return {
      name: PLUGIN_NAME,
    };
  }
  const { version = '' } = await readPackageJSON(root);
  return {
    name: PLUGIN_NAME,
    async configResolved(_config) {
      const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? '';
      // appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_');
      publicPath = _config.base;
      source = await getConfigSource(appTitle);
    },
    async transformIndexHtml(html) {
      publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
      const appConfigSrc = `${
        publicPath || '/'
      }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`;
      return {
        html,
        tags: [
          {
            tag: 'script',
            attrs: {
              src: appConfigSrc,
            },
          },
        ],
      };
    },
    async generateBundle() {
      try {
        this.emitFile({
          type: 'asset',
          fileName: GLOBAL_CONFIG_FILE_NAME,
          source,
        });
        console.log(colors.cyan(`✨configuration file is build successfully!`));
      } catch (error) {
        console.log(
          colors.red('configuration file configuration file failed to package:\n' + error),
        );
      }
    },
  };
}
/**
 * Get the configuration file variable name
 * @param env
 */
const getVariableName = (title: string) => {
  function strToHex(str: string) {
    const result: string[] = [];
    for (let i = 0; i < str.length; ++i) {
      const hex = str.charCodeAt(i).toString(16);
      result.push(('000' + hex).slice(-4));
    }
    return result.join('').toUpperCase();
  }
  return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
};
async function getConfigSource(appTitle: string) {
  const config = await getEnvConfig();
  const variableName = getVariableName(appTitle);
  const windowVariable = `window.${variableName}`;
  // Ensure that the variable will not be modified
  let source = `${windowVariable}=${JSON.stringify(config)};`;
  source += `
    Object.freeze(${windowVariable});
    Object.defineProperty(window, "${variableName}", {
      configurable: false,
      writable: false,
    });
  `.replace(/\s/g, '');
  return source;
}
export { createAppConfigPlugin };
internal/vite-config/src/plugins/compress.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
/**
 * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
 * https://github.com/anncwb/vite-plugin-compression
 */
import type { PluginOption } from 'vite';
import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin({
  compress,
  deleteOriginFile = false,
}: {
  compress: string;
  deleteOriginFile?: boolean;
}): PluginOption[] {
  const compressList = compress.split(',');
  const plugins: PluginOption[] = [];
  if (compressList.includes('gzip')) {
    plugins.push(
      compressPlugin({
        ext: '.gz',
        deleteOriginFile,
      }),
    );
  }
  if (compressList.includes('brotli')) {
    plugins.push(
      compressPlugin({
        ext: '.br',
        algorithm: 'brotliCompress',
        deleteOriginFile,
      }),
    );
  }
  return plugins;
}
internal/vite-config/src/plugins/html.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
/**
 * Plugin to minimize and use ejs template syntax in index.html.
 * https://github.com/anncwb/vite-plugin-html
 */
import type { PluginOption } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) {
  const htmlPlugin: PluginOption[] = createHtmlPlugin({
    minify: isBuild,
  });
  return htmlPlugin;
}
internal/vite-config/src/plugins/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { type PluginOption } from 'vite';
import purgeIcons from 'vite-plugin-purge-icons';
import DevTools from 'vite-plugin-vue-devtools';
import { createAppConfigPlugin } from './appConfig';
import { configCompressPlugin } from './compress';
import { configHtmlPlugin } from './html';
import { configMockPlugin } from './mock';
import { configSvgIconsPlugin } from './svgSprite';
import { configVisualizerConfig } from './visualizer';
interface Options {
  isBuild: boolean;
  root: string;
  compress: string;
  enableMock?: boolean;
  enableAnalyze?: boolean;
}
async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) {
  const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()];
  const appConfigPlugin = await createAppConfigPlugin({ root, isBuild });
  vitePlugins.push(appConfigPlugin);
  vitePlugins.push(DevTools());
  // vite-plugin-html
  vitePlugins.push(configHtmlPlugin({ isBuild }));
  // vite-plugin-svg-icons
  vitePlugins.push(configSvgIconsPlugin({ isBuild }));
  // vite-plugin-purge-icons
  vitePlugins.push(purgeIcons());
  // The following plugins only work in the production environment
  if (isBuild) {
    // rollup-plugin-gzip
    vitePlugins.push(
      configCompressPlugin({
        compress,
      }),
    );
  }
  // rollup-plugin-visualizer
  if (enableAnalyze) {
    vitePlugins.push(configVisualizerConfig());
  }
  // vite-plugin-mock
  if (enableMock) {
    vitePlugins.push(configMockPlugin({ isBuild }));
  }
  return vitePlugins;
}
export { createPlugins };
internal/vite-config/src/plugins/mock.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
/**
 * Mock plugin for development and production.
 * https://github.com/anncwb/vite-plugin-mock
 */
import { viteMockServe } from 'vite-plugin-mock';
export function configMockPlugin({ isBuild }: { isBuild: boolean }) {
  return viteMockServe({
    ignore: /^_/,
    mockPath: 'mock',
    localEnabled: !isBuild,
    prodEnabled: isBuild,
    injectCode: `
      import { setupProdMockServer } from '../mock/_createProductionServer';
      setupProdMockServer();
      `,
  });
}
internal/vite-config/src/plugins/svgSprite.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
/**
 *  Vite Plugin for fast creating SVG sprites.
 * https://github.com/anncwb/vite-plugin-svg-icons
 */
import { resolve } from 'node:path';
import type { PluginOption } from 'vite';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) {
  const svgIconsPlugin = createSvgIconsPlugin({
    iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
    svgoOptions: isBuild,
  });
  return svgIconsPlugin as PluginOption;
}
internal/vite-config/src/plugins/visualizer.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
/**
 * Package file volume analysis
 */
import visualizer from 'rollup-plugin-visualizer';
import { type PluginOption } from 'vite';
export function configVisualizerConfig() {
  return visualizer({
    filename: './node_modules/.cache/visualizer/stats.html',
    open: true,
    gzipSize: true,
    brotliSize: true,
  }) as PluginOption;
}
internal/vite-config/src/utils/env.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
import { join } from 'node:path';
import dotenv from 'dotenv';
import { readFile } from 'fs-extra';
/**
 * èŽ·å–å½“å‰çŽ¯å¢ƒä¸‹ç”Ÿæ•ˆçš„é…ç½®æ–‡ä»¶å
 */
function getConfFiles() {
  const script = process.env.npm_lifecycle_script as string;
  const reg = new RegExp('--mode ([a-z_\\d]+)');
  const result = reg.exec(script);
  if (result) {
    const mode = result[1];
    return ['.env', `.env.${mode}`];
  }
  return ['.env', '.env.production'];
}
/**
 * Get the environment variables starting with the specified prefix
 * @param match prefix
 * @param confFiles ext
 */
export async function getEnvConfig(
  match = 'VITE_GLOB_',
  confFiles = getConfFiles(),
): Promise<{
  [key: string]: string;
}> {
  let envConfig = {};
  for (const confFile of confFiles) {
    try {
      const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' });
      const env = dotenv.parse(envPath);
      envConfig = { ...envConfig, ...env };
    } catch (e) {
      console.error(`Error in parsing ${confFile}`, e);
    }
  }
  const reg = new RegExp(`^(${match})`);
  Object.keys(envConfig).forEach((key) => {
    if (!reg.test(key)) {
      Reflect.deleteProperty(envConfig, key);
    }
  });
  return envConfig;
}
internal/vite-config/src/utils/hash.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
import { createHash } from 'node:crypto';
function createContentHash(content: string, hashLSize = 12) {
  const hash = createHash('sha256').update(content);
  return hash.digest('hex').slice(0, hashLSize);
}
function strToHex(str: string) {
  const result: string[] = [];
  for (let i = 0; i < str.length; ++i) {
    const hex = str.charCodeAt(i).toString(16);
    result.push(('000' + hex).slice(-4));
  }
  return result.join('').toUpperCase();
}
export { createContentHash, strToHex };
internal/vite-config/src/utils/modifyVars.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
import { resolve } from 'node:path';
import { generate } from '@ant-design/colors';
// @ts-ignore: typo
/* import { getThemeVariables } from 'ant-design-vue/dist/theme'; */
import { theme } from 'ant-design-vue/lib';
import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken';
const { defaultAlgorithm, defaultSeed } = theme;
const primaryColor = '#0960bd';
function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') {
  return generate(color, {
    theme,
  });
}
/**
 * less global variable
 */
export function generateModifyVars() {
  const palettes = generateAntColors(primaryColor);
  const primary = palettes[5];
  const primaryColorObj: Record<string, string> = {};
  for (let index = 0; index < 10; index++) {
    primaryColorObj[`primary-${index + 1}`] = palettes[index];
  }
  // const modifyVars = getThemeVariables();
  const mapToken = defaultAlgorithm(defaultSeed);
  const v3Token = convertLegacyToken(mapToken);
  return {
    ...v3Token,
    // reference:  Avoid repeated references
    hack: `true; @import (reference) "${resolve('src/design/config.less')}";`,
    'primary-color': primary,
    ...primaryColorObj,
    'info-color': primary,
    'processing-color': primary,
    'success-color': '#55D187', //  Success color
    'error-color': '#ED6F6F', //  False color
    'warning-color': '#EFBD47', //   Warning color
    'font-size-base': '14px', //  Main font size
    'border-radius-base': '2px', //  Component/float fillet
    'link-color': primary, //   Link color
  };
}
internal/vite-config/tsconfig.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": "@vben/ts-config/node.json",
  "include": ["src"]
}