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

wip(app): nvue

上级 3d2d1efc
......@@ -27,5 +27,6 @@ declare namespace NodeJS {
UNI_CUSTOM_CONTEXT?: string
UNI_MINIMIZE?: 'true'
UNI_COMPILER: 'vue' | 'nvue'
UNI_COMPILER_NVUE: 'app' | 'page'
}
}
......@@ -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()),
......
......@@ -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 }),
]
}
......@@ -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()],
......
......@@ -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__
......
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: '' },
}
}
......
......@@ -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',
......
......@@ -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,
......
......@@ -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),
}
},
}
......
......@@ -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 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册