diff --git a/package.json b/package.json index 34ed2fc..a79bae2 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "@vue/eslint-config-typescript": "^14.6.0", "@vue/test-utils": "^2.4.6", "@vue/tsconfig": "^0.8.1", + "consola": "^3.4.2", "eslint": "^9.35.0", "eslint-plugin-oxlint": "~1.23.0", "eslint-plugin-playwright": "^2.2.2", @@ -107,6 +108,7 @@ "stylelint-config-standard-scss": "^16.0.0", "stylelint-config-standard-vue": "^1.0.0", "stylelint-define-config": "^16.24.0", + "tinyglobby": "^0.2.15", "typescript": "~5.9.2", "unocss": "^66.5.1", "unocss-preset-animations": "^1.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e42d5a..b290519 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -135,6 +135,9 @@ importers: '@vue/tsconfig': specifier: ^0.8.1 version: 0.8.1(typescript@5.9.2)(vue@3.5.22(typescript@5.9.2)) + consola: + specifier: ^3.4.2 + version: 3.4.2 eslint: specifier: ^9.35.0 version: 9.38.0(jiti@2.6.1) @@ -201,6 +204,9 @@ importers: stylelint-define-config: specifier: ^16.24.0 version: 16.24.0(stylelint@16.25.0(typescript@5.9.2)) + tinyglobby: + specifier: ^0.2.15 + version: 0.2.15 typescript: specifier: ~5.9.2 version: 5.9.2 diff --git a/tsconfig.node.json b/tsconfig.node.json index e0c1690..63809e1 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -8,6 +8,7 @@ "playwright.config.*", "eslint.config.*", "stylelint.config.*", + "vite-plugins", "fake/**/*" ], "compilerOptions": { @@ -16,6 +17,7 @@ "module": "ESNext", "moduleResolution": "Bundler", - "types": ["node"] + "types": ["node"], + "allowImportingTsExtensions": true } } diff --git a/vite-plugins/00.vue-macros.ts b/vite-plugins/00.vue-macros.ts new file mode 100644 index 0000000..4a592c8 --- /dev/null +++ b/vite-plugins/00.vue-macros.ts @@ -0,0 +1,26 @@ +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; +import { getPascalCaseRouteName } from 'unplugin-vue-router'; +import vueRouter from 'unplugin-vue-router/vite'; +import type { PluginOption } from 'vite'; +import VueMacros from 'vue-macros/vite'; + +export default [ + VueMacros({ + plugins: { + vue: vue({ include: [/\.vue$/, /\.md$/] }), + vueJsx: vueJsx(), + + // https://uvr.esm.is/guide/configuration.html + // https://github.com/posva/unplugin-vue-router + // ⚠️ Vue must be placed after VueRouter() + vueRouter: vueRouter({ + exclude: ['**/__*', '**/__*/**/*'], + extensions: ['.page.vue', '.page.md'], + getRouteName: (routeNode) => getPascalCaseRouteName(routeNode), + logs: false, + routesFolder: 'src/pages', + }), + }, + }), +] satisfies PluginOption; diff --git a/vite-plugins/02.vite-plugin-vue-layouts.disabled.ts b/vite-plugins/02.vite-plugin-vue-layouts.disabled.ts new file mode 100644 index 0000000..93764fe --- /dev/null +++ b/vite-plugins/02.vite-plugin-vue-layouts.disabled.ts @@ -0,0 +1,6 @@ +import type { PluginOption } from 'vite'; + +export default [ + // https://github.com/JohnCampionJr/vite-plugin-vue-layouts?tab=readme-ov-file#configuration + // Layouts({ defaultLayout: 'sakai-vue/AppLayout', pagesDirs: [] }), +] satisfies PluginOption; diff --git a/vite-plugins/02.vite-plugin-vue-meta-layouts.ts b/vite-plugins/02.vite-plugin-vue-meta-layouts.ts new file mode 100644 index 0000000..fb0ba59 --- /dev/null +++ b/vite-plugins/02.vite-plugin-vue-meta-layouts.ts @@ -0,0 +1,12 @@ +import type { PluginOption } from 'vite'; +import MetaLayouts from 'vite-plugin-vue-meta-layouts'; + +export default [ + // https://github.com/dishait/vite-plugin-vue-meta-layouts + MetaLayouts({ + // defaultLayout: 'sakai-vue/AppLayout', + // defaultLayout: 'naive-ui/AppLayout', + defaultLayout: 'base-layout/base-layout', + skipTopLevelRouteLayout: true, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭 + }), +] satisfies PluginOption; diff --git a/vite-plugins/03.unplugin-auto-import.ts b/vite-plugins/03.unplugin-auto-import.ts new file mode 100644 index 0000000..c3071b4 --- /dev/null +++ b/vite-plugins/03.unplugin-auto-import.ts @@ -0,0 +1,29 @@ +import type { PluginOption } from 'vite'; +import AutoImport from 'unplugin-auto-import/vite'; +import { createUtils4uAutoImports } from 'utils4u/auto-imports'; +import { VueRouterAutoImports } from 'unplugin-vue-router'; + +export default [ + // https://github.com/antfu/unplugin-auto-import + AutoImport({ + dirs: [ + // 'src/composables', + // 'src/utils', + 'src/stores', + ], + imports: [ + 'vue', + 'vue-i18n', + 'pinia', + '@vueuse/core', + VueRouterAutoImports, + createUtils4uAutoImports([]), + { + 'consola/browser': ['consola'], + 'vue-router/auto': ['useLink'], + 'naive-ui': ['useModal', 'useDialog', 'useMessage', 'useNotification', 'useLoadingBar'], + }, + ], + vueTemplate: true, + }), +] satisfies PluginOption; diff --git a/vite-plugins/03.unplugin-icons.ts b/vite-plugins/03.unplugin-icons.ts new file mode 100644 index 0000000..23d65f8 --- /dev/null +++ b/vite-plugins/03.unplugin-icons.ts @@ -0,0 +1,17 @@ +import type { PluginOption } from 'vite'; +import { FileSystemIconLoader } from 'unplugin-icons/loaders'; +import Icons from 'unplugin-icons/vite'; + +export default [ + Icons({ + autoInstall: true, + customCollections: { + svg: FileSystemIconLoader('src/assets/icons/svgs', (svg) => { + return svg.replace(/^ or */, + }), // https://github.com/unplugin/unplugin-icons?tab=readme-ov-file#auto-importing + TDesignResolver({ esm: true, library: 'mobile-vue' }), + VantResolver({ importStyle: true }), + PrimeVueResolver(/* { components: { prefix: 'P' } } */), + NaiveUiResolver(), + ], + }), +] satisfies PluginOption; diff --git a/vite.config.plugin.index-html-plugin.ts b/vite-plugins/999.index-html-plugin.ts similarity index 81% rename from vite.config.plugin.index-html-plugin.ts rename to vite-plugins/999.index-html-plugin.ts index 97ecde6..095f1d6 100644 --- a/vite.config.plugin.index-html-plugin.ts +++ b/vite-plugins/999.index-html-plugin.ts @@ -1,7 +1,7 @@ +import type { PluginOption } from 'vite'; import { minify as minifyHtml } from 'html-minifier-terser'; -import { type PluginOption } from 'vite'; -export function IndexHtmlPlugin(): PluginOption { +function IndexHtmlPlugin(): PluginOption { return { name: 'index-html-plugin', apply: 'build', @@ -24,3 +24,5 @@ export function IndexHtmlPlugin(): PluginOption { }, }; } + +export default [IndexHtmlPlugin()] satisfies PluginOption[]; diff --git a/vite-plugins/_x-demo.disabled.ts b/vite-plugins/_x-demo.disabled.ts new file mode 100644 index 0000000..f258958 --- /dev/null +++ b/vite-plugins/_x-demo.disabled.ts @@ -0,0 +1,9 @@ +import type { ConfigEnv, PluginOption } from 'vite'; + +export default [ + // ... +] satisfies PluginOption; + +export function loadPlugin(_configEnv: ConfigEnv): PluginOption { + return []; +} diff --git a/vite-plugins/cloudflare.ts b/vite-plugins/cloudflare.ts new file mode 100644 index 0000000..2245ec4 --- /dev/null +++ b/vite-plugins/cloudflare.ts @@ -0,0 +1,4 @@ +import type { PluginOption } from 'vite'; +import { cloudflare } from '@cloudflare/vite-plugin'; + +export default [cloudflare()] satisfies PluginOption; diff --git a/vite-plugins/unocss.ts b/vite-plugins/unocss.ts new file mode 100644 index 0000000..3226453 --- /dev/null +++ b/vite-plugins/unocss.ts @@ -0,0 +1,8 @@ +import type { PluginOption } from 'vite'; +import UnoCSS from 'unocss/vite'; + +export default [ + // https://github.com/antfu/unocss + // see uno.config.ts for config + UnoCSS(), +] satisfies PluginOption; diff --git a/vite-plugins/unplugin-vue-i18n.ts b/vite-plugins/unplugin-vue-i18n.ts new file mode 100644 index 0000000..c9fa84c --- /dev/null +++ b/vite-plugins/unplugin-vue-i18n.ts @@ -0,0 +1,19 @@ +import type { PluginOption } from 'vite'; +import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'; +import path from 'node:path'; + +export default [ + // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n + VueI18nPlugin({ + /* options */ + // locale messages resource pre-compile option + include: [path.resolve(import.meta.dirname, './src/locales/**')], + + // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#transformi18nblock + // transformI18nBlock(src) { + // console.debug(`src :>> `, src); + // console.debug(`typeof src :>> `, typeof src); + // return src as string; + // }, + }), +] satisfies PluginOption; diff --git a/vite-plugins/unplugin-vue-markdown.ts b/vite-plugins/unplugin-vue-markdown.ts new file mode 100644 index 0000000..67efc86 --- /dev/null +++ b/vite-plugins/unplugin-vue-markdown.ts @@ -0,0 +1,9 @@ +import type { PluginOption } from 'vite'; +import Markdown from 'unplugin-vue-markdown/vite'; + +export default [ + // https://github.com/unplugin/unplugin-vue-markdown + Markdown({ + headEnabled: true, + }), +] satisfies PluginOption; diff --git a/vite-plugins/vite-plugin-checker.ts b/vite-plugins/vite-plugin-checker.ts new file mode 100644 index 0000000..d11a1e6 --- /dev/null +++ b/vite-plugins/vite-plugin-checker.ts @@ -0,0 +1,19 @@ +import type { PluginOption } from 'vite'; +import checker from 'vite-plugin-checker'; + +export default [ + // https://vite-plugin-checker.netlify.app/introduction/introduction.html + checker({ + eslint: { + lintCommand: 'eslint "./src/**/*.{js,jsx,ts,tsx,vue}"', + useFlatConfig: true, + }, + vueTsc: true, + overlay: { + initialIsOpen: false, + }, + terminal: true, + enableBuild: true, + // XXX: pnpm add vls vti -D + }), +] satisfies PluginOption; diff --git a/vite-plugins/vite-plugin-fake-server.ts b/vite-plugins/vite-plugin-fake-server.ts new file mode 100644 index 0000000..1343749 --- /dev/null +++ b/vite-plugins/vite-plugin-fake-server.ts @@ -0,0 +1,16 @@ +import type { ConfigEnv, PluginOption } from 'vite'; +import { vitePluginFakeServer } from 'vite-plugin-fake-server'; +// https://github.com/condorheroblog/vite-plugin-fake-server?tab=readme-ov-file#usage + +// // if (mode !== 'test') {} +// export default [ + +// ] satisfies PluginOption; + +export function loadPlugin(_configEnv: ConfigEnv): PluginOption { + return vitePluginFakeServer({ + basename: 'fake-api', + enableProd: true, + include: 'fake', + }); +} diff --git a/vite-plugins/vite-plugin-image-optimizer.ts b/vite-plugins/vite-plugin-image-optimizer.ts new file mode 100644 index 0000000..351df1d --- /dev/null +++ b/vite-plugins/vite-plugin-image-optimizer.ts @@ -0,0 +1,11 @@ +import type { PluginOption } from 'vite'; +import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'; + +// env.VITE_ENABLE_VUE_DEVTOOLS === 'true' + +export default [ + // https://github.com/FatehAK/vite-plugin-image-optimizer?tab=readme-ov-file#default-configuration + ViteImageOptimizer({ + /* pass your config */ + }), +] satisfies PluginOption; diff --git a/vite-plugins/vite-plugin-vue-devtools.ts b/vite-plugins/vite-plugin-vue-devtools.ts new file mode 100644 index 0000000..9c2267a --- /dev/null +++ b/vite-plugins/vite-plugin-vue-devtools.ts @@ -0,0 +1,6 @@ +import type { PluginOption } from 'vite'; +import vueDevTools from 'vite-plugin-vue-devtools'; + +// env.VITE_ENABLE_VUE_DEVTOOLS === 'true' + +export default [vueDevTools()] satisfies PluginOption; diff --git a/vite-plugins/vite-plugin-webfont-dl.ts b/vite-plugins/vite-plugin-webfont-dl.ts new file mode 100644 index 0000000..948e2ed --- /dev/null +++ b/vite-plugins/vite-plugin-webfont-dl.ts @@ -0,0 +1,11 @@ +import type { PluginOption } from 'vite'; +import { ViteWebfontDownload } from 'vite-plugin-webfont-dl'; + +export default [ + // https://github.com/feat-agency/vite-plugin-webfont-dl?tab=readme-ov-file#-usage-simple-config-method-b- + ViteWebfontDownload([ + 'https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap', + 'https://fonts.googleapis.com/css2?family=Fira+Code&display=swap', + 'https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600,700,900', + ]), +] satisfies PluginOption; diff --git a/vite-plugins/x-vite-plugin-purgecss-v5.ts b/vite-plugins/x-vite-plugin-purgecss-v5.ts new file mode 100644 index 0000000..ad30829 --- /dev/null +++ b/vite-plugins/x-vite-plugin-purgecss-v5.ts @@ -0,0 +1,8 @@ +import type { PluginOption } from 'vite'; + +export default [ + // // https://github.com/rsnakdmx/vite-plugin-purgecss-v5?tab=readme-ov-file#-usage + // pluginPurgeCss({ + // variables: true, + // }), +] satisfies PluginOption; diff --git a/vite-plugins/x-vite-plugin-singlefile.ts b/vite-plugins/x-vite-plugin-singlefile.ts new file mode 100644 index 0000000..6d903f0 --- /dev/null +++ b/vite-plugins/x-vite-plugin-singlefile.ts @@ -0,0 +1,5 @@ +import type { PluginOption } from 'vite'; + +export default [ + // ... +] satisfies PluginOption; diff --git a/vite-plugins/x-vite-plugin-static-copy.ts b/vite-plugins/x-vite-plugin-static-copy.ts new file mode 100644 index 0000000..799e7ab --- /dev/null +++ b/vite-plugins/x-vite-plugin-static-copy.ts @@ -0,0 +1,15 @@ +import type { PluginOption } from 'vite'; + +export default [ + // plugins.push( + // viteStaticCopy({ + // targets: [ + // // globalThis.CESIUM_BASE_URL = 'https://digitalarsenal.io/'; + // { dest: cesiumBaseUrl, src: `${cesiumSource}/ThirdParty` }, + // { dest: cesiumBaseUrl, src: `${cesiumSource}/Workers` }, + // { dest: cesiumBaseUrl, src: `${cesiumSource}/Assets` }, + // { dest: cesiumBaseUrl, src: `${cesiumSource}/Widgets` }, + // ], + // }), + // ) +] satisfies PluginOption; diff --git a/vite-plugins/x-vite-plugin-zip-file.ts b/vite-plugins/x-vite-plugin-zip-file.ts new file mode 100644 index 0000000..37973eb --- /dev/null +++ b/vite-plugins/x-vite-plugin-zip-file.ts @@ -0,0 +1,17 @@ +import type { PluginOption } from 'vite'; + +export default [ + // // 检查是否在VS Code终端中运行 + // if (process.env.TERM_PROGRAM === 'vscode' || process.env.VSCODE_PID) { + // // plugins.push( + // // // 构建后自动将dist目录打包成zip文件 + // // viteArchiverPlugin({ + // // addTimestamp: false, // 是否添加时间戳到输出文件名 + // // format: 'zip', // 输出的压缩文件格式 + // // outputDir: '', // 输出目录,默认为项目根目录 + // // outputFileName: 'dist', // 输出的zip文件名(不含扩展名) + // // sourceDir: 'dist', // 要打包的源目录 + // // }), + // // ) + // } +] satisfies PluginOption; diff --git a/vite.config.optimizeDeps.ts b/vite.config.optimizeDeps.ts index 47dddbd..54db753 100644 --- a/vite.config.optimizeDeps.ts +++ b/vite.config.optimizeDeps.ts @@ -6,7 +6,11 @@ import type { DepOptimizationOptions } from 'vite'; // })(); export function optimizeDeps(): DepOptimizationOptions { return { - entries: ['src/main.ts', 'src/pages/**/*.vue'], + entries: [ + 'src/main.ts', + 'src/pages/**/*.vue', + 'packages/materials/src/index.ts', // > simplebar-vue + ], // include: [ // ...primevuecomponents, // '@primeuix/themes', diff --git a/vite.config.plugins.ts b/vite.config.plugins.ts deleted file mode 100644 index d53ccd3..0000000 --- a/vite.config.plugins.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { cloudflare } from '@cloudflare/vite-plugin'; -import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'; -import { PrimeVueResolver } from '@primevue/auto-import-resolver'; -import { VantResolver } from '@vant/auto-import-resolver'; -import vue from '@vitejs/plugin-vue'; -import vueJsx from '@vitejs/plugin-vue-jsx'; -import path from 'node:path'; -import UnoCSS from 'unocss/vite'; -import AutoImport from 'unplugin-auto-import/vite'; -import { FileSystemIconLoader } from 'unplugin-icons/loaders'; -import IconsResolver from 'unplugin-icons/resolver'; -import Icons from 'unplugin-icons/vite'; -import { - AntDesignVueResolver, - NaiveUiResolver, - TDesignResolver, -} from 'unplugin-vue-components/resolvers'; -import Components from 'unplugin-vue-components/vite'; -import Markdown from 'unplugin-vue-markdown/vite'; -import { getPascalCaseRouteName, VueRouterAutoImports } from 'unplugin-vue-router'; -import vueRouter from 'unplugin-vue-router/vite'; -import { createUtils4uAutoImports } from 'utils4u/auto-imports'; -import { type PluginOption } from 'vite'; -import { checker } from 'vite-plugin-checker'; -import { vitePluginFakeServer } from 'vite-plugin-fake-server'; -import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'; -import vueDevTools from 'vite-plugin-vue-devtools'; -import MetaLayouts from 'vite-plugin-vue-meta-layouts'; -import { ViteWebfontDownload } from 'vite-plugin-webfont-dl'; -import VueMacros from 'vue-macros/vite'; -import { IndexHtmlPlugin } from './vite.config.plugin.index-html-plugin'; - -export function Plugins({ - mode, - env, -}: { - mode: string; - env: Record; -}): PluginOption[] { - const plugins: PluginOption[] = [ - VueMacros({ - plugins: { - vue: vue({ include: [/\.vue$/, /\.md$/] }), - vueJsx: vueJsx(), - - // https://uvr.esm.is/guide/configuration.html - // https://github.com/posva/unplugin-vue-router - // ⚠️ Vue must be placed after VueRouter() - vueRouter: vueRouter({ - exclude: ['**/__*', '**/__*/**/*'], - extensions: ['.page.vue', '.page.md'], - getRouteName: (routeNode) => getPascalCaseRouteName(routeNode), - logs: false, - routesFolder: 'src/pages', - }), - }, - }), - ]; - - plugins.push( - // https://github.com/JohnCampionJr/vite-plugin-vue-layouts?tab=readme-ov-file#configuration - // Layouts({ defaultLayout: 'sakai-vue/AppLayout', pagesDirs: [] }), - - // https://github.com/dishait/vite-plugin-vue-meta-layouts - MetaLayouts({ - // defaultLayout: 'sakai-vue/AppLayout', - // defaultLayout: 'naive-ui/AppLayout', - defaultLayout: 'base-layout/base-layout', - skipTopLevelRouteLayout: true, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭 - }), - ); - - plugins.push( - // https://github.com/unplugin/unplugin-vue-markdown - Markdown({ - headEnabled: true, - }), - - cloudflare(), - ); - - plugins.push( - // https://github.com/antfu/unocss - // see uno.config.ts for config - UnoCSS(), - ); - - plugins.push( - // https://github.com/antfu/unplugin-auto-import - AutoImport({ - dirs: [ - // 'src/composables', - // 'src/utils', - 'src/stores', - ], - imports: [ - 'vue', - 'vue-i18n', - 'pinia', - '@vueuse/core', - VueRouterAutoImports, - createUtils4uAutoImports([]), - { - 'consola/browser': ['consola'], - 'vue-router/auto': ['useLink'], - 'naive-ui': ['useModal', 'useDialog', 'useMessage', 'useNotification', 'useLoadingBar'], - }, - ], - vueTemplate: true, - }), - - // https://github.com/antfu/unplugin-vue-components - Components({ - // __开头的 - excludeNames: [/^__/], - // allow auto load markdown components under `./src/components/` - extensions: ['vue', 'md'], - // allow auto import and register components used in markdown - include: [/\.vue$/, /\.vue\?vue/, /\.md$/], - resolvers: [ - AntDesignVueResolver({ - importStyle: false, // css in js - resolveIcons: true, - }), - IconsResolver({ - customCollections: ['svg'], - prefix: 'icon' /* or */, - }), // https://github.com/unplugin/unplugin-icons?tab=readme-ov-file#auto-importing - TDesignResolver({ esm: true, library: 'mobile-vue' }), - VantResolver({ importStyle: true }), - PrimeVueResolver(/* { components: { prefix: 'P' } } */), - NaiveUiResolver(), - ], - }), - - Icons({ - autoInstall: true, - customCollections: { - svg: FileSystemIconLoader('src/assets/icons/svgs', (svg) => { - return svg.replace(/^> `, src); - // console.debug(`typeof src :>> `, typeof src); - // return src as string; - // }, - }), - ); - - if (mode !== 'test') { - plugins.push( - // https://github.com/condorheroblog/vite-plugin-fake-server?tab=readme-ov-file#usage - vitePluginFakeServer({ - basename: 'fake-api', - enableProd: !true, - include: 'fake', - }), - ); - } - - if (env.VITE_ENABLE_VUE_DEVTOOLS === 'true') { - plugins.push(vueDevTools()); - } - - plugins.push( - // https://vite-plugin-checker.netlify.app/introduction/introduction.html - checker({ - eslint: { - lintCommand: 'eslint "./src/**/*.{js,jsx,ts,tsx,vue}"', - useFlatConfig: true, - }, - vueTsc: true, - overlay: { - initialIsOpen: false, - }, - terminal: true, - enableBuild: true, - // XXX: pnpm add vls vti -D - }), - ); - - plugins.push( - // https://github.com/FatehAK/vite-plugin-image-optimizer?tab=readme-ov-file#default-configuration - ViteImageOptimizer({ - /* pass your config */ - }), - ); - - // 检查是否在VS Code终端中运行 - if (process.env.TERM_PROGRAM === 'vscode' || process.env.VSCODE_PID) { - // plugins.push( - // // 构建后自动将dist目录打包成zip文件 - // viteArchiverPlugin({ - // addTimestamp: false, // 是否添加时间戳到输出文件名 - // format: 'zip', // 输出的压缩文件格式 - // outputDir: '', // 输出目录,默认为项目根目录 - // outputFileName: 'dist', // 输出的zip文件名(不含扩展名) - // sourceDir: 'dist', // 要打包的源目录 - // }), - // ) - } - - const _unused = () => { - // plugins.push( - // // https://github.com/rsnakdmx/vite-plugin-purgecss-v5?tab=readme-ov-file#-usage - // pluginPurgeCss({ - // variables: true, - // }), - // viteSingleFile(), - // viteStaticCopy({ - // targets: [ - // // globalThis.CESIUM_BASE_URL = 'https://digitalarsenal.io/'; - // { dest: cesiumBaseUrl, src: `${cesiumSource}/ThirdParty` }, - // { dest: cesiumBaseUrl, src: `${cesiumSource}/Workers` }, - // { dest: cesiumBaseUrl, src: `${cesiumSource}/Assets` }, - // { dest: cesiumBaseUrl, src: `${cesiumSource}/Widgets` }, - // ], - // }), - // ) - plugins.push( - // https://github.com/feat-agency/vite-plugin-webfont-dl?tab=readme-ov-file#-usage-simple-config-method-b- - ViteWebfontDownload([ - 'https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap', - 'https://fonts.googleapis.com/css2?family=Fira+Code&display=swap', - 'https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600,700,900', - ]), - ); - }; - - plugins.push(IndexHtmlPlugin()); - - return plugins; -} diff --git a/vite.config.ts b/vite.config.ts index ceac503..e5e8054 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,12 +1,80 @@ -import type { ManualChunkMeta, PreRenderedAsset } from 'rollup'; import { fileURLToPath, URL } from 'node:url'; +import type { ManualChunkMeta, PreRenderedAsset } from 'rollup'; import { createViteProxy } from 'utils4u/vite'; -import { defineConfig, loadEnv } from 'vite'; +import { defineConfig, loadEnv, type ConfigEnv, type PluginOption } from 'vite'; import { optimizeDeps } from './vite.config.optimizeDeps'; -import { Plugins } from './vite.config.plugins'; + +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { glob } from 'tinyglobby'; +import consola from 'consola'; + +async function loadPlugins(configEnv: ConfigEnv): Promise { + const plugins: PluginOption[] = []; + + consola.start('开始加载 Vite 插件...'); + + const pluginEntries = await glob('**/*.ts', { + absolute: true, + cwd: path.resolve(import.meta.dirname, 'vite-plugins'), + ignore: [ + '**/*.d.ts', + '**/*.disabled.ts', + '**/x-*.ts', // 禁用以 x- 开头的插件文件 + '**/_*', + ], + }); + + consola.info(`找到 ${pluginEntries.length} 个插件文件`); + + // 计算最长的文件名长度,用于对齐输出 + const maxNameLength = Math.max(...pluginEntries.map((entry) => path.basename(entry).length)); + + for (const entry of pluginEntries) { + const pluginName = path.basename(entry); + const paddedName = pluginName.padEnd(maxNameLength, ' '); + const imported = await import(pathToFileURL(entry).href); + + const loadPluginFn = imported.loadPlugin as (configEnv: ConfigEnv) => PluginOption; + let plugin: PluginOption | undefined; + let loadMethod = ''; + + // 优先使用 loadPlugin 函数(接收 configEnv 参数) + if (loadPluginFn && typeof loadPluginFn === 'function') { + const result = loadPluginFn(configEnv); + plugin = result; + loadMethod = 'loadPlugin'; + } else if (imported.default) { + plugin = imported.default; + loadMethod = 'default'; + } else { + consola.warn(`插件未导出有效内容: ${paddedName}`); + continue; // 跳过无效插件 + } + + if (plugin) { + const pluginArray = Array.isArray(plugin) ? plugin : [plugin]; + const validPlugins = pluginArray.filter(Boolean); // 过滤掉 null/undefined + const pluginCount = validPlugins.length; + + if (pluginCount > 0) { + plugins.push(...validPlugins); + consola.success(`${paddedName} → ${pluginCount} 个实例 (${loadMethod})`); + } else { + consola.warn(`${paddedName} 返回了空数组或无效值`); + } + } + } + + consola.success(`✅ 总共加载了 ${plugins.length} 个插件实例`); + + return plugins; +} // https://vite.dev/config/ -export default defineConfig(async ({ command, mode }) => { +export default defineConfig(async (configEnv) => { + const { command, mode } = configEnv; + const isBuild = command === 'build'; const env = loadEnv(mode, process.cwd()); @@ -79,9 +147,9 @@ export default defineConfig(async ({ command, mode }) => { if (packageName.includes('@juggle+resize-observer')) { return 'resize-observer'; } - if (packageName.includes('date-fns')) { - return 'date-fns'; - } + // if (packageName.includes('date-fns')) { + // return 'date-fns'; + // } if ( ['primelocale', 'primevue', '@primeuix'].some((name) => packageName!.includes(name), @@ -136,7 +204,7 @@ export default defineConfig(async ({ command, mode }) => { }, }, }, - plugins: Plugins({ mode, env }), + plugins: await loadPlugins(configEnv), resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), @@ -150,6 +218,10 @@ export default defineConfig(async ({ command, mode }) => { server: { allowedHosts: ['.NWCT.DEV'], proxy: createViteProxy(), + watch: { + // 监听 vite-plugins 目录的变化,触发配置文件重新加载 + ignored: ['!**/vite-plugins/**'], + }, }, optimizeDeps: optimizeDeps(), };