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

wip(app): nvue

上级 ccb0721f
......@@ -9,5 +9,8 @@ declare namespace NodeJS {
UNI_CLI_CONTEXT: string
UNI_COMPILER_VERSION: string
UNI_HBUILDERX_PLUGINS: string
UNI_RENDERER?: 'native'
UNI_NVUE_COMPILER: 'uni-app' | 'weex' | 'vue'
UNI_NVUE_STYLE_COMPILER: 'uni-app' | 'weex'
}
}
......@@ -67,6 +67,7 @@ declare namespace UniApp {
alwaysShowBeforeRender: boolean
autoclose: boolean
}
onReady: (fn: Function) => void
}
interface UniRoute {
......@@ -160,6 +161,7 @@ declare namespace UniApp {
}
interface PagesJsonPageStyle extends PagesJsonPagePlatformStyle {
isNVue?: boolean
disableScroll?: boolean
enablePullDownRefresh?: boolean
navigationBar: PageNavigationBar
......@@ -175,7 +177,6 @@ declare namespace UniApp {
interface PageRouteMeta extends PagesJsonPageStyle {
id?: number
route: string
isNVue?: boolean
isQuit?: boolean
isEntry?: boolean
isTabBar?: boolean
......
......@@ -1866,7 +1866,9 @@ var serviceContext = (function (vue) {
if (!vm) {
return;
}
const hooks = vm.$[name];
// 兼容 nvue
const hooks = (vm._$weex ? vm.$options : vm.$)[name]
;
return hooks && invokeArrayFns(hooks, args);
}
......@@ -10847,7 +10849,7 @@ var serviceContext = (function (vue) {
return preloadWebviews[url];
}
function registerPage({ url, path, query, openType, webview, vm, }) {
function registerPage({ url, path, query, openType, webview, }) {
// fast 模式,nvue 首页时,会在nvue中主动调用registerPage并传入首页webview,此时初始化一下首页(因为此时可能还未调用registerApp)
if (webview) {
initEntry();
......@@ -10893,15 +10895,15 @@ var serviceContext = (function (vue) {
const route = path.substr(1);
webview.__uniapp_route = route;
const pageInstance = initPageInternalInstance(openType, url, query, routeOptions.meta);
if (!webview.nvue) {
createPage(parseInt(webview.id), route, query, pageInstance, initPageOptions(routeOptions));
initNVueEntryPage(webview);
if (webview.nvue) {
// nvue 时,先启用一个占位 vm
const fakeNVueVm = createNVueVm(webview, pageInstance);
initPageVm(fakeNVueVm, pageInstance);
addCurrentPage(fakeNVueVm);
}
else {
initPageVm(vm, pageInstance);
addCurrentPage(vm);
if (webview.__preload__) {
webview.__page__ = vm;
}
createPage(parseInt(webview.id), route, query, pageInstance, initPageOptions(routeOptions));
}
return webview;
}
......@@ -10926,6 +10928,40 @@ var serviceContext = (function (vue) {
windowTop: meta.navigationBar.type === 'float' ? statusbarHeight + NAVBAR_HEIGHT : 0,
windowBottom: tabBar$1.indexOf(meta.route) >= 0 && tabBar$1.cover ? tabBar$1.height : 0,
};
}
function initNVueEntryPage(webview) {
const isLaunchNVuePage = webview.id === '1' && webview.nvue;
// 首页是 nvue 时,在 registerPage 时,执行路由堆栈
if (isLaunchNVuePage) {
if (__uniConfig.splashscreen &&
__uniConfig.splashscreen.autoclose &&
!__uniConfig.splashscreen.alwaysShowBeforeRender) {
plus.navigator.closeSplashscreen();
}
__uniConfig.onReady(function () {
navigateFinish();
});
}
}
function createNVueVm(webview, pageInstance) {
return {
$: {},
onNVuePageCreated(vm, curNVuePage) {
// 替换真实的 nvue 的 vm
initPageVm(vm, pageInstance);
const pages = getAllPages();
const index = pages.findIndex((p) => p === curNVuePage);
if (index > -1) {
pages.splice(index, 1, vm);
}
if (webview.__preload__) {
webview.__page__ = vm;
}
},
$getAppWebview() {
return webview;
},
};
}
const navigateTo = defineAsyncApi(API_NAVIGATE_TO, (args, { resolve, reject }) => {
......
......@@ -14,9 +14,10 @@ import { createWebview, initWebview } from '../webview'
import { createPage } from './define'
import { getStatusbarHeight } from '../../../helpers/statusBar'
import tabBar from '../app/tabBar'
import { addCurrentPage } from './getCurrentPages'
import { addCurrentPage, getAllPages } from './getCurrentPages'
import { getBaseSystemInfo } from '../../api/base/getBaseSystemInfo'
import { preloadWebviews, PreloadWebviewObject } from './preLoad'
import { navigateFinish } from '../../api/route/utils'
interface RegisterPageOptions {
url: string
......@@ -24,7 +25,6 @@ interface RegisterPageOptions {
query: Record<string, string>
openType: UniApp.OpenType
webview?: PlusWebviewWebviewObject
vm?: ComponentPublicInstance // nvue vm instance
// eventChannel: unknown
}
......@@ -34,7 +34,6 @@ export function registerPage({
query,
openType,
webview,
vm,
}: RegisterPageOptions) {
// fast 模式,nvue 首页时,会在nvue中主动调用registerPage并传入首页webview,此时初始化一下首页(因为此时可能还未调用registerApp)
if (webview) {
......@@ -96,7 +95,14 @@ export function registerPage({
routeOptions.meta
)
if (!(webview as any).nvue) {
initNVueEntryPage(webview)
if ((webview as any).nvue) {
// nvue 时,先启用一个占位 vm
const fakeNVueVm = createNVueVm(webview, pageInstance)
initPageVm(fakeNVueVm, pageInstance)
addCurrentPage(fakeNVueVm)
} else {
createPage(
parseInt(webview.id!),
route,
......@@ -104,13 +110,6 @@ export function registerPage({
pageInstance,
initPageOptions(routeOptions)
)
} else {
initPageVm(vm!, pageInstance)
addCurrentPage(vm!)
if ((webview as any).__preload__) {
;(webview as any).__page__ = vm
}
}
return webview
}
......@@ -139,3 +138,44 @@ function initPageOptions({ meta }: UniApp.UniRoute): PageNodeOptions {
tabBar.indexOf(meta.route) >= 0 && tabBar.cover ? tabBar.height : 0,
}
}
function initNVueEntryPage(webview: PlusWebviewWebviewObject) {
const isLaunchNVuePage = webview.id === '1' && (webview as any).nvue
// 首页是 nvue 时,在 registerPage 时,执行路由堆栈
if (isLaunchNVuePage) {
if (
__uniConfig.splashscreen &&
__uniConfig.splashscreen.autoclose &&
!__uniConfig.splashscreen.alwaysShowBeforeRender
) {
plus.navigator.closeSplashscreen()
}
__uniConfig.onReady(function () {
navigateFinish()
})
}
}
function createNVueVm(
webview: PlusWebviewWebviewObject,
pageInstance: Page.PageInstance['$page']
) {
return {
$: {}, // navigateBack 时,invokeHook 会调用 $
onNVuePageCreated(vm: ComponentPublicInstance, curNVuePage: unknown) {
// 替换真实的 nvue 的 vm
initPageVm(vm, pageInstance)
const pages = getAllPages()
const index = pages.findIndex((p) => p === curNVuePage)
if (index > -1) {
pages.splice(index, 1, vm)
}
if ((webview as any).__preload__) {
;(webview as any).__page__ = vm
}
},
$getAppWebview() {
return webview
},
} as unknown as ComponentPublicInstance
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initEnv = void 0;
function initEnv(options) {
if (options.styleCompiler === 'uni-app') {
process.env.UNI_NVUE_STYLE_COMPILER = 'uni-app';
}
}
exports.initEnv = initEnv;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createEntry = void 0;
function createEntry() {
return process.UNI_NVUE_ENTRY;
}
exports.createEntry = createEntry;
......@@ -6,14 +6,13 @@ const output_1 = require("./output");
const module_1 = require("./module");
const plugins_1 = require("./plugins");
const resolve_1 = require("./resolve");
const entry_1 = require("./entry");
function createConfig(mode, options) {
return {
mode: mode,
devtool: false,
watch: mode === 'development',
entry() {
return process.UNI_NVUE_ENTRY;
},
entry: entry_1.createEntry(),
externals: {
vue: 'Vue',
},
......
......@@ -6,10 +6,10 @@ const boolAttr_1 = require("./boolAttr");
const easycom_1 = require("./easycom");
const renderWhole_1 = require("./renderWhole");
const tags_1 = require("./tags");
function createModules(options) {
function createModules(_) {
// 先处理 easycom
const modules = [easycom_1.createEasycomModule(), renderWhole_1.createRenderWholeModule()];
if (options.compiler === 'uni-app') {
if (process.env.UNI_NVUE_COMPILER === 'uni-app') {
modules.push(tags_1.createTagsModule());
}
modules.push(assetUrl_1.createAssetUrlModule());
......
......@@ -8,10 +8,8 @@ const webpack_1 = __importDefault(require("webpack"));
const uni_shared_1 = require("@dcloudio/uni-shared");
const config_1 = require("./config");
const alias_1 = require("./alias");
const env_1 = require("../utils/env");
const initModuleAliasOnce = uni_shared_1.once(alias_1.initModuleAlias);
function runWebpack(mode, options) {
env_1.initEnv(options);
initModuleAliasOnce();
return new Promise((resolve, reject) => {
webpack_1.default(config_1.createConfig(mode, options), (err, stats) => {
......
interface NVueCompilerOptions {
compiler: 'uni-app' | 'weex'
styleCompiler: 'uni-app' | 'weex'
}
interface NVueCompilerOptions {}
export function initEnv(options: NVueCompilerOptions) {
if (options.styleCompiler === 'uni-app') {
process.env.UNI_NVUE_STYLE_COMPILER = 'uni-app'
}
}
export function createEntry() {
return process.UNI_NVUE_ENTRY
}
......@@ -4,6 +4,7 @@ import { createOutput } from './output'
import { createModule } from './module'
import { createPlugins } from './plugins'
import { createResolve } from './resolve'
import { createEntry } from './entry'
export function createConfig(
mode: 'production' | 'development',
options: NVueCompilerOptions
......@@ -12,9 +13,7 @@ export function createConfig(
mode: mode,
devtool: false,
watch: mode === 'development',
entry() {
return process.UNI_NVUE_ENTRY
},
entry: createEntry(),
externals: {
vue: 'Vue',
},
......
......@@ -4,10 +4,10 @@ import { createBoolAttrModule } from './boolAttr'
import { createEasycomModule } from './easycom'
import { createRenderWholeModule } from './renderWhole'
import { createTagsModule } from './tags'
export function createModules(options: NVueCompilerOptions): ModuleOptions[] {
export function createModules(_: NVueCompilerOptions): ModuleOptions[] {
// 先处理 easycom
const modules = [createEasycomModule(), createRenderWholeModule()]
if (options.compiler === 'uni-app') {
if (process.env.UNI_NVUE_COMPILER === 'uni-app') {
modules.push(createTagsModule())
}
......
......@@ -3,7 +3,6 @@ import { once } from '@dcloudio/uni-shared'
import { createConfig } from './config'
import { initModuleAlias } from './alias'
import { initEnv } from '../utils/env'
const initModuleAliasOnce = once(initModuleAlias)
......@@ -11,7 +10,6 @@ function runWebpack(
mode: 'production' | 'development',
options: NVueCompilerOptions
) {
initEnv(options)
initModuleAliasOnce()
return new Promise((resolve, reject) => {
webpack(createConfig(mode, options), (err, stats) => {
......
......@@ -17,13 +17,17 @@ export function initLaunchwebview(
process.env.UNI_ENTRY_PAGE_PATH = entryPagePath
manifestJson.plus.useragent.value = 'uni-app'
manifestJson.launch_path = '__uniappview.html'
extend(manifestJson.plus.launchwebview, {
id: '1',
kernel: 'WKWebview',
})
// TODO 纯原生渲染
// TODO 首页为nvue
// manifestJson.plus.launchwebview.uniNView = {path:'.js'}
// manifestJson.plus.launchwebview.id = '2'
// 首页为nvue
const entryPage = pagesJson.pages.find((p) => p.path === entryPagePath)
if (entryPage?.style.isNVue) {
manifestJson.plus.launchwebview.uniNView = { path: entryPagePath + '.js' }
manifestJson.plus.launchwebview.id = '2'
} else {
manifestJson.launch_path = '__uniappview.html'
}
}
......@@ -3,10 +3,24 @@ export function initNVue(
pagesJson: UniApp.PagesJson
) {}
export function getRenderer(manifestJson: Record<string, any>) {
const platformOptions = manifestJson['app-plus']
if (platformOptions && platformOptions.renderer === 'native') {
return 'native'
}
return ''
}
export function getNVueCompiler(manifestJson: Record<string, any>) {
const platformOptions = manifestJson['app-plus']
if (platformOptions && platformOptions.nvueCompiler === 'weex') {
return 'weex'
if (platformOptions) {
const { nvueCompiler } = platformOptions
if (nvueCompiler === 'weex') {
return 'weex'
}
if (nvueCompiler === 'vue') {
return 'vue'
}
}
return 'uni-app'
}
......
......@@ -3,7 +3,10 @@ import { normalizeIdentifier, normalizePagePath } from '../../../utils'
export function definePageCode(pagesJson: Record<string, any>) {
const importPagesCode: string[] = []
const definePagesCode: string[] = []
pagesJson.pages.forEach((page: UniApp.UniRoute) => {
pagesJson.pages.forEach((page: UniApp.PagesJsonPageOptions) => {
if (page.style.isNVue) {
return
}
const pagePath = page.path
const pageIdentifier = normalizeIdentifier(pagePath)
const pagePathWithExtname = normalizePagePath(pagePath, 'app')
......
......@@ -3,6 +3,8 @@ import { definePageCode } from './definePage'
import { normalizeAppUniConfig } from './uniConfig'
import { normalizeAppUniRoutes } from './uniRoutes'
export * from './nvue'
export function normalizeAppPagesJson(pagesJson: Record<string, any>) {
return polyfillCode + restoreGlobalCode + definePageCode(pagesJson)
}
......
import path from 'path'
import { normalizePath } from '../../../utils'
export function initWebpackNVueEntry(pages: UniApp.PagesJsonPageOptions[]) {
process.UNI_NVUE_ENTRY = {}
pages.forEach((page) => {
if (page.style.isNVue) {
process.UNI_NVUE_ENTRY[page.path] = genWebpackBase64Code(page.path)
}
})
}
function genWebpackBase64Code(route: string) {
return `data:text/javascript;base64,${Buffer.from(
genNVueEntryCode(route)
).toString('base64')}`
}
function genNVueEntryCode(route: string) {
return `import App from '${normalizePath(
path.resolve(process.env.UNI_INPUT_DIR, route)
)}.nvue?mpType=page'
if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {
Promise.prototype.finally = function(callback) {
var promise = this.constructor
return this.then(function(value) {
return promise.resolve(callback()).then(function() {
return value
})
}, function(reason) {
return promise.resolve(callback()).then(function() {
throw reason
})
})
}
}
App.mpType = 'page'
App.route = '${route}'
App.el = '#root'
new Vue(App)
`
}
......@@ -9,7 +9,7 @@ interface AppUniConfig {
pages: string[]
globalStyle: UniApp.PagesJsonPageStyle
nvue: {
compiler: 'uni-app' | 'weex'
compiler: 'uni-app' | 'weex' | 'vue'
styleCompiler: 'weex' | 'uni-app'
'flex-direction': 'row' | 'row-reverse' | 'column' | 'column-reverse'
}
......
......@@ -4,6 +4,7 @@ import { extend, hasOwn, isArray, isPlainObject } from '@vue/shared'
import { once, TABBAR_HEIGHT } from '@dcloudio/uni-shared'
import { normalizePath } from '../utils'
import { parseJson } from './json'
import { initWebpackNVueEntry } from './app/pages'
export const parsePagesJson = (
inputDir: string,
......@@ -40,8 +41,17 @@ export function normalizePagesJson(jsonStr: string, platform: UniApp.PLATFORM) {
)
// pageStyle
normalizePages(pagesJson.pages, platform)
if (platform === 'app' && process.env.UNI_NVUE_COMPILER !== 'vue') {
initWebpackNVueEntry(pagesJson.pages)
}
// globalStyle
pagesJson.globalStyle = normalizePageStyle(pagesJson.globalStyle!, platform)
pagesJson.globalStyle = normalizePageStyle(
null,
pagesJson.globalStyle!,
platform
)
// tabBar
if (pagesJson.tabBar) {
const tabBar = normalizeTabBar(pagesJson.tabBar!)
......@@ -70,7 +80,7 @@ function normalizePages(
platform: UniApp.PLATFORM
) {
return pages.filter((page) => {
page.style = normalizePageStyle(page.style!, platform)
page.style = normalizePageStyle(page.path, page.style!, platform)
return true
})
}
......@@ -93,9 +103,17 @@ function normalizeSubpackages(
}
function normalizePageStyle(
pagePath: string | null,
pageStyle: UniApp.PagesJsonPageStyle,
platform: UniApp.PLATFORM
) {
const isNVue =
pagePath &&
process.env.UNI_NVUE_COMPILER !== 'vue' &&
fs.existsSync(path.join(process.env.UNI_INPUT_DIR, pagePath + '.nvue'))
? true
: undefined
if (pageStyle) {
if (platform === 'h5') {
extend(pageStyle, pageStyle['app'] || pageStyle['app-plus'])
......@@ -112,9 +130,10 @@ function normalizePageStyle(
pageStyle.pullToRefresh = normalizePullToRefresh(pageStyle)
}
}
pageStyle.isNVue = isNVue
return removePlatformStyle(pageStyle)
}
return { navigationBar: {} }
return { navigationBar: {}, isNVue }
}
const navigationBarMaps = {
......@@ -323,13 +342,9 @@ export function normalizePagesRoute(
(tabBarPage: { pagePath: string }) => tabBarPage.pagePath === pagePath
)
const isTabBar = tabBarIndex !== -1 ? true : undefined
const isNVue = fs.existsSync(
path.join(process.env.UNI_INPUT_DIR, pagePath + '.nvue')
)
let windowTop = 0
const meta = extend(
{
isNVue: isNVue || undefined,
isQuit: isEntry || isTabBar ? true : undefined,
isEntry: isEntry || undefined,
isTabBar: isTabBar || undefined,
......
......@@ -30,7 +30,12 @@ export function invokeHook(
if (!vm) {
return
}
const hooks = vm.$[name as string]
// 兼容 nvue
const hooks =
__PLATFORM__ === 'app'
? ((vm as any)._$weex ? vm.$options : vm.$)[name as string]
: vm.$[name as string]
return hooks && invokeArrayFns(hooks, args)
}
......
......@@ -3,20 +3,22 @@ import {
getNVueCompiler,
getNVueStyleCompiler,
} from '@dcloudio/uni-cli-shared'
import { getRenderer } from '../../../uni-cli-shared/dist/json/app/manifest/nvue'
function initNVueCompilerOptions() {
export function initNVueEnv() {
const manifestJson = parseManifestJsonOnce(process.env.UNI_INPUT_DIR)
const nvueCompilerOptions = {
compiler: 'uni-app',
styleCompiler: 'weex',
if (getRenderer(manifestJson) === 'native') {
process.env.UNI_RENDERER = 'native'
}
if (getNVueCompiler(manifestJson) === 'uni-app') {
nvueCompilerOptions.compiler = 'uni-app'
const nvueCompiler = getNVueCompiler(manifestJson)
if (nvueCompiler === 'uni-app') {
process.env.UNI_NVUE_COMPILER = 'uni-app'
} else if (nvueCompiler === 'vue') {
process.env.UNI_NVUE_COMPILER = 'vue'
}
if (getNVueStyleCompiler(manifestJson) === 'uni-app') {
nvueCompilerOptions.styleCompiler = 'uni-app'
process.env.UNI_NVUE_STYLE_COMPILER = 'uni-app'
}
return nvueCompilerOptions
}
export async function runNVue(mode: 'prod' | 'dev') {
......@@ -38,10 +40,12 @@ export async function runNVue(mode: 'prod' | 'dev') {
if (!nvue) {
return
}
const options = initNVueCompilerOptions()
if (process.env.UNI_NVUE_COMPILER === 'vue') {
return
}
if (mode === 'prod') {
await nvue.runWebpackBuild(options)
await nvue.runWebpackBuild()
} else {
await nvue.runWebpackDev(options)
await nvue.runWebpackDev()
}
}
......@@ -5,6 +5,7 @@ import { BuildOptions, InlineConfig } from 'vite'
import { isInHBuilderX } from '@dcloudio/uni-cli-shared'
import { CliOptions } from '.'
import { initNVueEnv } from './nvue'
export const PLATFORMS = [
'app',
......@@ -82,6 +83,9 @@ export function initEnv(type: 'dev' | 'build', options: CliOptions) {
process.exit(1)
)
}
if (process.env.UNI_PLATFORM === 'app') {
initNVueEnv()
}
}
export function cleanOptions(options: CliOptions) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册