"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.uniAppPlugin = void 0; const path_1 = __importDefault(require("path")); const fs_extra_1 = __importDefault(require("fs-extra")); const shared_1 = require("@vue/shared"); const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared"); const utils_1 = require("./utils"); const manifestJson_1 = require("./manifestJson"); const utils_2 = require("../utils"); const uniCloudSpaceList = (0, utils_1.getUniCloudSpaceList)(); let isFirst = true; function uniAppPlugin() { const inputDir = process.env.UNI_INPUT_DIR; const outputDir = process.env.UNI_OUTPUT_DIR; // const uniModulesDir = normalizePath(path.resolve(inputDir, 'uni_modules')) const mainUTS = (0, uni_cli_shared_1.resolveMainPathOnce)(inputDir); const pagesJsonPath = (0, uni_cli_shared_1.normalizePath)(path_1.default.resolve(inputDir, 'pages.json')); const uvueOutputDir = (0, uni_cli_shared_1.uvueOutDir)('app-android'); const tscOutputDir = (0, uni_cli_shared_1.tscOutDir)('app-android'); const manifestJson = (0, uni_cli_shared_1.parseManifestJsonOnce)(inputDir); // 预留一个口子,方便切换测试 const split = manifestJson['uni-app-x']?.split; // 开始编译时,清空输出目录 function emptyOutDir() { // ext-api 编译时,需要同时编译多个平台,并保留多个平台的输出目录 if (process.env.UNI_COMPILE_TARGET === 'ext-api') { return; } if (fs_extra_1.default.existsSync(outputDir)) { (0, uni_cli_shared_1.emptyDir)(outputDir); } } emptyOutDir(); function emptyUVueDir() { if (fs_extra_1.default.existsSync(uvueOutputDir)) { (0, uni_cli_shared_1.emptyDir)(uvueOutputDir); } } emptyUVueDir(); function emptyTscDir() { if (fs_extra_1.default.existsSync(tscOutputDir)) { (0, uni_cli_shared_1.emptyDir)(tscOutputDir); } } emptyTscDir(); let resolvedConfig; const uniXKotlinCompiler = process.env.UNI_APP_X_TSC === 'true' ? (0, uni_cli_shared_1.resolveUTSCompiler)().createUniXKotlinCompilerOnce() : null; const changedFiles = []; return { name: 'uni:app-uts', apply: 'build', uni: (0, utils_2.createUniOptions)('android'), config() { return { base: '/', // 强制 base build: { // 手动清理 emptyOutDir: false, outDir: process.env.UNI_APP_X_TSC === 'true' ? tscOutputDir : uvueOutputDir, lib: { // 必须使用 lib 模式 fileName: 'output', entry: (0, uni_cli_shared_1.resolveMainPathOnce)(inputDir), formats: ['cjs'], }, rollupOptions: { external(source) { if (['vue', 'vuex', 'pinia', '@dcloudio/uni-app'].includes(source)) { return true; } // 相对目录 if (source.startsWith('@/') || source.startsWith('.')) { return false; } if (path_1.default.isAbsolute(source)) { return false; } // 'virtual:uno.css' if (source.includes(':')) { return false; } // android 系统库,三方库,iOS 的库呢?一般不包含. if (source.includes('.')) { return true; } return false; }, output: { chunkFileNames(chunk) { // if (chunk.isDynamicEntry && chunk.facadeModuleId) { // const { filename } = parseVueRequest(chunk.facadeModuleId) // if (filename.endsWith('.nvue')) { // return ( // removeExt( // normalizePath(path.relative(inputDir, filename)) // ) + '.js' // ) // } // } return '[name].js'; }, }, }, }, }; }, async configResolved(config) { (0, utils_2.configResolved)(config, true); resolvedConfig = config; if (uniXKotlinCompiler) { await uniXKotlinCompiler.init(); } }, async transform(code, id) { const { filename } = (0, uni_cli_shared_1.parseVueRequest)(id); if (!filename.endsWith('.uts') && !filename.endsWith('.ts')) { if (filename.endsWith('.json')) { this.emitFile({ type: 'asset', fileName: (0, uni_cli_shared_1.normalizeEmitAssetFileName)(normalizeFilename(id, false)), source: code, }); } return; } // 仅处理 uts 文件 // 忽略 uni-app-uts/lib/automator/index.uts if (!filename.includes('uni-app-uts')) { code = (await (0, utils_1.transformAutoImport)((0, utils_1.transformUniCloudMixinDataCom)((0, uni_cli_shared_1.rewriteUniModulesConsoleExpr)(id, code)), id)).code; const isMainUTS = (0, uni_cli_shared_1.normalizePath)(id) === mainUTS; this.emitFile({ type: 'asset', fileName: (0, uni_cli_shared_1.normalizeEmitAssetFileName)(normalizeFilename(id, isMainUTS)), source: normalizeCode(code, isMainUTS), }); } code = await (0, utils_1.parseImports)(code, (0, utils_1.createTryResolve)(id, this.resolve.bind(this))); return code; }, generateBundle(_, bundle) { if (!(0, uni_cli_shared_1.isNormalCompileTarget)()) { return; } // 开发者仅在 script 中引入了 easyCom 类型,但模板里边没用到,此时额外生成一个辅助的.uvue文件 // checkUTSEasyComAutoImports(inputDir, bundle, this) }, watchChange(fileName, change) { if (uniXKotlinCompiler) { // watcher && watcher.watch(3000) fileName = (0, uni_cli_shared_1.normalizePath)(fileName); if (fileName === pagesJsonPath) { // pages.json 被注入了main.uts,需要触发main.uts的重新编译 changedFiles.push({ fileName: (0, uni_cli_shared_1.normalizePath)(mainUTS), event: change.event, }); } else { // 主工程可能引入uni_modules中的文件 // if (fileName.startsWith(uniModulesDir)) { // // 忽略uni_modules uts原生插件中的文件 // const plugin = fileName // .slice(uniModulesDir.length + 1) // .split('/')[0] // if (getCurrentCompiledUTSPlugins().has(plugin)) { // return // } // } const depMap = (0, uni_cli_shared_1.getCssDepMap)(); if (depMap.has(fileName)) { for (const id of depMap.get(fileName)) { changedFiles.push({ fileName: id, event: change.event }); } } } changedFiles.push({ fileName, event: change.event }); } }, async writeBundle() { const { compileApp } = (0, uni_cli_shared_1.resolveUTSCompiler)(); if (!(0, uni_cli_shared_1.isNormalCompileTarget)()) { if (process.env.UNI_COMPILE_TARGET === 'ext-api') { if (uniXKotlinCompiler) { await uniXKotlinCompiler.addRootFile(path_1.default.join(tscOutputDir, 'main.uts.ts')); await uniXKotlinCompiler.close(); const res = await compileApp(path_1.default.join(uvueOutputDir, 'main.uts'), { pageCount: 0, split: false, disableSplitManifest: process.env.NODE_ENV !== 'development', inputDir: uvueOutputDir, outputDir: outputDir, outFilename: `${process.env.UNI_COMPILE_EXT_API_OUT_FILE_NAME || 'components'}.kt`, package: (0, uni_cli_shared_1.parseKotlinPackageWithPluginId)(process.env.UNI_COMPILE_EXT_API_PLUGIN_ID, true), sourceMap: false, uni_modules: [process.env.UNI_COMPILE_EXT_API_PLUGIN_ID], extApiComponents: [], uvueClassNamePrefix: utils_1.UVUE_CLASS_NAME_PREFIX, transform: { uvueClassNamePrefix: 'Uni', uvueClassNameOnlyBasename: true, }, }); if (res?.error) { throw res.error; } } } return; } if (uniXKotlinCompiler) { if (changedFiles.length) { const files = changedFiles.splice(0); await uniXKotlinCompiler.invalidate(files); } else if (isFirst) { await uniXKotlinCompiler.addRootFile(path_1.default.join(tscOutputDir, 'main.uts.ts')); } } let pageCount = 0; if (isFirst) { isFirst = false; // 自动化测试时,不显示页面数量进度条 // if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) { pageCount = parseInt(process.env.UNI_APP_X_PAGE_COUNT) || 0; // } } // x 上暂时编译所有uni ext api,不管代码里是否调用了 await (0, uni_cli_shared_1.buildUniExtApis)(); const uniCloudObjectInfo = (0, utils_1.getUniCloudObjectInfo)(uniCloudSpaceList); if (uniCloudObjectInfo.length > 0) { process.env.UNI_APP_X_UNICLOUD_OBJECT = 'true'; } else { process.env.UNI_APP_X_UNICLOUD_OBJECT = 'false'; } const res = await compileApp(path_1.default.join(uvueOutputDir, 'main.uts'), { pageCount, uniCloudObjectInfo, split: split !== false, disableSplitManifest: process.env.NODE_ENV !== 'development', inputDir: uvueOutputDir, outputDir: outputDir, package: 'uni.' + (manifestJson.appid || utils_1.DEFAULT_APPID).replace(/_/g, ''), sourceMap: (0, uni_cli_shared_1.enableSourceMap)(), uni_modules: [...(0, uni_cli_shared_1.getCurrentCompiledUTSPlugins)()], extApis: (0, uni_cli_shared_1.parseUniExtApiNamespacesOnce)(process.env.UNI_UTS_PLATFORM, process.env.UNI_UTS_TARGET_LANGUAGE), extApiComponents: [...(0, utils_2.getExtApiComponents)()], uvueClassNamePrefix: utils_1.UVUE_CLASS_NAME_PREFIX, autoImports: await (0, uni_cli_shared_1.initUTSKotlinAutoImportsOnce)(), extApiProviders: parseUniExtApiProviders(), uniModulesArtifacts: (0, uni_cli_shared_1.parseUniModulesArtifacts)(), env: parseProcessEnv(resolvedConfig), }); if (uniXKotlinCompiler && process.env.NODE_ENV !== 'development') { await uniXKotlinCompiler.close(); } if (res) { if (process.env.NODE_ENV === 'development') { const files = []; if (process.env.UNI_APP_UTS_CHANGED_FILES) { try { files.push(...JSON.parse(process.env.UNI_APP_UTS_CHANGED_FILES)); } catch (e) { } } if (res.changed) { // 触发了kotlinc编译,且没有编译成功 if (!res.changed.length && res.kotlinc) { throw new Error('编译失败'); } files.push(...res.changed); } process.env.UNI_APP_UTS_CHANGED_FILES = JSON.stringify([ ...new Set(files), ]); } else { // 生产环境,记录使用到的modules const modules = res.inject_modules; const manifest = (0, manifestJson_1.getOutputManifestJson)(); if (manifest) { // 执行了摇树逻辑,就需要设置 modules 节点 (0, utils_2.updateManifestModules)(manifest, modules); fs_extra_1.default.outputFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, 'manifest.json'), JSON.stringify(manifest, null, 2)); } } } }, }; } exports.uniAppPlugin = uniAppPlugin; function normalizeFilename(filename, isMain = false) { if (isMain) { return 'main.uts'; } return (0, utils_1.parseUTSRelativeFilename)(filename, process.env.UNI_INPUT_DIR); } function commentUnoCssImport(code) { // 使用正则表达式匹配 'import 'virtual:uno.css'' 语句 const regex = /^import\s+['"]virtual:uno\.css['"];?/gm; return code.replace(regex, '// $&'); } function normalizeCode(code, isMain = false) { code = commentUnoCssImport(code); if (!(0, uni_cli_shared_1.isNormalCompileTarget)()) { return code; } if (!isMain) { return code; } const automatorCode = process.env.UNI_AUTOMATOR_WS_ENDPOINT && process.env.UNI_AUTOMATOR_APP_WEBVIEW !== 'true' ? 'initAutomator();' : ''; return `${code} export function main(app: IApp) { definePageRoutes(); defineAppConfig(); ${automatorCode} (createApp()['app'] as VueApp).mount(app, ${utils_1.UVUE_CLASS_NAME_PREFIX}UniApp()); } `; } function parseUniExtApiProviders() { const providers = []; const customProviders = (0, uni_cli_shared_1.getUniExtApiProviderRegisters)(); customProviders.forEach((provider) => { providers.push([provider.service, provider.name, provider.class]); }); return providers; } function parseProcessEnv(resolvedConfig) { const env = {}; const defines = {}; const userDefines = resolvedConfig.define; Object.keys(userDefines).forEach((key) => { if (key.startsWith('process.env.')) { defines[key.replace('process.env.', '')] = userDefines[key]; } }); (0, shared_1.extend)(defines, resolvedConfig.env); Object.keys(defines).forEach((key) => { let value = defines[key]; if ((0, shared_1.isString)(value)) { try { value = JSON.parse(value); } catch (e) { } } if (!(0, shared_1.isString)(value)) { value = JSON.stringify(value); } env[key] = value; }); return env; }