375 lines
17 KiB
JavaScript
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;
|
|
}
|