diff --git a/packages/uni-app-vite/src/plugin/configResolved.ts b/packages/uni-app-vite/src/plugin/configResolved.ts index 77af6b825f4db0d56a8baf8eb858b1e877561d6b..27be5d07743119eb3e0dc2c631d9e8d3372459a7 100644 --- a/packages/uni-app-vite/src/plugin/configResolved.ts +++ b/packages/uni-app-vite/src/plugin/configResolved.ts @@ -3,7 +3,6 @@ import path from 'path' import { Plugin } from 'vite' import { - removePlugins, injectAssetPlugin, injectCssPlugin, injectCssPostPlugin, @@ -24,7 +23,6 @@ function normalizeCssChunkFilename(id: string) { export const configResolved: Plugin['configResolved'] = (config) => { const inputDir = process.env.UNI_INPUT_DIR const mainPath = resolveMainPathOnce(inputDir) - removePlugins('vite:import-analysis', config) injectCssPlugin(config) injectCssPostPlugin(config, { chunkCssFilename(id: string) { diff --git a/packages/uni-cli-shared/src/vite/utils/plugin.ts b/packages/uni-cli-shared/src/vite/utils/plugin.ts index cfc487db1d26d68da96a9a5113c9f082004ff2de..2d45751ae7dbe06237af8f1cbb95e237cde4d981 100644 --- a/packages/uni-cli-shared/src/vite/utils/plugin.ts +++ b/packages/uni-cli-shared/src/vite/utils/plugin.ts @@ -1,4 +1,5 @@ import type { Plugin, ResolvedConfig } from 'vite' +import { extend } from '@vue/shared' import { assetPlugin } from '../plugins/vitejs/plugins/asset' import { cssPlugin, cssPostPlugin } from '../plugins/vitejs/plugins/css' @@ -28,10 +29,17 @@ export function injectCssPostPlugin( chunkCssCode: (filename: string, cssCode: string) => string } ) { - replacePlugins( - [cssPostPlugin(config, { chunkCssFilename, chunkCssCode })], - config + const newCssPostPlugin = cssPostPlugin(config, { + chunkCssFilename, + chunkCssCode, + }) + const oldCssPostPlugin = config.plugins.find( + (p) => p.name === newCssPostPlugin.name ) + // 直接覆盖原有方法,不能删除,替换,因为 unocss 在 pre 阶段已经获取到了旧的 css-post 插件对象 + if (oldCssPostPlugin) { + extend(oldCssPostPlugin, newCssPostPlugin) + } } export function replacePlugins(plugins: Plugin[], config: ResolvedConfig) { diff --git a/packages/uni-mp-vite/src/plugin/configResolved.ts b/packages/uni-mp-vite/src/plugin/configResolved.ts index abc5485d0dfd7d9fef8809193897434d86d3b2d2..ae36cf034202a8935c3536b0672dc5114ca50c91 100644 --- a/packages/uni-mp-vite/src/plugin/configResolved.ts +++ b/packages/uni-mp-vite/src/plugin/configResolved.ts @@ -1,7 +1,7 @@ import debug from 'debug' -import { Plugin } from 'vite' +import type { Plugin, ResolvedConfig } from 'vite' +import type { EmittedAsset } from 'rollup' import { - removePlugins, injectAssetPlugin, injectCssPlugin, injectCssPostPlugin, @@ -43,24 +43,31 @@ export function createConfigResolved({ } return (config) => { const mainPath = resolveMainPathOnce(process.env.UNI_INPUT_DIR) - removePlugins('vite:import-analysis', config) + fixUnocss(config) injectCssPlugin(config) + + const unocssGlobalBuildGenerateIndex = config.plugins.findIndex( + (p) => p.name === 'unocss:global:build:generate' + ) + const hasUnocssGlobalBuildGenerate = unocssGlobalBuildGenerateIndex > -1 + // unocss 是根据 .css 后缀来编译文件,需要先保持 css 文件后缀为 .css,等 unocss 处理完后,再重置回正确的文件后缀 + const cssExtname = hasUnocssGlobalBuildGenerate ? '.css' : extname injectCssPostPlugin(config, { chunkCssFilename(id: string) { if (id === mainPath) { - return 'app' + extname + return 'app' + cssExtname } else if (isUniPageUrl(id)) { - return normalizeCssChunkFilename(parseVirtualPagePath(id), extname) + return normalizeCssChunkFilename(parseVirtualPagePath(id), cssExtname) } else if (isUniComponentUrl(id)) { return normalizeCssChunkFilename( parseVirtualComponentPath(id), - extname + cssExtname ) } }, chunkCssCode(filename, cssCode) { cssCode = transformScopedCss(cssCode) - if (filename === 'app' + extname) { + if (filename === 'app' + cssExtname) { const componentCustomHiddenCss = (component && component.vShow && @@ -94,5 +101,44 @@ export function createConfigResolved({ }, }) injectAssetPlugin(config) + + if (hasUnocssGlobalBuildGenerate && extname !== '.css') { + ;(config.plugins as Plugin[]).splice( + unocssGlobalBuildGenerateIndex + 1, + 0, + adjustCssExtname(extname) + ) + } + } +} + +function adjustCssExtname(extname: string): Plugin { + return { + name: 'vite:uni-adjust-css-extname', + generateBundle(_, bundle) { + const files = Object.keys(bundle) + files.forEach((name) => { + if (name.endsWith('.css')) { + const asset = bundle[name] as EmittedAsset + this.emitFile({ + fileName: name.replace('.css', extname), + type: 'asset', + source: asset.source, + }) + delete bundle[name] + } + }) + }, + } +} +function fixUnocss(config: ResolvedConfig) { + const unocssGlobalBuildScan = config.plugins.find( + (p) => p.name === 'unocss:global:build:scan' + ) + // TODO 原始的 scan 的 buildStart 会清空 vfsLayerMap,导致 watch 时,load 阶段 /__uno.css 获取不到 + // https://github.com/antfu/unocss/blob/main/packages/vite/src/modes/global/build.ts#L25 + if (unocssGlobalBuildScan) { + // 隐患: task 未被清空 + unocssGlobalBuildScan.buildStart = () => {} } }