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.

281 lines
12 KiB

2 months ago
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initUniXCompilerRootWorkers = exports.uniJavaScriptWorkersPlugin = exports.resolveWorkersDir = exports.uniWorkersPlugin = exports.initWorkers = exports.getWorkersRootDirs = exports.resolveWorkersRootDir = exports.getWorkers = void 0;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const debug_1 = __importDefault(require("debug"));
const fast_glob_1 = require("fast-glob");
const utils_1 = require("./utils");
const json_1 = require("./json");
const uts_1 = require("./uts");
const uni_modules_1 = require("./vite/plugins/uts/uni_modules");
const resolve_1 = require("./resolve");
const debugWorkers = (0, debug_1.default)('uni:workers');
let workersRootDir = null;
let workersRootDirs = [];
let workers = {};
function getWorkers() {
return workers;
}
exports.getWorkers = getWorkers;
function resolveWorkersRootDir() {
// 默认是 workers
return workersRootDir || 'workers';
}
exports.resolveWorkersRootDir = resolveWorkersRootDir;
function getWorkersRootDirs() {
return workersRootDirs;
}
exports.getWorkersRootDirs = getWorkersRootDirs;
/**
* 遍历目录下的所有uts文件读取文件内容正则匹配出定义的worker返回文件名和类名的映射关系
* export class MyWorkerTask extends WorkerTaskImpl {}
* @param dir
*/
function initWorkers(workersDirs, rootDir) {
workers = {};
for (const workersDir of workersDirs) {
const dir = path_1.default.join(rootDir, workersDir);
if (!fs_extra_1.default.existsSync(dir)) {
continue;
}
(0, fast_glob_1.sync)('**/*.uts', { cwd: dir }).forEach((file) => {
const content = fs_extra_1.default.readFileSync(path_1.default.join(dir, file), 'utf-8');
const match = content.match(/class\s+(.*)\s+extends\s+WorkerTaskImpl/);
if (match && match[1]) {
const key = (0, utils_1.normalizePath)(path_1.default.join(workersDir, file));
workers[key] = match[1];
}
});
}
debugWorkers('workers', workers);
return workers;
}
exports.initWorkers = initWorkers;
function uniWorkersPlugin() {
const inputDir = process.env.UNI_INPUT_DIR;
const platform = process.env.UNI_UTS_PLATFORM;
const resolveWorkers = () => getWorkers();
function refreshWorkers() {
workersRootDirs = resolveWorkersDir(inputDir);
initWorkers(workersRootDirs, inputDir);
return Object.keys(getWorkers()).length > 0;
}
refreshWorkers();
const preprocessor = platform === 'app-android'
? (0, uni_modules_1.createAppAndroidUniModulesSyncFilePreprocessorOnce)(false)
: platform === 'app-ios'
? (0, uni_modules_1.createAppIosUniModulesSyncFilePreprocessorOnce)(false)
: platform === 'app-harmony'
? (0, uni_modules_1.createAppHarmonyUniModulesSyncFilePreprocessorOnce)(false)
: null;
const cache = {};
const uniXKotlinCompiler = platform === 'app-android'
? (0, uts_1.resolveUTSCompiler)().createUniXKotlinCompilerOnce({
resolveWorkers,
})
: null;
const uniXSwiftCompiler = platform === 'app-ios'
? (0, uts_1.resolveUTSCompiler)().createUniXSwiftCompilerOnce({
resolveWorkers,
})
: null;
const uniXArkTSCompiler = platform === 'app-harmony'
? (0, uts_1.resolveUTSCompiler)().createUniXArkTSCompilerOnce({
resolveWorkers,
})
: null;
return {
name: 'uni-workers',
enforce: 'pre',
async buildStart() {
if (refreshWorkers()) {
if (preprocessor) {
await syncWorkersFiles(platform, inputDir, preprocessor, cache);
}
}
// 需要等待 workers 文件同步完之后,添加到 rootFiles 中,触发 tsc 的编译
if (uniXKotlinCompiler) {
await initUniXCompilerRootWorkers((0, uts_1.tscOutDir)('app-android'), uniXKotlinCompiler);
}
if (uniXSwiftCompiler) {
await initUniXCompilerRootWorkers((0, uts_1.tscOutDir)('app-ios'), uniXSwiftCompiler);
}
if (uniXArkTSCompiler) {
await initUniXCompilerRootWorkers((0, uts_1.tscOutDir)('app-harmony'), uniXArkTSCompiler);
}
},
};
}
exports.uniWorkersPlugin = uniWorkersPlugin;
async function syncWorkersFiles(platform, inputDir, preprocessor, cache) {
if (platform !== 'app-harmony' &&
platform !== 'app-android' &&
platform !== 'app-ios') {
return;
}
const workersDirs = resolveWorkersDir(inputDir);
if (workersDirs.length) {
const { syncUTSFiles } = (0, uts_1.resolveUTSCompiler)();
for (const workersDir of workersDirs) {
await syncUTSFiles((0, utils_1.normalizePath)(path_1.default.join(workersDir, '**/*.uts')), inputDir, (0, uts_1.tscOutDir)(platform), true, preprocessor, cache);
}
}
}
function resolveWorkersDir(inputDir) {
const workersDirs = [];
const manifestJson = (0, json_1.parseManifestJsonOnce)(inputDir);
if (manifestJson.workers) {
let workersDir = typeof manifestJson.workers === 'string'
? manifestJson.workers
: manifestJson.workers.path;
if (workersDir) {
workersDir = (0, utils_1.normalizePath)(workersDir);
const dir = path_1.default.join(inputDir, workersDir);
if (fs_extra_1.default.existsSync(dir)) {
workersRootDir = workersDir;
workersDirs.push(workersDir);
}
}
}
// 遍历uni_modules插件目录是否有workers目录
const uniModulesDir = path_1.default.join(inputDir, 'uni_modules');
if (fs_extra_1.default.existsSync(uniModulesDir)) {
fs_extra_1.default.readdirSync(uniModulesDir).forEach((dir) => {
if (fs_extra_1.default.existsSync(path_1.default.join(uniModulesDir, dir, 'workers'))) {
workersDirs.push('uni_modules/' + dir + '/workers');
}
});
}
debugWorkers('workersDirs', workersDirs);
return workersDirs;
}
exports.resolveWorkersDir = resolveWorkersDir;
function uniJavaScriptWorkersPlugin() {
// 仅小程序平台外置uni-worker.mp.js
const external = (process.env.UNI_UTS_PLATFORM || '').startsWith('mp-');
let workerPolyfillCode = '';
let isWrite = false;
const UniAppWorkerJSName = external ? 'uni-worker.mp.js' : 'uni-worker.web.js';
let viteServer = null;
const workersRootPaths = [];
const workerPolyfillPath = `@dcloudio/uni-app/dist-x/${UniAppWorkerJSName}`;
const workerPolyfillAbsPath = (0, utils_1.normalizePath)((0, resolve_1.resolveBuiltIn)(workerPolyfillPath));
function isWorkerFile(id) {
if (workersRootPaths.length) {
return workersRootPaths.some((dir) => id.startsWith(dir));
}
return false;
}
function parseWorkerEntryFile(workerJsPath) {
const workerPath = workerJsPath.slice(1).replace('.js', '.uts');
if (workerPath in workers) {
return (0, utils_1.normalizePath)(path_1.default.resolve(process.env.UNI_INPUT_DIR, workerPath));
}
}
function parseWorkerClass(id) {
const filename = id.split('?')[0];
if (isWorkerFile(filename)) {
const workerPath = (0, utils_1.normalizePath)(path_1.default.relative(process.env.UNI_INPUT_DIR, filename));
return workers[workerPath] || '';
}
return false;
}
return {
name: 'uni:javascript-workers',
configureServer(server) {
viteServer = server;
},
buildStart() {
if (!workerPolyfillCode && Object.keys(getWorkers()).length) {
workerPolyfillCode = fs_extra_1.default.readFileSync(workerPolyfillAbsPath, 'utf-8');
}
workersRootPaths.length = 0;
for (const workersRootDir of getWorkersRootDirs()) {
workersRootPaths.push((0, utils_1.normalizePath)(path_1.default.resolve(process.env.UNI_INPUT_DIR, workersRootDir)));
}
},
resolveId(id) {
// uni.createWorker('workers/request/index.uts')
// 编译阶段调整为 uni.createWorker('workers/request/index.js'),确保开发和运行时都是用.js后缀加载
// 不调整成js后缀或.uts?import这些格式 vite 是不会走transform逻辑的而是直接读取文件内容
if (viteServer) {
const workerEntryFile = parseWorkerEntryFile(id);
if (workerEntryFile) {
return workerEntryFile;
}
if (id === workerPolyfillPath) {
return workerPolyfillAbsPath;
}
}
},
load(id) {
const filename = id.split('?')[0];
const workerClass = parseWorkerClass(filename);
if (workerClass === false) {
return;
}
if (fs_extra_1.default.existsSync(filename)) {
let code = (viteServer ? `import '${workerPolyfillPath}';` : '') +
fs_extra_1.default
.readFileSync(filename, 'utf-8')
// 移除 export
.replace(/export\s+class\s+(.*)\s+extends\s+WorkerTaskImpl\s*{/, 'class $1 extends WorkerTaskImpl {');
// 如果是入口文件,需要追加初始化代码
if (workerClass) {
code += `\n;new ${workerClass}().entry()`;
}
return code;
}
},
generateBundle(_, bundle) {
const workers = getWorkers();
const workerRootDir = resolveWorkersRootDir();
const workerPaths = Object.keys(workers).map((key) => {
if (key.startsWith('uni_modules')) {
key = workerRootDir + '/' + key;
}
return key.replace('.uts', '.js');
});
if (workerPaths.length) {
Object.keys(bundle).forEach((file) => {
if (workerPaths.includes(file)) {
const chunk = bundle[file];
if (chunk.type === 'chunk') {
const workerCode = external
? `require('${(0, utils_1.normalizePath)(path_1.default.relative(path_1.default.dirname(file), path_1.default.join(resolveWorkersRootDir(), 'uni-worker.js')))}')`
: workerPolyfillCode;
chunk.code = `${workerCode}\n${chunk.code}`;
}
}
});
}
},
writeBundle() {
if (external && Object.keys(getWorkers()).length && !isWrite) {
isWrite = true;
// 写入uni-worker.js
fs_extra_1.default.outputFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, resolveWorkersRootDir(), 'uni-worker.js'), workerPolyfillCode);
}
},
};
}
exports.uniJavaScriptWorkersPlugin = uniJavaScriptWorkersPlugin;
async function initUniXCompilerRootWorkers(rootDir, compiler) {
const workers = getWorkers();
if (Object.keys(workers).length) {
for (const key in workers) {
const file = path_1.default.join(rootDir, key + '.ts');
if (fs_extra_1.default.existsSync(file)) {
if (!compiler.hasRootFile(file)) {
await compiler.addRootFile(file);
}
}
}
}
}
exports.initUniXCompilerRootWorkers = initUniXCompilerRootWorkers;