From 5df88a2384d0d930d61ae4e8a440190550815a58 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Mon, 14 Feb 2022 17:35:03 +0800 Subject: [PATCH] wip(app): nvue --- packages/shims-node.d.ts | 1 + packages/uni-app-vite/src/index.ts | 2 +- packages/uni-app-vite/src/nvue/index.ts | 7 +- .../uni-app-vite/src/nvue/plugin/index.ts | 16 ++--- .../uni-app-vite/src/nvue/plugins/esbuild.ts | 48 ++++++++++++-- .../uni-app-vite/src/nvue/plugins/mainJs.ts | 8 ++- .../src/nvue/plugins/pagesJson.ts | 8 ++- packages/uni-app-vite/src/plugin/build.ts | 16 ++++- packages/uni-app-vite/src/plugin/index.ts | 8 ++- packages/vite-plugin-uni/src/cli/build.ts | 64 ++++++++++++------- 10 files changed, 128 insertions(+), 50 deletions(-) diff --git a/packages/shims-node.d.ts b/packages/shims-node.d.ts index 3376084fd..5e771ee01 100644 --- a/packages/shims-node.d.ts +++ b/packages/shims-node.d.ts @@ -27,5 +27,6 @@ declare namespace NodeJS { UNI_CUSTOM_CONTEXT?: string UNI_MINIMIZE?: 'true' UNI_COMPILER: 'vue' | 'nvue' + UNI_COMPILER_NVUE: 'app' | 'page' } } diff --git a/packages/uni-app-vite/src/index.ts b/packages/uni-app-vite/src/index.ts index 3c89456d3..58bd1d901 100644 --- a/packages/uni-app-vite/src/index.ts +++ b/packages/uni-app-vite/src/index.ts @@ -3,7 +3,7 @@ import { initNVuePlugins } from './nvue' import { uniAppPlugin } from './plugin' export default () => { return [ - uniAppPlugin(), + uniAppPlugin({ renderer: process.env.UNI_RENDERER }), ...(process.env.UNI_COMPILER === 'nvue' ? initNVuePlugins() : initVuePlugins()), diff --git a/packages/uni-app-vite/src/nvue/index.ts b/packages/uni-app-vite/src/nvue/index.ts index 4d5504488..2344ddeb5 100644 --- a/packages/uni-app-vite/src/nvue/index.ts +++ b/packages/uni-app-vite/src/nvue/index.ts @@ -17,16 +17,17 @@ import { uniPagesJsonPlugin } from './plugins/pagesJson' export { initNVueNodeTransforms } from './plugin' export function initNVuePlugins() { + const renderer = process.env.UNI_RENDERER return [ uniAppCssPlugin(), uniEasycomPlugin({ exclude: UNI_EASYCOM_EXCLUDE }), uniHBuilderXConsolePlugin(), - uniMainJsPlugin(), + uniMainJsPlugin({ renderer }), ...(process.env.UNI_RENDERER === 'native' ? [uniManifestJsonPlugin()] : []), - uniPagesJsonPlugin(), + uniPagesJsonPlugin({ renderer }), uniViteInjectPlugin('uni:app-inject', initAppProvide()), uniStatsPlugin(), uniAppNVuePlugin(), - uniEsbuildPlugin(), + uniEsbuildPlugin({ renderer }), ] } diff --git a/packages/uni-app-vite/src/nvue/plugin/index.ts b/packages/uni-app-vite/src/nvue/plugin/index.ts index cf27938b9..67ee6aae8 100644 --- a/packages/uni-app-vite/src/nvue/plugin/index.ts +++ b/packages/uni-app-vite/src/nvue/plugin/index.ts @@ -52,12 +52,6 @@ export function uniAppNVuePlugin(): Plugin { name: 'uni:app-nvue', config() { return { - lib: { - // 必须使用 lib 模式,否则会生成 preload 等代码 - fileName: 'main.js', - entry: mainPath, - formats: ['esm'], - }, css: { postcss: { plugins: initPostcssPlugin({ @@ -67,12 +61,15 @@ export function uniAppNVuePlugin(): Plugin { }, }, build: { + lib: { + // 必须使用 lib 模式,否则会生成 preload 等代码 + fileName: 'app', + entry: mainPath, + formats: ['es'], + }, outDir: nvueOutDir(), rollupOptions: { external, - input: { - main: mainPath, - }, output: { entryFileNames(chunk) { if (chunk.name === 'main') { @@ -80,7 +77,6 @@ export function uniAppNVuePlugin(): Plugin { } return chunk.name + '.js' }, - format: 'esm', assetFileNames: '[name][extname]', chunkFileNames: createChunkFileNames(inputDir), plugins: [dynamicImportPolyfill()], diff --git a/packages/uni-app-vite/src/nvue/plugins/esbuild.ts b/packages/uni-app-vite/src/nvue/plugins/esbuild.ts index e7b29a47d..78ea61261 100644 --- a/packages/uni-app-vite/src/nvue/plugins/esbuild.ts +++ b/packages/uni-app-vite/src/nvue/plugins/esbuild.ts @@ -5,14 +5,22 @@ import path from 'path' import fs from 'fs-extra' import debug from 'debug' -import { transformWithEsbuild } from '@dcloudio/uni-cli-shared' +import { + APP_SERVICE_FILENAME, + transformWithEsbuild, +} from '@dcloudio/uni-cli-shared' import { nvueOutDir } from '../../utils' import { esbuildGlobals } from '../utils' +import { APP_CSS_JS } from './appCss' const debugEsbuild = debug('uni:app-nvue-esbuild') -export function uniEsbuildPlugin(): Plugin { +export function uniEsbuildPlugin({ + renderer, +}: { + renderer?: 'native' +}): Plugin { let buildOptions: BuildOptions const outputDir = process.env.UNI_OUTPUT_DIR return { @@ -42,9 +50,18 @@ export function uniEsbuildPlugin(): Plugin { entryPoints.push(name) } }) + if (renderer === 'native') { + debugEsbuild('start', APP_SERVICE_FILENAME) + await buildNVueAppService(buildOptions).then((code) => { + return fs.outputFile( + path.resolve(outputDir, APP_SERVICE_FILENAME), + code + ) + }) + } debugEsbuild('start', entryPoints.length, entryPoints) for (const filename of entryPoints) { - await buildNVuePage(filename, buildOptions).then((code) => { + await buildNVuePage(renderer, filename, buildOptions).then((code) => { return fs.outputFile(path.resolve(outputDir, filename), code) }) } @@ -53,10 +70,31 @@ export function uniEsbuildPlugin(): Plugin { } } -function buildNVuePage(filename: string, options: BuildOptions) { +function buildNVueAppService(options: BuildOptions) { + return transformWithEsbuild( + `import './app.js'`, + path.join(nvueOutDir(), 'main.js'), + options + ).then((res) => { + if (res.outputFiles) { + return res.outputFiles[0].text + } + return '' + }) +} + +function buildNVuePage( + renderer: 'native' | undefined, + filename: string, + options: BuildOptions +) { return transformWithEsbuild( `import App from './${filename}' -import { AppStyles } from './app.css.js' +${ + renderer === 'native' + ? 'const AppStyles = __uniConfig.appStyles || []' + : `import { AppStyles } from '${APP_CSS_JS}'` +} const webview = plus.webview.currentWebview() const __pageId = parseInt(webview.id) const __pagePath = webview.__path__ diff --git a/packages/uni-app-vite/src/nvue/plugins/mainJs.ts b/packages/uni-app-vite/src/nvue/plugins/mainJs.ts index 8296fe5b3..62535dd5b 100644 --- a/packages/uni-app-vite/src/nvue/plugins/mainJs.ts +++ b/packages/uni-app-vite/src/nvue/plugins/mainJs.ts @@ -1,19 +1,21 @@ import { defineUniMainJsPlugin, PAGES_JSON_JS } from '@dcloudio/uni-cli-shared' import { APP_CSS_JS } from './appCss' -export function uniMainJsPlugin() { +export function uniMainJsPlugin({ renderer }: { renderer?: 'native' }) { return defineUniMainJsPlugin((opts) => { return { name: 'uni:app-nvue-main-js', enforce: 'pre', transform(code, id) { if (opts.filter(id)) { - if (process.env.UNI_RENDERER === 'native') { + if (renderer === 'native') { code = code.includes('createSSRApp') ? createApp(code) : createLegacyApp(code) return { - code: `import './${PAGES_JSON_JS}';` + code, + code: + `import './${PAGES_JSON_JS}';import('${APP_CSS_JS}').then(()=>{});` + + code, map: { mappings: '' }, } } diff --git a/packages/uni-app-vite/src/nvue/plugins/pagesJson.ts b/packages/uni-app-vite/src/nvue/plugins/pagesJson.ts index 068dafcc0..8f4e20571 100644 --- a/packages/uni-app-vite/src/nvue/plugins/pagesJson.ts +++ b/packages/uni-app-vite/src/nvue/plugins/pagesJson.ts @@ -11,7 +11,11 @@ import { MANIFEST_JSON_JS, } from '@dcloudio/uni-cli-shared' -export function uniPagesJsonPlugin(): Plugin { +export function uniPagesJsonPlugin({ + renderer, +}: { + renderer?: 'native' +}): Plugin { return defineUniPagesJsonPlugin((opts) => { return { name: 'uni:app-nvue-pages-json', @@ -34,7 +38,7 @@ export function uniPagesJsonPlugin(): Plugin { ) } }) - if (process.env.UNI_RENDERER === 'native') { + if (renderer === 'native') { this.emitFile({ fileName: `app-config-service.js`, type: 'asset', diff --git a/packages/uni-app-vite/src/plugin/build.ts b/packages/uni-app-vite/src/plugin/build.ts index d8690b809..95992905a 100644 --- a/packages/uni-app-vite/src/plugin/build.ts +++ b/packages/uni-app-vite/src/plugin/build.ts @@ -11,22 +11,34 @@ import { import { nvueOutDir } from '../utils' export function buildOptions( + renderer: 'native' | undefined, userConfig: UserConfig, _: ConfigEnv ): UserConfig['build'] { const inputDir = process.env.UNI_INPUT_DIR const outputDir = process.env.UNI_OUTPUT_DIR // 开始编译时,清空输出目录 - if (isInHybridNVue(userConfig)) { + function emptyNVueDir() { const nvueOutputDir = nvueOutDir() if (fs.existsSync(nvueOutputDir)) { emptyDir(nvueOutputDir) } - } else { + } + function emptyOutDir() { if (fs.existsSync(outputDir)) { emptyDir(outputDir) } } + if (renderer === 'native') { + emptyNVueDir() + emptyOutDir() + } else { + if (isInHybridNVue(userConfig)) { + emptyNVueDir() + } else { + emptyOutDir() + } + } return { // App 端目前仅提供 inline sourcemap: userConfig.build?.sourcemap ? 'inline' : false, diff --git a/packages/uni-app-vite/src/plugin/index.ts b/packages/uni-app-vite/src/plugin/index.ts index 0da025ba0..a5dad5847 100644 --- a/packages/uni-app-vite/src/plugin/index.ts +++ b/packages/uni-app-vite/src/plugin/index.ts @@ -3,13 +3,17 @@ import { UniVitePlugin } from '@dcloudio/uni-cli-shared' import { uniOptions } from './uni' import { buildOptions } from './build' -export function uniAppPlugin(): UniVitePlugin { +export function uniAppPlugin({ + renderer, +}: { + renderer?: 'native' +} = {}): UniVitePlugin { return { name: 'uni:app', uni: uniOptions(), config(config, env) { return { - build: buildOptions(config, env), + build: buildOptions(renderer, config, env), } }, } diff --git a/packages/vite-plugin-uni/src/cli/build.ts b/packages/vite-plugin-uni/src/cli/build.ts index fc5e8a038..b41af44ed 100644 --- a/packages/vite-plugin-uni/src/cli/build.ts +++ b/packages/vite-plugin-uni/src/cli/build.ts @@ -99,8 +99,19 @@ export async function buildApp(options: CliOptions) { return buildManifestJson() } if (process.env.UNI_RENDERER === 'native') { + // 纯原生渲染时,main.js + App.vue 需要跟页面分开,独立编译(因为需要包含 Vuex 等共享内容) process.env.UNI_COMPILER = 'nvue' - return buildByVite( + process.env.UNI_COMPILER_NVUE = 'app' + const nvueAppBuilder = await buildByVite( + addConfigFile( + extend( + { nvueApp: true, nvue: true }, + initBuildOptions(options, cleanOptions(options) as BuildOptions) + ) + ) + ) + process.env.UNI_COMPILER_NVUE = 'page' + const nvueBuilder = await buildByVite( addConfigFile( extend( { nvue: true }, @@ -108,6 +119,12 @@ export async function buildApp(options: CliOptions) { ) ) ) + if ((options as ServerOptions).watch) { + return initAppWatcher( + nvueAppBuilder as RollupWatcher, + nvueBuilder as RollupWatcher + ) + } } // 指定为 vue 方便 App 插件初始化 vue 所需插件列表 process.env.UNI_COMPILER = 'vue' @@ -138,56 +155,59 @@ export async function buildApp(options: CliOptions) { } class AppWatcher { - private _vueStart: boolean = false - private _vueEnd: boolean = false - private _nvueStart: boolean = false - private _nvueEnd: boolean = false + private _firstStart: boolean = false + private _firstEnd: boolean = false + private _secondStart: boolean = false + private _secondEnd: boolean = false private _callback!: (event: RollupWatcherEvent) => void on(callback: (event: RollupWatcherEvent) => void) { this._callback = callback } - _bundleVueStart(event: RollupWatcherEvent) { - this._vueStart = true + _bundleFirstStart(event: RollupWatcherEvent) { + this._firstStart = true this._bundleStart(event) } - _bundleVueEnd(event: RollupWatcherEvent) { - this._vueEnd = true + _bundleFirstEnd(event: RollupWatcherEvent) { + this._firstEnd = true this._bundleEnd(event) } - _bundleNVueStart(event: RollupWatcherEvent) { - this._nvueStart = true + _bundleSecondStart(event: RollupWatcherEvent) { + this._secondStart = true this._bundleStart(event) } - _bundleNVueEnd(event: RollupWatcherEvent) { - this._nvueEnd = true + _bundleSecondEnd(event: RollupWatcherEvent) { + this._secondEnd = true this._bundleEnd(event) } _bundleStart(event: RollupWatcherEvent) { - if (this._vueStart && this._nvueStart) { + if (this._firstStart && this._secondStart) { this._callback(event) } } _bundleEnd(event: RollupWatcherEvent) { - if (this._vueEnd && this._nvueEnd) { + if (this._firstEnd && this._secondEnd) { this._callback(event) } } } -function initAppWatcher(vueWatcher: RollupWatcher, nvueWatcher: RollupWatcher) { +function initAppWatcher( + firstWatcher: RollupWatcher, + secondWatcher: RollupWatcher +) { const appWatcher = new AppWatcher() - vueWatcher.on('event', (event) => { + firstWatcher.on('event', (event) => { if (event.code === 'BUNDLE_START') { - appWatcher._bundleVueStart(event) + appWatcher._bundleFirstStart(event) } else if (event.code === 'BUNDLE_END') { - appWatcher._bundleVueEnd(event) + appWatcher._bundleFirstEnd(event) } }) - nvueWatcher.on('event', (event) => { + secondWatcher.on('event', (event) => { if (event.code === 'BUNDLE_START') { - appWatcher._bundleNVueStart(event) + appWatcher._bundleSecondStart(event) } else if (event.code === 'BUNDLE_END') { - appWatcher._bundleNVueEnd(event) + appWatcher._bundleSecondEnd(event) } }) return { -- GitLab