You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compileCloudUniModuleWithTsc = exports.addUniModulesExtApiComponents = exports.uniEncryptUniModulesPlugin = exports.uniEncryptUniModulesAssetsPlugin = exports.createEncryptCssUrlReplacer = void 0;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const uni_modules_cloud_1 = require("../uni_modules.cloud");
const utils_1 = require("./plugins/vitejs/utils");
const uts_1 = require("../uts");
const utils_2 = require("../utils");
const easycom_1 = require("../easycom");
const uni_modules_1 = require("./plugins/uts/uni_modules");
const utils_3 = require("./utils");
const json_1 = require("../json");
const workers_1 = require("../workers");
function createEncryptCssUrlReplacer(resolve) {
return async (url, importer) => {
if (url.startsWith('/') && !url.startsWith('//')) {
// /static/logo.png => @/static/logo.png
url = '@' + url;
}
const resolved = await resolve(url, importer);
if (resolved) {
return ('@/' + (0, utils_2.normalizePath)(path_1.default.relative(process.env.UNI_INPUT_DIR, resolved)));
}
return url;
};
}
exports.createEncryptCssUrlReplacer = createEncryptCssUrlReplacer;
// 处理静态资源加载目前仅限非app-android
function uniEncryptUniModulesAssetsPlugin() {
let resolvedConfig;
return {
name: 'uni:encrypt-uni-modules-assets',
enforce: 'pre',
configResolved(config) {
resolvedConfig = config;
},
resolveId(id, importer) {
if (resolvedConfig.assetsInclude((0, utils_1.cleanUrl)(id))) {
id = (0, utils_2.normalizePath)(id);
if (importer && (id.startsWith('./') || id.startsWith('../'))) {
id = (0, utils_2.normalizePath)(path_1.default.resolve(path_1.default.dirname(importer), id));
}
if (path_1.default.isAbsolute(id)) {
id = '@/' + path_1.default.relative(process.env.UNI_INPUT_DIR, id);
}
return `\0${id}`;
}
},
load(id) {
if (resolvedConfig.assetsInclude((0, utils_1.cleanUrl)(id))) {
return {
code: `export default ${JSON.stringify(id.replace(/\0/g, ''))}`,
moduleSideEffects: false,
};
}
},
};
}
exports.uniEncryptUniModulesAssetsPlugin = uniEncryptUniModulesAssetsPlugin;
function uniEncryptUniModulesPlugin() {
let resolvedConfig;
const isMp = process.env.UNI_UTS_PLATFORM.startsWith('mp-');
const encryptModuleOutputFiles = [];
return {
name: 'uni:encrypt-uni-modules',
apply: 'build',
config() {
const build = initEncryptUniModulesBuildOptions(process.env.UNI_UTS_PLATFORM, process.env.UNI_INPUT_DIR);
Object.keys(build.rollupOptions?.input || {}).forEach((key) => {
encryptModuleOutputFiles.push(key + '.js');
});
return {
resolve: {
alias: initEncryptUniModulesAlias(),
},
build,
};
},
configResolved(config) {
const isMp = process.env.UNI_UTS_PLATFORM.startsWith('mp-');
if (isMp) {
// 云编译时禁用了lib:false但默认会生成 preload 等代码,需要主动移除该插件
(0, utils_3.removePlugins)(['vite:build-import-analysis'], config);
}
// 编译组件时,禁用内联资源
config.build.assetsInlineLimit = 0;
config.build.rollupOptions.external = createExternal(config);
resolvedConfig = config;
},
resolveId(id, importer) {
if (process.env.UNI_UTS_PLATFORM !== 'app-android') {
if (resolvedConfig.assetsInclude((0, utils_1.cleanUrl)(id))) {
id = (0, utils_2.normalizePath)(id);
if (importer && (id.startsWith('./') || id.startsWith('../'))) {
id = (0, utils_2.normalizePath)(path_1.default.resolve(path_1.default.dirname(importer), id));
}
if (path_1.default.isAbsolute(id)) {
id = '@/' + path_1.default.relative(process.env.UNI_INPUT_DIR, id);
}
return `\0${id}`;
}
}
},
load(id) {
if (process.env.UNI_UTS_PLATFORM !== 'app-android') {
if (resolvedConfig.assetsInclude((0, utils_1.cleanUrl)(id))) {
return {
code: `export default ${JSON.stringify(id.replace(/\0/g, ''))}`,
moduleSideEffects: false,
};
}
}
},
generateBundle(_, bundle) {
Object.keys(bundle).forEach((fileName) => {
if (fileName.endsWith('.module.js')) {
const uniModuleId = path_1.default.basename(fileName).replace('.module.js', '');
// app-android 不需要 js
if (process.env.UNI_UTS_PLATFORM !== 'app-android') {
const newFileName = 'uni_modules/' +
fileName.replace('.module.js', '/index.module.js');
bundle[newFileName] = bundle[fileName];
bundle[newFileName].fileName = newFileName;
}
delete bundle[fileName];
const pkg = `uni_modules/${uniModuleId}/package.json`;
bundle[pkg] = {
type: 'asset',
fileName: pkg,
name: pkg,
originalFileName: null,
needsCodeReference: false,
source: genUniModulesPackageJson(uniModuleId, process.env.UNI_INPUT_DIR, {
env: (0, uni_modules_cloud_1.initCheckEnv)(),
}),
};
}
else if (fileName.endsWith('.js')) {
if (isMp) {
const output = bundle[fileName];
if (output.type === 'chunk') {
// 组件 js 可能会引用 index.module.js需要替换路径
const relativePath = path_1.default.relative(path_1.default.dirname(fileName), 'index.module.js');
let code = output.code;
encryptModuleOutputFiles.forEach((file) => {
const relativeModulePath = relativePath.replace('index.module.js', file);
// import { TuiCharts } from "../../../../tui-xechars_2.0.0.module.js";
if (code.includes(relativeModulePath)) {
code = code.replaceAll(relativeModulePath, relativeModulePath
.replace('../../', '')
.replace(file, 'index.module.js'));
}
});
output.code = code;
}
}
}
});
if (isMp) {
(0, json_1.findChangedJsonFiles)(false).forEach((value, key) => {
this.emitFile({
type: 'asset',
fileName: key + '.json',
source: value,
});
});
}
},
async writeBundle() {
if (process.env.UNI_UTS_PLATFORM !== 'app-android') {
return;
}
const uniXKotlinCompiler = process.env.UNI_APP_X_TSC === 'true'
? (0, uts_1.resolveUTSCompiler)().createUniXKotlinCompilerOnce({
resolveWorkers: () => (0, workers_1.getWorkers)(),
})
: null;
if (uniXKotlinCompiler) {
const tscOutputDir = tscOutDir('app-android');
const uniModulesDir = path_1.default.resolve(tscOutputDir, 'uni_modules');
if (fs_extra_1.default.existsSync(uniModulesDir)) {
for (const plugin of fs_extra_1.default.readdirSync(uniModulesDir)) {
const indexFileName = path_1.default.join(uniModulesDir, plugin, 'index.module.uts.ts');
if (fs_extra_1.default.existsSync(indexFileName)) {
await uniXKotlinCompiler.addRootFile(indexFileName);
}
}
}
await uniXKotlinCompiler.close();
}
// 编译所有 uni_modules 插件
const tempOutputDir = uvueOutDir('app-android');
const tempUniModulesDir = path_1.default.join(tempOutputDir, 'uni_modules');
const tempUniModules = [];
if (fs_extra_1.default.existsSync(tempUniModulesDir)) {
fs_extra_1.default.readdirSync(tempUniModulesDir).forEach((uniModuleDir) => {
if (fs_extra_1.default.existsSync(path_1.default.join(tempUniModulesDir, uniModuleDir, 'index.module.uts'))) {
tempUniModules.push(uniModuleDir);
}
});
}
const compiler = (0, uts_1.resolveUTSCompiler)();
for (const uniModule of tempUniModules) {
const pluginDir = path_1.default.resolve(tempUniModulesDir, uniModule);
// TODO 待优化autoImports目前 uni-app x 的编译autoImport 是在js层处理过rust层基本不再使用
// 但uts插件目前还是使用的rust层的autoImports
const autoImports = {};
const allAutoImports = (0, easycom_1.getUTSEasyComAutoImports)();
Object.keys(allAutoImports).forEach((source) => {
if (!source.startsWith(`@/uni_modules/${uniModule}/components/`)) {
autoImports[source] = allAutoImports[source];
}
});
const uni_modules = [];
const pkgJson = path_1.default.resolve(process.env.UNI_INPUT_DIR, 'uni_modules', uniModule, 'package.json');
if (fs_extra_1.default.existsSync(pkgJson)) {
try {
const pkg = require(pkgJson);
if (pkg.uni_modules?.dependencies) {
uni_modules.push(...pkg.uni_modules.dependencies);
}
}
catch (e) {
console.error(e);
}
}
const result = await compiler.compile(pluginDir, {
isX: process.env.UNI_APP_X === 'true',
isSingleThread: true,
isPlugin: false,
sourceMap: false,
uni_modules,
transform: {
uvueClassNamePrefix: 'Gen',
autoImports,
uvueGenDefaultAs: '__sfc__',
},
});
if (result) {
const apis = result.inject_apis;
const scopedSlots = result.scoped_slots;
const customElements = result.custom_elements;
const components = getUniModulesExtApiComponents(uniModule);
const modules = (0, uts_1.resolveUTSCompiler)().parseInjectModules(apis, {}, components);
fs_extra_1.default.writeFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, 'uni_modules', uniModule, 'package.json'), genUniModulesPackageJson(uniModule, process.env.UNI_INPUT_DIR, {
env: (0, uni_modules_cloud_1.initCheckEnv)(),
apis,
components,
modules,
scopedSlots,
customElements,
}));
}
}
},
};
}
exports.uniEncryptUniModulesPlugin = uniEncryptUniModulesPlugin;
function tscOutDir(platform) {
return path_1.default.join(process.env.UNI_APP_X_TSC_DIR, platform);
}
function uvueOutDir(platform) {
return path_1.default.join(process.env.UNI_APP_X_UVUE_DIR, platform);
}
function createExternal(config) {
return function external(source) {
if ([
'vue',
'plugin-vue:export-helper',
'vue-router',
'pinia',
'vuex',
'vue-i18n',
'tslib',
].includes(source)) {
return true;
}
if (source.startsWith('@vue/')) {
return true;
}
if (source.startsWith('@dcloudio/')) {
return true;
}
if (source.startsWith('@/uni_modules/')) {
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;
};
}
function initEncryptUniModulesAlias() {
return [
{
find: '\0plugin-vue:export-helper',
replacement: 'plugin-vue:export-helper',
},
];
}
function initEncryptUniModulesBuildOptions(platform, inputDir) {
const modules = (0, uni_modules_cloud_1.parseUniModulesWithComponents)(inputDir, platform);
const moduleNames = Object.keys(modules);
if (!moduleNames.length) {
throw new Error('No encrypt uni_modules found');
}
// 生成入口文件
const input = {};
moduleNames.forEach((module) => {
const moduleDir = path_1.default.resolve(inputDir, 'uni_modules', module);
const indexEncryptFile = path_1.default.resolve(moduleDir, 'index.module.uts');
if (modules[module]) {
fs_extra_1.default.writeFileSync(indexEncryptFile, modules[module]);
// 输出 xxx.module ,确保相对路径的准确性,因为真正引用的时候,是从 @/uni_modules/xxx 引入的
input[module + '.module'] = indexEncryptFile;
}
});
return {
lib: false, // 不使用 lib 模式lib模式会直接内联资源
cssCodeSplit: false,
// outDir: process.env.UNI_OUTPUT_DIR,
rollupOptions: {
preserveEntrySignatures: 'strict',
input,
output: {
format: 'es',
banner: ``,
entryFileNames: '[name].js',
assetFileNames(asset) {
if (asset.name && path_1.default.isAbsolute(asset.name)) {
const uniModuleId = parseUniModuleId(path_1.default.relative(inputDir, asset.name));
if (uniModuleId) {
return `uni_modules/${uniModuleId}/assets/[name]-[hash][extname]`;
}
}
return 'assets/[name]-[hash][extname]';
},
},
},
};
}
function genUniModulesPackageJson(uniModuleId, inputDir, artifacts) {
const pkg = require(path_1.default.resolve(inputDir, path_1.default.join('uni_modules', uniModuleId, 'package.json')));
return JSON.stringify({
id: pkg.id,
version: pkg.version,
uni_modules: {
dependencies: pkg.uni_modules?.dependencies || [],
artifacts,
},
}, null, 2);
}
function parseUniModuleId(relativeFilename) {
const parts = (0, utils_2.normalizePath)(relativeFilename).split('/', 2);
if (parts[0] === 'uni_modules') {
return parts[1];
}
}
const uniModulesExtApiComponents = new Map();
function addUniModulesExtApiComponents(relativeFilename, components) {
const uniModuleId = parseUniModuleId(relativeFilename);
if (uniModuleId) {
let extApiComponents = uniModulesExtApiComponents.get(uniModuleId);
if (!extApiComponents) {
extApiComponents = new Set();
uniModulesExtApiComponents.set(uniModuleId, extApiComponents);
}
components.forEach((component) => extApiComponents.add(component));
}
}
exports.addUniModulesExtApiComponents = addUniModulesExtApiComponents;
function getUniModulesExtApiComponents(uniModuleId) {
return [...(uniModulesExtApiComponents.get(uniModuleId) || [])];
}
function compileCloudUniModuleWithTsc(platform, pluginDir) {
const { compileUniModuleWithTsc, createUniXKotlinCompilerOnce, createUniXSwiftCompilerOnce, createUniXArkTSCompilerOnce, } = (0, uts_1.resolveUTSCompiler)();
const isX = process.env.UNI_APP_X === 'true';
const resolveWorkers = () => (0, workers_1.getWorkers)();
return compileUniModuleWithTsc(platform, pluginDir, platform === 'app-android'
? createUniXKotlinCompilerOnce({ resolveWorkers })
: platform === 'app-harmony'
? createUniXArkTSCompilerOnce({ resolveWorkers })
: createUniXSwiftCompilerOnce({ resolveWorkers }), {
rootFiles: [],
preprocessor: platform === 'app-android'
? (0, uni_modules_1.createAppAndroidUniModulesSyncFilePreprocessorOnce)(isX)
: platform === 'app-harmony'
? (0, uni_modules_1.createAppHarmonyUniModulesSyncFilePreprocessorOnce)(isX)
: (0, uni_modules_1.createAppIosUniModulesSyncFilePreprocessorOnce)(isX),
});
}
exports.compileCloudUniModuleWithTsc = compileCloudUniModuleWithTsc;