Files
2026-08-11 17:41:36 +08:00

375 lines
17 KiB
JavaScript

"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;
let isFirstBundleSuccess = false;
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)('app-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,
map: {
mappings: '',
},
};
},
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) {
// 如果 main.uts.ts 没有被添加到 uniXKotlinCompiler 中,则添加
// 有可能首次编译失败,并没有走到这里,二次编译导致了changedFiles有内容
const mainFile = path_1.default.join(tscOutputDir, 'main.uts.ts');
if (!uniXKotlinCompiler.hasRootFile(mainFile)) {
await uniXKotlinCompiler.addRootFile(mainFile);
}
if (changedFiles.length) {
const files = changedFiles.splice(0);
await uniXKotlinCompiler.invalidate(files);
}
}
let pageCount = 0;
if (isFirst) {
isFirst = false;
}
// 首次编译成功后,不再显示页面数量进度条
if (!isFirstBundleSuccess) {
// 自动化测试时,不显示页面数量进度条
// 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));
}
}
}
isFirstBundleSuccess = true;
},
};
}
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();\n'
: '';
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;
}