@vnxjs/service
Version:
Vnmf Service
220 lines (189 loc) • 6.45 kB
text/typescript
import type { RecursiveTemplate, UnRecursiveTemplate } from '@vnxjs/shared/dist/template'
import type { IPluginContext } from '../types/index'
interface IFileType {
templ: string
style: string
config: string
script: string
xs?: string
}
interface IWrapper {
init? (): void
close? (): void
}
class Transaction {
wrappers: IWrapper[] = []
async perform (fn: (...args: any[]) => void, scope: VnmfPlatformBase, ...args) {
this.initAll(scope)
await fn.call(scope, ...args)
this.closeAll(scope)
}
initAll (scope) {
const wrappers = this.wrappers
wrappers.forEach(wrapper => wrapper.init?.call(scope))
}
closeAll (scope) {
const wrappers = this.wrappers
wrappers.forEach(wrapper => wrapper.close?.call(scope))
}
addWrapper (wrapper: IWrapper) {
this.wrappers.push(wrapper)
}
}
export abstract class VnmfPlatformBase {
ctx: IPluginContext
helper: IPluginContext['helper']
config: any
compiler: string
abstract platform: string
abstract globalObject: string
abstract runtimePath: string | string[]
abstract fileType: IFileType
abstract template: RecursiveTemplate | UnRecursiveTemplate
projectConfigJson?: string
vnmfComponentsPath?: string
setupTransaction = new Transaction()
buildTransaction = new Transaction()
constructor (ctx: IPluginContext, config) {
this.ctx = ctx
this.helper = ctx.helper
this.config = config
const _compiler = config.compiler
this.compiler = typeof _compiler === 'object' ? _compiler.type : _compiler
}
/**
* 1. Empty dist Folder
* 2. Output compile hint
* 3. Generate project.config.json
*/
private async setup () {
await this.setupTransaction.perform(this.setupImpl, this)
this.ctx.onSetupClose?.(this)
}
private setupImpl () {
const { needClearOutput } = this.config
if (typeof needClearOutput === 'undefined' || !!needClearOutput) {
this.emptyOutputDir()
}
this.printDevelopmentTip(this.platform)
if (this.projectConfigJson) {
this.generateProjectConfig(this.projectConfigJson)
}
if (this.ctx.initialConfig.logger?.quiet === false) {
const { printLog, processTypeEnum } = this.ctx.helper
printLog(processTypeEnum.START, 'Developer Tool-Project Directory', `${this.ctx.paths.outputPath}`)
}
}
protected emptyOutputDir () {
const { outputPath } = this.ctx.paths
this.helper.emptyDirectory(outputPath)
}
protected printDevelopmentTip (platform: string) {
const tips: string[] = []
const config = this.config
const { chalk } = this.helper
if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
const { isWindows } = this.helper
const exampleCommand = isWindows
? `$ set NODE_ENV=production && vnmf build --type ${platform} --watch`
: `$ NODE_ENV=production vnmf build --type ${platform} --watch`
tips.push(chalk.yellowBright(`Larger files generated by preview mode,Settings NODE_ENV Yes. production You can turn on the compression.。
Example:
${exampleCommand}`))
}
if (this.compiler === 'webpack5' && !config.cache?.enable) {
tips.push(chalk.yellowBright('It\'s recommended to start the durability cache.,It\'s an effective way to increase the speed of secondary editing.,Please refer to the details.: https://docs.vnmf.zone/docs/config-detail#cache。'))
}
if (tips.length) {
console.log(chalk.yellowBright('Tips:'))
tips.forEach((item, index) => console.log(`${chalk.yellowBright(index + 1)}. ${item}`))
console.log('\n')
}
}
/**
* Return to the current item @vnxjs/mini-runner Bag.
*/
protected async getRunner () {
const { appPath } = this.ctx.paths
const { npm } = this.helper
let runnerPkg: string
switch (this.compiler) {
case 'webpack5':
runnerPkg = '@vnxjs/webpack5-runner'
break
default:
runnerPkg = '@vnxjs/mini-runner'
}
const runner = await npm.getNpmPkg(runnerPkg, appPath)
return runner.bind(null, appPath)
}
/**
* Ready. mini-runner Parameters
* @param extraOptions Could not close temporary folder: %s Options Configuration entry
*/
protected getOptions (extraOptions = {}) {
const { ctx, config, globalObject, fileType, template } = this
return {
...config,
nodeModulesPath: ctx.paths.nodeModulesPath,
buildAdapter: config.platform,
globalObject,
fileType,
template,
...extraOptions
}
}
/**
* Call mini-runner Commence compilation.
* @param extraOptions Could not close temporary folder: %s @vnxjs/mini-runner Configuration entry
*/
private async build (extraOptions = {}) {
this.ctx.onBuildInit?.(this)
await this.buildTransaction.perform(this.buildImpl, this, extraOptions)
}
private async buildImpl (extraOptions) {
const runner = await this.getRunner()
const options = this.getOptions(Object.assign({
runtimePath: this.runtimePath,
vnmfComponentsPath: this.vnmfComponentsPath
}, extraOptions))
await runner(options)
}
/**
* Generate project.config.json
* @param src Name of the profile in project source
* @param dist Name of the compiled configuration file,Default As 'project.config.json'
*/
protected generateProjectConfig (src: string, dist = 'project.config.json') {
if (this.config.isBuildNativeComp) return
this.ctx.generateProjectConfig({
srcConfigName: src,
distConfigName: dist
})
}
/**
* Recursively replace object key Value
*/
protected recursiveReplaceObjectKeys (obj, keyMap) {
Object.keys(obj).forEach(key => {
if (keyMap[key]) {
obj[keyMap[key]] = obj[key]
if (typeof obj[key] === 'object') {
this.recursiveReplaceObjectKeys(obj[keyMap[key]], keyMap)
}
delete obj[key]
} else if (keyMap[key] === false) {
delete obj[key]
} else if (typeof obj[key] === 'object') {
this.recursiveReplaceObjectKeys(obj[key], keyMap)
}
})
}
/**
* Call mini-runner Turn on the compiler.
*/
public async start () {
await this.setup()
await this.build()
}
}