@dcloudio/uni-cli-shared
Version:
uni-cli-shared
248 lines (228 loc) • 6.6 kB
JavaScript
const path = require('path')
const {
resolveUTSCompiler,
parseUniExtApiNamespacesOnce
} = require('./uts')
const {
parseUTSModuleDeps
} = require('./uni_modules')
const {
dataToEsm
} = require('./dataToEsm')
const {
getUniXKotlinCompiler,
getUniXSwiftCompiler,
getChangedFiles,
getUTSPlugins
} = require('./uts-webpack-plugin')
function createUniModulesSyncFilePreprocessor (
platform,
utsPlatform
) {
const initPreprocessContext = require('../preprocess')
const {
vueContext: preContext
} = initPreprocessContext(
platform,
global.uniPlugin.platforms
)
if (utsPlatform === 'app-android') {
preContext.APP_ANDROID = true
}
if (utsPlatform === 'app-ios') {
preContext.APP_IOS = true
}
const {
preprocess
} = require('@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/preprocess/lib/preprocess')
function preJs (jsCode) {
return preprocess(jsCode, preContext, {
type: 'js'
})
}
function preHtml (htmlCode) {
return preprocess(htmlCode, preContext, {
type: 'html'
})
}
return async (content, fileName) => {
const extname = path.extname(fileName)
if (extname === '.json') {
return dataToEsm(JSON.parse(preJs(content)), {
namedExports: true,
preferConst: true
})
} else if (extname === '.uts' || extname === '.ts') {
return preJs(content)
} else if (extname === '.uvue' || extname === '.vue') {
return preUTSSDKVueFile(fileName, preJs(preHtml(content)))
}
return content
}
}
function preUTSSDKVueFile (filename, content) {
if (
filename.includes('utssdk') &&
(filename.includes('app-android') || filename.includes('app-ios'))
) {
const {
parseComponent
} = require('vue-template-compiler')
const descriptor = parseComponent(content, {
sourceMap: false,
pad: 'line'
})
if (descriptor.script?.content) {
return (
descriptor.script.content +
// 补充 template 内容
`/*${descriptor.template?.content}*/`
)
}
return content
}
return content
}
function once (fn, ctx = null) {
let res
return (...args) => {
if (fn) {
res = fn.apply(ctx, args)
fn = null
}
return res
}
}
const createAppAndroidUniModulesSyncFilePreprocessorOnce = once(
() => {
return createUniModulesSyncFilePreprocessor('app', 'app-android')
}
)
const createAppIosUniModulesSyncFilePreprocessorOnce = once(
() => {
return createUniModulesSyncFilePreprocessor('app', 'app-ios')
}
)
module.exports = async function (content) {
const callback = this.async()
const uniXKotlinCompiler = getUniXKotlinCompiler()
const uniXSwiftCompiler = getUniXSwiftCompiler()
const {
syncUniModuleFilesByCompiler,
resolveTscUniModuleIndexFileName,
resolveTscUniModuleUTSSDKVueFileNames
} = resolveUTSCompiler()
const compilePlugin = async (pluginDir) => {
const pluginId = path.basename(pluginDir)
const utsPlugins = getUTSPlugins()
const changedFiles = getChangedFiles()
if (uniXKotlinCompiler) {
await uniXKotlinCompiler.init()
await syncUniModuleFilesByCompiler(
'app-android',
uniXKotlinCompiler,
pluginDir,
createAppAndroidUniModulesSyncFilePreprocessorOnce()
)
}
if (uniXSwiftCompiler) {
await uniXSwiftCompiler.init()
await syncUniModuleFilesByCompiler(
'app-ios',
uniXSwiftCompiler,
pluginDir,
createAppIosUniModulesSyncFilePreprocessorOnce()
)
}
// 不判重了,不然nvue,vue并发同一个插件时,其中一个会跳过tsc编译,直接走到rust那里,导致一些文件还没有生成,比如vue兼容模式组件之类的
// if (!utsPlugins.has(pluginId)) {
utsPlugins.add(pluginId)
if (uniXKotlinCompiler) {
const platform = 'app-android'
const vueFiles = resolveTscUniModuleUTSSDKVueFileNames(
platform,
pluginDir
)
for (const vueFile of vueFiles) {
await uniXKotlinCompiler.addRootFile(vueFile)
}
const indexFileName = resolveTscUniModuleIndexFileName(
platform,
pluginDir
)
if (indexFileName) {
await uniXKotlinCompiler.addRootFile(indexFileName)
}
}
if (uniXSwiftCompiler) {
const platform = 'app-ios'
const vueFiles = resolveTscUniModuleUTSSDKVueFileNames(
platform,
pluginDir
)
for (const vueFile of vueFiles) {
await uniXSwiftCompiler.addRootFile(vueFile)
}
const indexFileName = resolveTscUniModuleIndexFileName(
platform,
pluginDir
)
if (indexFileName) {
await uniXSwiftCompiler.addRootFile(indexFileName)
}
}
// }
// 处理uni_modules中的文件变更
const files = changedFiles.get(pluginId)
if (files) {
// 仅限watch模式是会生效
changedFiles.delete(pluginId)
if (uniXKotlinCompiler) {
await uniXKotlinCompiler.invalidate(files)
}
if (uniXSwiftCompiler) {
await uniXSwiftCompiler.invalidate(files)
}
}
const pkgJson = require(path.join(pluginDir, 'package.json'))
const compiler = resolveUTSCompiler()
// 处理依赖的 uts 插件
const deps = parseUTSModuleDeps(
pkgJson.uni_modules?.dependencies || [],
process.env.UNI_INPUT_DIR
)
if (deps.length) {
for (const dep of deps) {
await compilePlugin(
path.resolve(process.env.UNI_INPUT_DIR, 'uni_modules', dep)
)
}
}
return compiler.compile(pluginDir, {
isX: false,
isPlugin: true,
extApis: parseUniExtApiNamespacesOnce(
process.env.UNI_UTS_PLATFORM,
process.env.UNI_UTS_TARGET_LANGUAGE
),
sourceMap: process.env.NODE_ENV === 'development',
uni_modules: deps
// 暂不提供
// async kotlinAutoImports() {}
// async swiftAutoImports() {}
})
}
const pluginDir = path.dirname(this.resourcePath)
compilePlugin(pluginDir).then(result => {
if (result) {
result.deps.forEach((dep) => {
this.addDependency(dep)
})
callback(null, result.code)
} else {
callback(null, '')
}
}).catch(err => {
callback(err)
})
}