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

wip(app): app watcher

上级 ad69e765
...@@ -29,5 +29,7 @@ declare namespace NodeJS { ...@@ -29,5 +29,7 @@ declare namespace NodeJS {
UNI_COMPILER: 'vue' | 'nvue' UNI_COMPILER: 'vue' | 'nvue'
UNI_RENDERER_NATIVE: 'appService' | 'pages' UNI_RENDERER_NATIVE: 'appService' | 'pages'
UNI_NVUE_APP_STYLES: string UNI_NVUE_APP_STYLES: string
UNI_APP_CHANGED_FILES: string
UNI_APP_CHANGED_PAGES: string
} }
} }
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -649,7 +649,10 @@ function getBaseSystemInfo() { ...@@ -649,7 +649,10 @@ function getBaseSystemInfo() {
if (typeof __SYSTEM_INFO__ !== 'undefined') { if (typeof __SYSTEM_INFO__ !== 'undefined') {
return window.__SYSTEM_INFO__; return window.__SYSTEM_INFO__;
} }
const { resolutionWidth } = plus.screen.getCurrentSize(); // 好像开发时刷新,偶发的 plus.screen.getCurrentSize 为 undefined
const { resolutionWidth } = plus.screen.getCurrentSize() || {
resolutionWidth: 0,
};
return { return {
platform: (plus.os.name || '').toLowerCase(), platform: (plus.os.name || '').toLowerCase(),
pixelRatio: plus.screen.scale, pixelRatio: plus.screen.scale,
...@@ -13043,7 +13046,11 @@ function deviceId$1 () { ...@@ -13043,7 +13046,11 @@ function deviceId$1 () {
} }
function getScreenInfo() { function getScreenInfo() {
const { resolutionWidth, resolutionHeight } = plus.screen.getCurrentSize(); // 好像开发时刷新,偶发的 plus.screen.getCurrentSize 为 undefined
const { resolutionWidth, resolutionHeight } = plus.screen.getCurrentSize() || {
resolutionWidth: 0,
resolutionHeight: 0,
};
return { return {
screenWidth: Math.round(resolutionWidth), screenWidth: Math.round(resolutionWidth),
screenHeight: Math.round(resolutionHeight), screenHeight: Math.round(resolutionHeight),
......
...@@ -7,7 +7,10 @@ export function getBaseSystemInfo() { ...@@ -7,7 +7,10 @@ export function getBaseSystemInfo() {
if (typeof __SYSTEM_INFO__ !== 'undefined') { if (typeof __SYSTEM_INFO__ !== 'undefined') {
return (window as any).__SYSTEM_INFO__ return (window as any).__SYSTEM_INFO__
} }
const { resolutionWidth } = plus.screen.getCurrentSize() // 好像开发时刷新,偶发的 plus.screen.getCurrentSize 为 undefined
const { resolutionWidth } = plus.screen.getCurrentSize() || {
resolutionWidth: 0,
}
return { return {
platform: (plus.os.name || '').toLowerCase(), platform: (plus.os.name || '').toLowerCase(),
pixelRatio: plus.screen.scale!, pixelRatio: plus.screen.scale!,
......
...@@ -9,7 +9,12 @@ import deviceId from '../../../helpers/uuid' ...@@ -9,7 +9,12 @@ import deviceId from '../../../helpers/uuid'
type SafeAreaInsets = Required<PlusNavigatorSafeAreaInsets> type SafeAreaInsets = Required<PlusNavigatorSafeAreaInsets>
function getScreenInfo() { function getScreenInfo() {
const { resolutionWidth, resolutionHeight } = plus.screen.getCurrentSize() // 好像开发时刷新,偶发的 plus.screen.getCurrentSize 为 undefined
const { resolutionWidth, resolutionHeight } =
plus.screen.getCurrentSize() || {
resolutionWidth: 0,
resolutionHeight: 0,
}
return { return {
screenWidth: Math.round(resolutionWidth), screenWidth: Math.round(resolutionWidth),
screenHeight: Math.round(resolutionHeight), screenHeight: Math.round(resolutionHeight),
......
...@@ -28,9 +28,8 @@ export function initNVuePlugins() { ...@@ -28,9 +28,8 @@ export function initNVuePlugins() {
uniManifestJsonPlugin(), uniManifestJsonPlugin(),
uniPagesJsonPlugin({ renderer, appService }), uniPagesJsonPlugin({ renderer, appService }),
uniViteInjectPlugin('uni:app-inject', initAppProvide()), uniViteInjectPlugin('uni:app-inject', initAppProvide()),
uniStatsPlugin(),
uniAppNVuePlugin({ appService }), uniAppNVuePlugin({ appService }),
uniEsbuildPlugin({ renderer, appService }), uniEsbuildPlugin({ renderer, appService }),
...(appService ? [uniTemplatePlugin({ renderer })] : []), ...(appService ? [uniStatsPlugin(), uniTemplatePlugin({ renderer })] : []),
] ]
} }
import type { Plugin } from 'vite' import type { Plugin, ResolvedConfig } from 'vite'
import type { BuildOptions, PluginBuild } from 'esbuild' import type { BuildOptions, PluginBuild } from 'esbuild'
import path from 'path' import path from 'path'
...@@ -7,6 +7,7 @@ import debug from 'debug' ...@@ -7,6 +7,7 @@ import debug from 'debug'
import { import {
APP_CONFIG_SERVICE, APP_CONFIG_SERVICE,
hash,
removeExt, removeExt,
transformWithEsbuild, transformWithEsbuild,
} from '@dcloudio/uni-cli-shared' } from '@dcloudio/uni-cli-shared'
...@@ -17,14 +18,18 @@ import { APP_CSS_JS } from './appCss' ...@@ -17,14 +18,18 @@ import { APP_CSS_JS } from './appCss'
const debugEsbuild = debug('uni:app-nvue-esbuild') const debugEsbuild = debug('uni:app-nvue-esbuild')
const emittedHashMap = new WeakMap<ResolvedConfig, Map<string, string>>()
export function uniEsbuildPlugin({ export function uniEsbuildPlugin({
appService, appService,
}: { }: {
renderer?: 'native' renderer?: 'native'
appService: boolean appService: boolean
}): Plugin { }): Plugin {
let resolvedConfig: ResolvedConfig
let buildOptions: BuildOptions let buildOptions: BuildOptions
const outputDir = process.env.UNI_OUTPUT_DIR const outputDir = process.env.UNI_OUTPUT_DIR
let isFirst = true
return { return {
name: 'uni:app-nvue-esbuild', name: 'uni:app-nvue-esbuild',
enforce: 'post', enforce: 'post',
...@@ -39,6 +44,8 @@ export function uniEsbuildPlugin({ ...@@ -39,6 +44,8 @@ export function uniEsbuildPlugin({
write: false, write: false,
plugins: [esbuildGlobalPlugin(esbuildGlobals(appService))], plugins: [esbuildGlobalPlugin(esbuildGlobals(appService))],
} }
resolvedConfig = config
emittedHashMap.set(resolvedConfig, new Map<string, string>())
}, },
async writeBundle(_, bundle) { async writeBundle(_, bundle) {
const entryPoints: string[] = [] const entryPoints: string[] = []
...@@ -55,14 +62,31 @@ export function uniEsbuildPlugin({ ...@@ -55,14 +62,31 @@ export function uniEsbuildPlugin({
if (!entryPoints.length) { if (!entryPoints.length) {
return return
} }
buildAppCss() const emittedHash = emittedHashMap.get(resolvedConfig)!
const changedFiles: string[] = []
if (buildAppCss()) {
changedFiles.push(APP_CONFIG_SERVICE)
}
debugEsbuild('start', entryPoints.length, entryPoints) debugEsbuild('start', entryPoints.length, entryPoints)
for (const filename of entryPoints) { for (const filename of entryPoints) {
await buildNVuePage(filename, buildOptions).then((code) => { await buildNVuePage(filename, buildOptions).then((code) => {
const outputFileHash = hash(code)
if (emittedHash.get(filename) !== outputFileHash) {
changedFiles.push(filename)
emittedHash.set(filename, outputFileHash)
return fs.outputFile(path.resolve(outputDir, filename), code) return fs.outputFile(path.resolve(outputDir, filename), code)
}
}) })
} }
if (!isFirst && changedFiles.length) {
process.env[
changedFiles.includes(APP_CONFIG_SERVICE)
? 'UNI_APP_CHANGED_FILES'
: 'UNI_APP_CHANGED_PAGES'
] = JSON.stringify(changedFiles)
}
debugEsbuild('end') debugEsbuild('end')
isFirst = false
}, },
} }
} }
...@@ -76,28 +100,29 @@ function buildAppCss() { ...@@ -76,28 +100,29 @@ function buildAppCss() {
if (!fs.existsSync(appCssJsFilename)) { if (!fs.existsSync(appCssJsFilename)) {
return return
} }
const appConfigServiceFilename = path.join(
process.env.UNI_OUTPUT_DIR,
APP_CONFIG_SERVICE
)
if (!fs.existsSync(appConfigServiceFilename)) {
return
}
const appCssJsCode = fs.readFileSync(appCssJsFilename, 'utf8') const appCssJsCode = fs.readFileSync(appCssJsFilename, 'utf8')
const appCssJsFn = new Function('exports', appCssJsCode) const appCssJsFn = new Function('exports', appCssJsCode)
const exports = { styles: [] } const exports = { styles: [] }
appCssJsFn(exports) appCssJsFn(exports)
const appCssJsonCode = JSON.stringify(exports.styles) const appCssJsonCode = JSON.stringify(exports.styles)
if (process.env.UNI_NVUE_APP_STYLES === appCssJsonCode) { if (process.env.UNI_NVUE_APP_STYLES === appCssJsonCode) {
return return
} }
process.env.UNI_NVUE_APP_STYLES = appCssJsonCode process.env.UNI_NVUE_APP_STYLES = appCssJsonCode
// 首次 build 时,可能还没生成 app-config-service 的文件,故仅写入环境变量
const appConfigServiceFilename = path.join(
process.env.UNI_OUTPUT_DIR,
APP_CONFIG_SERVICE
)
if (!fs.existsSync(appConfigServiceFilename)) {
return
}
const appConfigServiceCode = fs.readFileSync(appConfigServiceFilename, 'utf8') const appConfigServiceCode = fs.readFileSync(appConfigServiceFilename, 'utf8')
fs.writeFileSync( fs.writeFileSync(
appConfigServiceFilename, appConfigServiceFilename,
wrapperNVueAppStyles(appConfigServiceCode) wrapperNVueAppStyles(appConfigServiceCode)
) )
return true
} }
function buildNVuePage(filename: string, options: BuildOptions) { function buildNVuePage(filename: string, options: BuildOptions) {
......
import { extend } from '@vue/shared' import { extend } from '@vue/shared'
import { RollupWatcher } from 'rollup' import { RollupWatcher } from 'rollup'
import { BuildOptions, createLogger, ServerOptions } from 'vite' import { BuildOptions, createLogger, ServerOptions } from 'vite'
import { M, output } from '@dcloudio/uni-cli-shared' import { APP_CONFIG_SERVICE, M, output } from '@dcloudio/uni-cli-shared'
import { CliOptions } from '.' import { CliOptions } from '.'
import { build, buildSSR } from './build' import { build, buildSSR } from './build'
import { createServer, createSSRServer } from './server' import { createServer, createSSRServer } from './server'
...@@ -42,11 +42,20 @@ export async function runDev(options: CliOptions & ServerOptions) { ...@@ -42,11 +42,20 @@ export async function runDev(options: CliOptions & ServerOptions) {
) )
} }
const files = process.env.UNI_APP_CHANGED_FILES const files = process.env.UNI_APP_CHANGED_FILES
if (files && !files.includes('app-config-service.js')) { const pages = process.env.UNI_APP_CHANGED_PAGES
const changedFiles = pages || files
process.env.UNI_APP_CHANGED_PAGES = ''
process.env.UNI_APP_CHANGED_FILES = '' process.env.UNI_APP_CHANGED_FILES = ''
if (changedFiles && !changedFiles.includes(APP_CONFIG_SERVICE)) {
if (pages) {
return output( return output(
'log', 'log',
M['dev.watching.end.files'].replace('{files}', files) M['dev.watching.end.pages'].replace('{pages}', changedFiles)
)
}
return output(
'log',
M['dev.watching.end.files'].replace('{files}', changedFiles)
) )
} }
return output('log', M['dev.watching.end']) return output('log', M['dev.watching.end'])
......
...@@ -98,6 +98,10 @@ export async function buildApp(options: CliOptions) { ...@@ -98,6 +98,10 @@ export async function buildApp(options: CliOptions) {
if ((options as BuildOptions).manifest) { if ((options as BuildOptions).manifest) {
return buildManifestJson() return buildManifestJson()
} }
let appWatcher: AppWatcher | undefined
if ((options as ServerOptions).watch) {
appWatcher = new AppWatcher()
}
if (process.env.UNI_RENDERER === 'native') { if (process.env.UNI_RENDERER === 'native') {
// 纯原生渲染时,main.js + App.vue 需要跟页面分开,独立编译(因为需要包含 Vuex 等共享内容) // 纯原生渲染时,main.js + App.vue 需要跟页面分开,独立编译(因为需要包含 Vuex 等共享内容)
process.env.UNI_COMPILER = 'nvue' process.env.UNI_COMPILER = 'nvue'
...@@ -105,11 +109,15 @@ export async function buildApp(options: CliOptions) { ...@@ -105,11 +109,15 @@ export async function buildApp(options: CliOptions) {
const nvueAppBuilder = await buildByVite( const nvueAppBuilder = await buildByVite(
addConfigFile( addConfigFile(
extend( extend(
{ nvueApp: true, nvue: true }, { nvueAppService: true, nvue: true },
initBuildOptions(options, cleanOptions(options) as BuildOptions) initBuildOptions(options, cleanOptions(options) as BuildOptions)
) )
) )
) )
if (appWatcher) {
appWatcher.setFirstWatcher(nvueAppBuilder as RollupWatcher)
}
process.env.UNI_RENDERER_NATIVE = 'pages' process.env.UNI_RENDERER_NATIVE = 'pages'
const nvueBuilder = await buildByVite( const nvueBuilder = await buildByVite(
addConfigFile( addConfigFile(
...@@ -119,12 +127,11 @@ export async function buildApp(options: CliOptions) { ...@@ -119,12 +127,11 @@ export async function buildApp(options: CliOptions) {
) )
) )
) )
if ((options as ServerOptions).watch) { if (appWatcher) {
return initAppWatcher( appWatcher.setSecondWatcher(nvueBuilder as RollupWatcher)
nvueAppBuilder as RollupWatcher, return appWatcher
nvueBuilder as RollupWatcher
)
} }
return
} }
// 指定为 vue 方便 App 插件初始化 vue 所需插件列表 // 指定为 vue 方便 App 插件初始化 vue 所需插件列表
process.env.UNI_COMPILER = 'vue' process.env.UNI_COMPILER = 'vue'
...@@ -133,6 +140,9 @@ export async function buildApp(options: CliOptions) { ...@@ -133,6 +140,9 @@ export async function buildApp(options: CliOptions) {
initBuildOptions(options, cleanOptions(options) as BuildOptions) initBuildOptions(options, cleanOptions(options) as BuildOptions)
) )
) )
if (appWatcher) {
appWatcher.setFirstWatcher(vueBuilder as RollupWatcher)
}
// 临时指定为 nvue 方便 App 插件初始化 nvue 所需插件列表 // 临时指定为 nvue 方便 App 插件初始化 nvue 所需插件列表
process.env.UNI_COMPILER = 'nvue' process.env.UNI_COMPILER = 'nvue'
const nvueBuilder = await buildByVite( const nvueBuilder = await buildByVite(
...@@ -146,11 +156,9 @@ export async function buildApp(options: CliOptions) { ...@@ -146,11 +156,9 @@ export async function buildApp(options: CliOptions) {
// 还原为 vue // 还原为 vue
process.env.UNI_COMPILER = 'vue' process.env.UNI_COMPILER = 'vue'
if ((options as ServerOptions).watch) { if (appWatcher) {
return initAppWatcher( appWatcher.setSecondWatcher(nvueBuilder as RollupWatcher)
vueBuilder as RollupWatcher, return appWatcher
nvueBuilder as RollupWatcher
)
} }
} }
...@@ -160,9 +168,27 @@ class AppWatcher { ...@@ -160,9 +168,27 @@ class AppWatcher {
private _secondStart: boolean = false private _secondStart: boolean = false
private _secondEnd: boolean = false private _secondEnd: boolean = false
private _callback!: (event: RollupWatcherEvent) => void private _callback!: (event: RollupWatcherEvent) => void
on(callback: (event: RollupWatcherEvent) => void) { on(_event: string, callback: (event: RollupWatcherEvent) => void) {
this._callback = callback this._callback = callback
} }
setFirstWatcher(firstWatcher: RollupWatcher) {
firstWatcher.on('event', (event) => {
if (event.code === 'BUNDLE_START') {
this._bundleFirstStart(event)
} else if (event.code === 'BUNDLE_END') {
this._bundleFirstEnd(event)
}
})
}
setSecondWatcher(secondWatcher: RollupWatcher) {
secondWatcher.on('event', (event) => {
if (event.code === 'BUNDLE_START') {
this._bundleSecondStart(event)
} else if (event.code === 'BUNDLE_END') {
this._bundleSecondEnd(event)
}
})
}
_bundleFirstStart(event: RollupWatcherEvent) { _bundleFirstStart(event: RollupWatcherEvent) {
this._firstStart = true this._firstStart = true
this._bundleStart(event) this._bundleStart(event)
...@@ -190,29 +216,3 @@ class AppWatcher { ...@@ -190,29 +216,3 @@ class AppWatcher {
} }
} }
} }
function initAppWatcher(
firstWatcher: RollupWatcher,
secondWatcher: RollupWatcher
) {
const appWatcher = new AppWatcher()
firstWatcher.on('event', (event) => {
if (event.code === 'BUNDLE_START') {
appWatcher._bundleFirstStart(event)
} else if (event.code === 'BUNDLE_END') {
appWatcher._bundleFirstEnd(event)
}
})
secondWatcher.on('event', (event) => {
if (event.code === 'BUNDLE_START') {
appWatcher._bundleSecondStart(event)
} else if (event.code === 'BUNDLE_END') {
appWatcher._bundleSecondEnd(event)
}
})
return {
on(_, fn) {
appWatcher.on(fn as (event: RollupWatcherEvent) => void)
},
} as RollupWatcher
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册