363 lines
16 KiB
JavaScript
363 lines
16 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;
|
||
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;
|
||
}
|