From b7168c4e1f7caca3fd1280b1a8884d500aaebb18 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Mon, 24 Jan 2022 20:51:06 +0800 Subject: [PATCH] wip(app): nvue styler --- packages/uni-app-vite/package.json | 4 +- .../uni-app-vite/src/nvue/plugin/index.ts | 57 +++++++---- .../uni-app-vite/src/nvue/plugins/esbuild.ts | 12 +-- .../uni-app-vite/src/plugin/configResolved.ts | 11 ++- packages/uni-app-vite/src/vue/plugin/index.ts | 41 ++++---- packages/uni-cli-shared/src/vite/index.ts | 7 +- .../uni-cli-shared/src/vite/plugins/index.ts | 4 + .../src/vite/plugins/vitejs/plugins/css.ts | 2 +- .../uni-cli-shared/src/vite/utils/plugin.ts | 17 +--- .../uni-mp-vite/src/plugin/configResolved.ts | 95 ++++++++++--------- packages/vite-plugin-uni/src/utils/plugin.ts | 6 ++ packages/vite-plugin-uni/src/vue/options.ts | 5 + pnpm-lock.yaml | 4 + 13 files changed, 156 insertions(+), 109 deletions(-) diff --git a/packages/uni-app-vite/package.json b/packages/uni-app-vite/package.json index 0bb66e8f8..4db324e37 100644 --- a/packages/uni-app-vite/package.json +++ b/packages/uni-app-vite/package.json @@ -28,12 +28,14 @@ "@vue/compiler-sfc": "3.2.27", "debug": "^4.3.2", "fs-extra": "^10.0.0", + "picocolors": "^1.0.0", "rollup": "^2.59.0" }, "devDependencies": { "@types/debug": "^4.1.7", "@types/fs-extra": "^9.0.13", "@vue/compiler-core": "3.2.27", - "esbuild": "^0.13.12" + "esbuild": "^0.13.12", + "postcss": "^8.4.5" } } diff --git a/packages/uni-app-vite/src/nvue/plugin/index.ts b/packages/uni-app-vite/src/nvue/plugin/index.ts index 05b552d25..04231530a 100644 --- a/packages/uni-app-vite/src/nvue/plugin/index.ts +++ b/packages/uni-app-vite/src/nvue/plugin/index.ts @@ -1,10 +1,13 @@ import type { PreRenderedChunk } from 'rollup' import type { Plugin } from 'vite' import path from 'path' +import colors from 'picocolors' import { + commonjsProxyRE, createTransformTag, + cssLangRE, dynamicImportPolyfill, - isUniPageSfcFile, + generateCodeFrame, normalizePath, parseVueRequest, removeExt, @@ -17,6 +20,7 @@ import { transformAppendAsTree } from './transforms/transformAppendAsTree' import { transformVideo } from './transforms/transformVideo' import { transformText } from './transforms/transformText' import { createConfigResolved } from '../../plugin/configResolved' + const uTags = { text: 'u-text', image: 'u-image', @@ -41,9 +45,6 @@ export function initNVueNodeTransforms() { export function uniAppNVuePlugin(): Plugin { const inputDir = process.env.UNI_INPUT_DIR const mainPath = resolveMainPathOnce(inputDir) - function normalizeCssChunkFilename(id: string) { - return removeExt(normalizePath(path.relative(inputDir, id))) + '.css.js' - } return { name: 'uni:app-nvue', config() { @@ -77,22 +78,42 @@ export function uniAppNVuePlugin(): Plugin { } }, configResolved: createConfigResolved({ - chunkCssFilename(id: string) { - if (id === mainPath) { - return 'app.css.js' - } else if (isUniPageSfcFile(id, inputDir)) { - return normalizeCssChunkFilename(id) + createCssPostPlugin(config) { + return { + name: 'vite:css-post', + buildStart() { + // 用于覆盖原始插件方法 + // noop + }, + async transform(source, filename) { + if (!cssLangRE.test(filename) || commonjsProxyRE.test(filename)) { + return + } + const { code, messages } = await parse(source, { + filename, + descendant: false, + logLevel: 'WARNING', + }) + messages.forEach((message) => { + if (message.type === 'warning') { + let msg = `[vite:css] ${message.text}` + if (message.line && message.column) { + msg += `\n${generateCodeFrame(source, { + line: message.line, + column: message.column, + })}` + } + config.logger.warn(colors.yellow(msg)) + } + }) + return { code: `export default ${code}`, map: { mappings: '' } } + }, + generateBundle() { + // 用于覆盖原始插件方法 + // noop + }, } }, - async chunkCssCode(filename, cssCode) { - const { code, messages } = await parse(cssCode, { filename }) - messages.forEach((msg) => { - if (msg.type === 'warning' || msg.type === 'error') { - console.warn(msg.text) - } - }) - return `export default ${code}` - }, }), } } diff --git a/packages/uni-app-vite/src/nvue/plugins/esbuild.ts b/packages/uni-app-vite/src/nvue/plugins/esbuild.ts index 402010e68..71e08f2ed 100644 --- a/packages/uni-app-vite/src/nvue/plugins/esbuild.ts +++ b/packages/uni-app-vite/src/nvue/plugins/esbuild.ts @@ -38,11 +38,13 @@ export function uniEsbuildPlugin(): Plugin { } }) debugEsbuild('start', entryPoints.length, entryPoints) - for (const filename of entryPoints) { - await buildNVuePage(filename, buildOptions).then((code) => { - return fs.outputFile(path.resolve(outputDir, filename), code) + await Promise.all( + entryPoints.map((filename) => { + return buildNVuePage(filename, buildOptions).then((code) => { + return fs.outputFile(path.resolve(outputDir, filename), code) + }) }) - } + ) debugEsbuild('end') }, } @@ -51,8 +53,6 @@ export function uniEsbuildPlugin(): Plugin { function buildNVuePage(filename: string, options: BuildOptions) { return transformWithEsbuild( `import NVuePageComponent from './${filename}' -import NVuePageComponentStyle from './${filename.replace('.js', '.css')}' -NVuePageComponent.__stylesheet = NVuePageComponentStyle Vue.createApp(NVuePageComponent).mount('#root')`, path.join(nvueOutDir(), 'main.js'), options diff --git a/packages/uni-app-vite/src/plugin/configResolved.ts b/packages/uni-app-vite/src/plugin/configResolved.ts index 7d88e08e4..37438df9a 100644 --- a/packages/uni-app-vite/src/plugin/configResolved.ts +++ b/packages/uni-app-vite/src/plugin/configResolved.ts @@ -1,4 +1,4 @@ -import { Plugin } from 'vite' +import { Plugin, ResolvedConfig } from 'vite' import { injectAssetPlugin, @@ -6,13 +6,14 @@ import { injectCssPostPlugin, } from '@dcloudio/uni-cli-shared' -export function createConfigResolved(options: { - chunkCssFilename: (id: string) => string | void - chunkCssCode: (filename: string, cssCode: string) => string | Promise +export function createConfigResolved({ + createCssPostPlugin, +}: { + createCssPostPlugin: (config: ResolvedConfig) => Plugin }): Plugin['configResolved'] { return (config) => { injectCssPlugin(config) - injectCssPostPlugin(config, options) + injectCssPostPlugin(config, createCssPostPlugin(config)) // 强制不inline config.build.assetsInlineLimit = 0 injectAssetPlugin(config) diff --git a/packages/uni-app-vite/src/vue/plugin/index.ts b/packages/uni-app-vite/src/vue/plugin/index.ts index 25b9c5d21..2fddff80a 100644 --- a/packages/uni-app-vite/src/vue/plugin/index.ts +++ b/packages/uni-app-vite/src/vue/plugin/index.ts @@ -2,6 +2,7 @@ import path from 'path' import fs from 'fs-extra' import { APP_SERVICE_FILENAME, + cssPostPlugin, isUniPageSfcFile, normalizePath, parsePagesJsonOnce, @@ -42,24 +43,28 @@ export function uniAppVuePlugin(): UniVitePlugin { } }, configResolved: createConfigResolved({ - chunkCssFilename(id: string) { - if (id === mainPath) { - return 'app.css' - } else if (isUniPageSfcFile(id, inputDir)) { - return normalizeCssChunkFilename(id) - } - }, - chunkCssCode(filename, cssCode) { - if (filename === 'app.css') { - if (!appCss) { - appCss = fs.readFileSync( - require.resolve('@dcloudio/uni-app-plus/dist/style.css'), - 'utf8' - ) - } - return appCss + '\n' + cssCode - } - return cssCode + createCssPostPlugin(config) { + return cssPostPlugin(config, { + chunkCssFilename(id: string) { + if (id === mainPath) { + return 'app.css' + } else if (isUniPageSfcFile(id, inputDir)) { + return normalizeCssChunkFilename(id) + } + }, + chunkCssCode(filename, cssCode) { + if (filename === 'app.css') { + if (!appCss) { + appCss = fs.readFileSync( + require.resolve('@dcloudio/uni-app-plus/dist/style.css'), + 'utf8' + ) + } + return appCss + '\n' + cssCode + } + return cssCode + }, + }) }, }), generateBundle(_, bundle) { diff --git a/packages/uni-cli-shared/src/vite/index.ts b/packages/uni-cli-shared/src/vite/index.ts index 8d8497fbd..e15d26fae 100644 --- a/packages/uni-cli-shared/src/vite/index.ts +++ b/packages/uni-cli-shared/src/vite/index.ts @@ -1,7 +1,11 @@ import type { Plugin } from 'vite' import type { EmittedAsset } from 'rollup' import type { ParserOptions } from '@vue/compiler-core' -import type { CompilerOptions, TemplateCompiler } from '@vue/compiler-sfc' +import type { + CompilerOptions, + SFCStyleCompileOptions, + TemplateCompiler, +} from '@vue/compiler-sfc' import { UniViteCopyPluginOptions } from './plugins/copy' export const cssTarget = 'chrome53' @@ -15,6 +19,7 @@ export interface CopyOptions { interface UniVitePluginUniOptions { compiler?: TemplateCompiler + styleOptions?: Pick compilerOptions?: { miniProgram?: { emitFile?: (emittedFile: EmittedAsset) => string diff --git a/packages/uni-cli-shared/src/vite/plugins/index.ts b/packages/uni-cli-shared/src/vite/plugins/index.ts index 4c866c065..d3be4caa9 100644 --- a/packages/uni-cli-shared/src/vite/plugins/index.ts +++ b/packages/uni-cli-shared/src/vite/plugins/index.ts @@ -12,4 +12,8 @@ export { cssPlugin, cssPostPlugin, minifyCSS, + cssLangRE, + commonjsProxyRE, } from './vitejs/plugins/css' + +export { generateCodeFrame } from './vitejs/utils' diff --git a/packages/uni-cli-shared/src/vite/plugins/vitejs/plugins/css.ts b/packages/uni-cli-shared/src/vite/plugins/vitejs/plugins/css.ts index 64916459d..56718d94d 100644 --- a/packages/uni-cli-shared/src/vite/plugins/vitejs/plugins/css.ts +++ b/packages/uni-cli-shared/src/vite/plugins/vitejs/plugins/css.ts @@ -71,7 +71,7 @@ const cssLangs = `\\.(css|less|sass|scss|styl|stylus|pcss|postcss)($|\\?)` export const cssLangRE = new RegExp(cssLangs) const cssModuleRE = new RegExp(`\\.module${cssLangs}`) const directRequestRE = /(\?|&)direct\b/ -const commonjsProxyRE = /\?commonjs-proxy/ +export const commonjsProxyRE = /\?commonjs-proxy/ const enum PreprocessLang { less = 'less', diff --git a/packages/uni-cli-shared/src/vite/utils/plugin.ts b/packages/uni-cli-shared/src/vite/utils/plugin.ts index cca2c2428..645cee7ca 100644 --- a/packages/uni-cli-shared/src/vite/utils/plugin.ts +++ b/packages/uni-cli-shared/src/vite/utils/plugin.ts @@ -1,7 +1,7 @@ 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' +import { cssPlugin } from '../plugins/vitejs/plugins/css' export type CreateUniViteFilterPlugin = ( opts: UniViteFilterPluginOptions @@ -21,21 +21,8 @@ export function injectCssPlugin(config: ResolvedConfig) { export function injectCssPostPlugin( config: ResolvedConfig, - { - chunkCssFilename, - chunkCssCode, - }: { - chunkCssFilename: (id: string) => string | void - chunkCssCode: ( - filename: string, - cssCode: string - ) => string | Promise - } + newCssPostPlugin: Plugin ) { - const newCssPostPlugin = cssPostPlugin(config, { - chunkCssFilename, - chunkCssCode, - }) const oldCssPostPlugin = config.plugins.find( (p) => p.name === newCssPostPlugin.name ) diff --git a/packages/uni-mp-vite/src/plugin/configResolved.ts b/packages/uni-mp-vite/src/plugin/configResolved.ts index cf055febf..9d5ca4ea0 100644 --- a/packages/uni-mp-vite/src/plugin/configResolved.ts +++ b/packages/uni-mp-vite/src/plugin/configResolved.ts @@ -11,6 +11,7 @@ import { transformScopedCss, normalizeMiniProgramFilename, relativeFile, + cssPostPlugin, } from '@dcloudio/uni-cli-shared' import { UniMiniProgramPluginOptions } from '.' import { getNVueCssPaths } from '../plugins/pagesJson' @@ -52,54 +53,60 @@ export function createConfigResolved({ const hasUnocssGlobalBuildGenerate = unocssGlobalBuildGenerateIndex > -1 // unocss 是根据 .css 后缀来编译文件,需要先保持 css 文件后缀为 .css,等 unocss 处理完后,再重置回正确的文件后缀 const cssExtname = hasUnocssGlobalBuildGenerate ? '.css' : extname - injectCssPostPlugin(config, { - chunkCssFilename(id: string) { - if (id === mainPath) { - return 'app' + cssExtname - } else if (isUniPageUrl(id)) { - return normalizeCssChunkFilename(parseVirtualPagePath(id), cssExtname) - } else if (isUniComponentUrl(id)) { - return normalizeCssChunkFilename( - parseVirtualComponentPath(id), - cssExtname - ) - } - }, - chunkCssCode(filename, cssCode) { - cssCode = transformScopedCss(cssCode) - if (filename === 'app' + cssExtname) { - const componentCustomHiddenCss = - (component && - component.vShow && - genComponentCustomHiddenCss(component.vShow)) || - '' - if (config.isProduction) { - return ( - cssCode + - genShadowCss(`https://cdn${cdn || ''}.dcloud.net.cn`) + - cssVars + - componentCustomHiddenCss + injectCssPostPlugin( + config, + cssPostPlugin(config, { + chunkCssFilename(id: string) { + if (id === mainPath) { + return 'app' + cssExtname + } else if (isUniPageUrl(id)) { + return normalizeCssChunkFilename( + parseVirtualPagePath(id), + cssExtname + ) + } else if (isUniComponentUrl(id)) { + return normalizeCssChunkFilename( + parseVirtualComponentPath(id), + cssExtname ) - } else { - return cssCode + cssVars + componentCustomHiddenCss } - } + }, + chunkCssCode(filename, cssCode) { + cssCode = transformScopedCss(cssCode) + if (filename === 'app' + cssExtname) { + const componentCustomHiddenCss = + (component && + component.vShow && + genComponentCustomHiddenCss(component.vShow)) || + '' + if (config.isProduction) { + return ( + cssCode + + genShadowCss(`https://cdn${cdn || ''}.dcloud.net.cn`) + + cssVars + + componentCustomHiddenCss + ) + } else { + return cssCode + cssVars + componentCustomHiddenCss + } + } - const nvueCssPaths = getNVueCssPaths(config) - if (!nvueCssPaths || !nvueCssPaths.length) { + const nvueCssPaths = getNVueCssPaths(config) + if (!nvueCssPaths || !nvueCssPaths.length) { + return cssCode + } + const normalized = normalizePath(filename) + if (nvueCssPaths.find((pageCssPath) => pageCssPath === normalized)) { + debugNVueCss(normalized) + return ( + `@import "${relativeFile(normalized, 'nvue' + extname)}";\n` + + cssCode + ) + } return cssCode - } - const normalized = normalizePath(filename) - if (nvueCssPaths.find((pageCssPath) => pageCssPath === normalized)) { - debugNVueCss(normalized) - return ( - `@import "${relativeFile(normalized, 'nvue' + extname)}";\n` + - cssCode - ) - } - return cssCode - }, - }) + }, + }) + ) injectAssetPlugin(config) if (hasUnocssGlobalBuildGenerate && extname !== '.css') { diff --git a/packages/vite-plugin-uni/src/utils/plugin.ts b/packages/vite-plugin-uni/src/utils/plugin.ts index c51b24339..7d4daca2f 100644 --- a/packages/vite-plugin-uni/src/utils/plugin.ts +++ b/packages/vite-plugin-uni/src/utils/plugin.ts @@ -26,6 +26,7 @@ export function initPluginUniOptions(UniVitePlugins: UniVitePlugin[]) { const transformEvent: Record = Object.create(null) const compilerOptions: Required['uni']['compilerOptions'] = {} const jsxOptions: Required['uni']['jsxOptions'] = {} + const styleOptions: Required['uni']['styleOptions'] = {} let compiler: TemplateCompiler | undefined UniVitePlugins.forEach((plugin) => { const { @@ -33,6 +34,7 @@ export function initPluginUniOptions(UniVitePlugins: UniVitePlugin[]) { copyOptions: pluginCopyOptions, compilerOptions: pluginCompilerOptions, jsxOptions: pluginJsxOptions, + styleOptions: pluginStyleOpitons, } = plugin.uni || {} if (pluginTemplateCompiler) { compiler = pluginTemplateCompiler @@ -43,6 +45,9 @@ export function initPluginUniOptions(UniVitePlugins: UniVitePlugin[]) { if (pluginJsxOptions) { extend(jsxOptions, pluginJsxOptions) } + if (pluginStyleOpitons) { + extend(styleOptions, pluginStyleOpitons) + } if (pluginCopyOptions) { let copyOptions = pluginCopyOptions as CopyOptions if (isFunction(pluginCopyOptions)) { @@ -65,6 +70,7 @@ export function initPluginUniOptions(UniVitePlugins: UniVitePlugin[]) { transformEvent, compilerOptions, jsxOptions, + styleOptions, } } diff --git a/packages/vite-plugin-uni/src/vue/options.ts b/packages/vite-plugin-uni/src/vue/options.ts index 5419e505e..b4508fe9b 100644 --- a/packages/vite-plugin-uni/src/vue/options.ts +++ b/packages/vite-plugin-uni/src/vue/options.ts @@ -46,6 +46,7 @@ export function initPluginVueOptions( const { compiler, + styleOptions: { postcssPlugins }, compilerOptions: { miniProgram, isNativeTag, @@ -55,6 +56,10 @@ export function initPluginVueOptions( }, } = uniPluginOptions + if (postcssPlugins) { + styleOptions.postcssPlugins.push(...postcssPlugins) + } + if (compiler) { templateOptions.compiler = compiler } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5bfa2ea6c..ddd7035ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -211,6 +211,8 @@ importers: debug: ^4.3.2 esbuild: ^0.13.12 fs-extra: ^10.0.0 + picocolors: ^1.0.0 + postcss: ^8.4.5 rollup: ^2.59.0 dependencies: '@dcloudio/uni-cli-shared': link:../uni-cli-shared @@ -222,12 +224,14 @@ importers: '@vue/compiler-sfc': 3.2.27 debug: 4.3.3 fs-extra: 10.0.0 + picocolors: 1.0.0 rollup: 2.60.2 devDependencies: '@types/debug': 4.1.7 '@types/fs-extra': 9.0.13 '@vue/compiler-core': 3.2.27 esbuild: 0.13.15 + postcss: 8.4.5 packages/uni-app-vue: specifiers: {} -- GitLab