From 0c45e2289f2a22c249920fd2a5bd04fa49628f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E6=B5=A9?= Date: Sun, 26 Oct 2025 01:01:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor(vite):=20=E6=8F=90=E5=8F=96=20rollup?= =?UTF-8?q?=20=E9=85=8D=E7=BD=AE=E5=88=B0=E7=8B=AC=E7=AB=8B=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite.config.rollup.output.ts | 102 +++++++++++++++++++++++++++++++++++ vite.config.ts | 94 +------------------------------- 2 files changed, 104 insertions(+), 92 deletions(-) create mode 100644 vite.config.rollup.output.ts diff --git a/vite.config.rollup.output.ts b/vite.config.rollup.output.ts new file mode 100644 index 0000000..c9f9f13 --- /dev/null +++ b/vite.config.rollup.output.ts @@ -0,0 +1,102 @@ +import type { ManualChunkMeta, PreRenderedAsset, RollupOptions } from 'rollup'; + +import path from 'node:path'; + +// https://www.npmjs.com/package/utils4u/v/2.19.2?activeTab=code + +export const viteConfigRollupOptions: RollupOptions = { + /* onwarn: (warning, warn) => { + if (warning.code === 'EMPTY_BUNDLE') return; + if (warning.code === 'EVAL' && warning.id?.includes('node_modules/eruda')) return; + if (warning.code === 'EVAL' && warning.id?.includes('node_modules/mockjs')) return; + if (warning.code === 'EVAL' && warning.id?.includes('node_modules/protobufjs')) return; + warn(warning); + }, */ + + output: { + // Keep hashed file names predictable across entry, chunk, and asset outputs. + entryFileNames: 'entry/[name].[hash].js', // 默认: "[name].js" + chunkFileNames: 'chunk/[name].[hash].js', // 默认: "[name]-[hash].js" + // assetFileNames:'', // 默认: "assets/[name]-[hash][extname]" + // https://cn.rollupjs.org/configuration-options/#output-assetfilenames + assetFileNames(chunkInfo: PreRenderedAsset) { + const names = chunkInfo.names; + + if (names.length !== 1) { + console.error('Multiple names for asset:', chunkInfo); + process.exit(1); + } + + const assetName = names[0]; + const ext = assetName.split('.').pop()?.toLowerCase(); + if (ext && /png|jpe?g|gif|svg|webp|avif/.test(ext)) { + return 'chunks/images/[name].[hash][extname]'; + } + if (ext && /woff2?|ttf|otf/.test(ext)) { + return 'chunks/fonts/[name].[hash][extname]'; + } + if (ext === 'css') { + return 'chunks/css/[name].[hash][extname]'; + } + return '_chunks/[name].[hash][extname]'; + }, + + manualChunks: (id: string, _meta: ManualChunkMeta) => { + /* 有一个问题: dynamic import will not move module into another chunk. + if (['/src/layouts'].some((prefix) => id.includes(prefix))) { + return 'layouts'; + } + */ + + if (id.includes('index.page.vue')) { + const parentDir = path.basename(path.dirname(id)); + return `${parentDir}-index.page`; + } + + if (!id.includes('node_modules')) return; + // 处理 pnpm 的特殊路径结构 + let packageName; + if (id.includes('.pnpm')) { + // pnpm 路径: .pnpm/naive-ui@2.43.1_vue@3.5.22/node_modules/naive-ui/... + const pnpmMatch = id.match(/\.pnpm\/(.+?)@/); + if (pnpmMatch) { + packageName = pnpmMatch[1]; + } + } else { + // 普通路径: node_modules/lodash/... + const normalMatch = id.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)\//); + if (normalMatch) { + packageName = normalMatch[1]; + } + } + + if (packageName) { + if (['highlight.js'].includes(packageName)) { + return 'lib-hljs'; + } + + // 根据包名分组 + if (['consola', 'lodash', '@juggle+resize-observer', 'vueuc'].includes(packageName)) { + return 'lib-vendor'; + } + + if (['naive-ui'].includes(packageName) && id.includes('_internal')) { + console.debug(`id :>> `, id); + return 'lib-naive-ui-internal'; + } + + if (['naive-ui'].includes(packageName)) { + return 'lib-naive-ui'; + } + + if (['primelocale', 'primevue', '@primeuix'].some((name) => packageName!.includes(name))) { + return 'lib-primevue'; + } + + if (['vue', 'vue-router', 'pinia', 'vue-demi', 'vue-i18n'].includes(packageName)) { + return 'lib-vue-vendor'; + } + } + }, + }, +}; diff --git a/vite.config.ts b/vite.config.ts index eebb43a..facb95f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,11 @@ import consola from 'consola'; import path from 'node:path'; import { fileURLToPath, pathToFileURL, URL } from 'node:url'; -import type { ManualChunkMeta, PreRenderedAsset } from 'rollup'; import { glob } from 'tinyglobby'; import { createViteProxy } from 'utils4u/vite'; import { defineConfig, loadEnv, type ConfigEnv, type PluginOption } from 'vite'; import { optimizeDeps } from './vite.config.optimizeDeps'; +import { viteConfigRollupOptions } from './vite.config.rollup.output'; type LoadPluginFunction = (configEnv: ConfigEnv) => PluginOption; async function loadPlugins(configEnv: ConfigEnv): Promise { @@ -82,97 +82,7 @@ export default defineConfig(async (configEnv) => { minify: env.VITE_APP_BUILD_MINIFY === 'true' ? undefined /* 即默认 */ : false, // 默认: 'terser' sourcemap: env.VITE_APP_BUILD_SOURCE_MAP === 'true', - rollupOptions: { - /* onwarn: (warning, warn) => { - if (warning.code === 'EMPTY_BUNDLE') return; - if (warning.code === 'EVAL' && warning.id?.includes('node_modules/eruda')) return; - if (warning.code === 'EVAL' && warning.id?.includes('node_modules/mockjs')) return; - if (warning.code === 'EVAL' && warning.id?.includes('node_modules/protobufjs')) return; - warn(warning); - }, */ - - output: { - // Keep hashed file names predictable across entry, chunk, and asset outputs. - entryFileNames: 'entry/[name].[hash].js', // 默认: "[name].js" - chunkFileNames: 'chunk/[name].[hash].js', // 默认: "[name]-[hash].js" - // assetFileNames:'', // 默认: "assets/[name]-[hash][extname]" - // https://cn.rollupjs.org/configuration-options/#output-assetfilenames - assetFileNames(chunkInfo: PreRenderedAsset) { - const names = chunkInfo.names; - - if (names.length !== 1) { - console.error('Multiple names for asset:', chunkInfo); - process.exit(1); - } - - const assetName = names[0]; - const ext = assetName.split('.').pop()?.toLowerCase(); - if (ext && /png|jpe?g|gif|svg|webp|avif/.test(ext)) { - return 'chunks/images/[name].[hash][extname]'; - } - if (ext && /woff2?|ttf|otf/.test(ext)) { - return 'chunks/fonts/[name].[hash][extname]'; - } - if (ext === 'css') { - return 'chunks/css/[name].[hash][extname]'; - } - return '_chunks/[name].[hash][extname]'; - }, - - // https://www.npmjs.com/package/utils4u/v/2.19.2?activeTab=code - manualChunks: (id: string, _meta: ManualChunkMeta) => { - /* 有一个问题: dynamic import will not move module into another chunk. - if (['/src/layouts'].some((prefix) => id.includes(prefix))) { - return 'layouts'; - } - */ - - if (id.includes('index.page.vue')) { - const parentDir = path.basename(path.dirname(id)); - return `${parentDir}-index.page`; - } - - if (!id.includes('node_modules')) return; - // 处理 pnpm 的特殊路径结构 - let packageName; - if (id.includes('.pnpm')) { - // pnpm 路径: .pnpm/naive-ui@2.43.1_vue@3.5.22/node_modules/naive-ui/... - const pnpmMatch = id.match(/\.pnpm\/(.+?)@/); - if (pnpmMatch) { - packageName = pnpmMatch[1]; - } - } else { - // 普通路径: node_modules/lodash/... - const normalMatch = id.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)\//); - if (normalMatch) { - packageName = normalMatch[1]; - } - } - - if (packageName) { - if (['highlight.js'].includes(packageName)) { - return 'lib-hljs'; - } - - // 根据包名分组 - if (['consola', 'lodash', '@juggle+resize-observer'].includes(packageName)) { - return 'lib-vendor'; - } - if (['naive-ui', 'vueuc'].includes(packageName)) { - return 'lib-naive-ui'; - } - if ( - ['primelocale', 'primevue', '@primeuix'].some((name) => packageName!.includes(name)) - ) { - return 'lib-primevue'; - } - if (['vue', 'vue-router', 'pinia', 'vue-demi', 'vue-i18n'].includes(packageName)) { - return 'lib-vue-vendor'; - } - } - }, - }, - }, + rollupOptions: viteConfigRollupOptions, }, css: { devSourcemap: true,