提交 b7168c4e 编写于 作者: fxy060608's avatar fxy060608

wip(app): nvue styler

上级 a0618b9e
......@@ -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"
}
}
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}`
},
}),
}
}
......
......@@ -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
......
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<string>
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)
......
......@@ -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) {
......
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<SFCStyleCompileOptions, 'postcssPlugins'>
compilerOptions?: {
miniProgram?: {
emitFile?: (emittedFile: EmittedAsset) => string
......
......@@ -12,4 +12,8 @@ export {
cssPlugin,
cssPostPlugin,
minifyCSS,
cssLangRE,
commonjsProxyRE,
} from './vitejs/plugins/css'
export { generateCodeFrame } from './vitejs/utils'
......@@ -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',
......
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<string>
}
newCssPostPlugin: Plugin
) {
const newCssPostPlugin = cssPostPlugin(config, {
chunkCssFilename,
chunkCssCode,
})
const oldCssPostPlugin = config.plugins.find(
(p) => p.name === newCssPostPlugin.name
)
......
......@@ -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') {
......
......@@ -26,6 +26,7 @@ export function initPluginUniOptions(UniVitePlugins: UniVitePlugin[]) {
const transformEvent: Record<string, string> = Object.create(null)
const compilerOptions: Required<UniVitePlugin>['uni']['compilerOptions'] = {}
const jsxOptions: Required<UniVitePlugin>['uni']['jsxOptions'] = {}
const styleOptions: Required<UniVitePlugin>['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,
}
}
......
......@@ -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
}
......
......@@ -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: {}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册