"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;