plugin.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.uniAppPlugin = void 0;
  7. const path_1 = __importDefault(require("path"));
  8. const fs_extra_1 = __importDefault(require("fs-extra"));
  9. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  10. const utils_1 = require("./utils");
  11. const manifestJson_1 = require("./manifestJson");
  12. const utils_2 = require("../utils");
  13. const __1 = require("../..");
  14. const uniCloudSpaceList = (0, utils_1.getUniCloudSpaceList)();
  15. let isFirst = true;
  16. function uniAppPlugin() {
  17. const inputDir = process.env.UNI_INPUT_DIR;
  18. const outputDir = process.env.UNI_OUTPUT_DIR;
  19. const mainUTS = (0, uni_cli_shared_1.resolveMainPathOnce)(inputDir);
  20. const tempOutputDir = (0, utils_1.uvueOutDir)();
  21. const manifestJson = (0, uni_cli_shared_1.parseManifestJsonOnce)(inputDir);
  22. // 预留一个口子,方便切换测试
  23. const split = manifestJson['uni-app-x']?.split;
  24. // 开始编译时,清空输出目录
  25. function emptyOutDir() {
  26. if (fs_extra_1.default.existsSync(outputDir)) {
  27. (0, uni_cli_shared_1.emptyDir)(outputDir);
  28. }
  29. }
  30. emptyOutDir();
  31. return {
  32. name: 'uni:app-uts',
  33. apply: 'build',
  34. uni: (0, utils_2.createUniOptions)('android'),
  35. config() {
  36. return {
  37. base: '/',
  38. build: {
  39. outDir: tempOutputDir,
  40. lib: {
  41. // 必须使用 lib 模式
  42. fileName: 'output',
  43. entry: (0, uni_cli_shared_1.resolveMainPathOnce)(inputDir),
  44. formats: ['cjs'],
  45. },
  46. rollupOptions: {
  47. external(source) {
  48. if (['vue', 'vuex', 'pinia', '@dcloudio/uni-app'].includes(source)) {
  49. return true;
  50. }
  51. // 相对目录
  52. if (source.startsWith('@/') || source.startsWith('.')) {
  53. return false;
  54. }
  55. if (path_1.default.isAbsolute(source)) {
  56. return false;
  57. }
  58. // android 系统库,三方库
  59. if (source.includes('.')) {
  60. return true;
  61. }
  62. return false;
  63. },
  64. output: {
  65. chunkFileNames(chunk) {
  66. // if (chunk.isDynamicEntry && chunk.facadeModuleId) {
  67. // const { filename } = parseVueRequest(chunk.facadeModuleId)
  68. // if (filename.endsWith('.nvue')) {
  69. // return (
  70. // removeExt(
  71. // normalizePath(path.relative(inputDir, filename))
  72. // ) + '.js'
  73. // )
  74. // }
  75. // }
  76. return '[name].js';
  77. },
  78. },
  79. },
  80. },
  81. };
  82. },
  83. configResolved(config) {
  84. (0, utils_2.configResolved)(config, true);
  85. },
  86. async transform(code, id) {
  87. if (process.env.UNI_APP_X_TSC === 'true') {
  88. return;
  89. }
  90. const { filename } = (0, uni_cli_shared_1.parseVueRequest)(id);
  91. if (!filename.endsWith('.uts') && !filename.endsWith('.ts')) {
  92. return;
  93. }
  94. // 仅处理 uts 文件
  95. // 忽略 uni-app-uts/lib/automator/index.uts
  96. if (!filename.includes('uni-app-uts')) {
  97. const isMainUTS = (0, uni_cli_shared_1.normalizePath)(id) === mainUTS;
  98. const fileName = path_1.default.relative(inputDir, id);
  99. this.emitFile({
  100. type: 'asset',
  101. fileName: normalizeFilename(fileName, isMainUTS),
  102. source: normalizeCode(code, isMainUTS),
  103. });
  104. }
  105. code = await (0, utils_1.parseImports)(code, (0, utils_1.createTryResolve)(id, this.resolve.bind(this)));
  106. return code;
  107. },
  108. generateBundle(_, bundle) {
  109. // 开发者仅在 script 中引入了 easyCom 类型,但模板里边没用到,此时额外生成一个辅助的.uvue文件
  110. checkUTSEasyComAutoImports(inputDir, bundle, this);
  111. },
  112. async writeBundle() {
  113. let pageCount = 0;
  114. if (isFirst) {
  115. isFirst = false;
  116. // 自动化测试时,不显示页面数量进度条
  117. if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
  118. pageCount = parseInt(process.env.UNI_APP_X_PAGE_COUNT) || 0;
  119. }
  120. }
  121. await (0, uni_cli_shared_1.buildUniExtApiProviders)();
  122. const res = await (0, uni_cli_shared_1.resolveUTSCompiler)().compileApp(path_1.default.join(tempOutputDir, 'main.uts'), {
  123. pageCount,
  124. uniCloudObjectInfo: (0, utils_1.getUniCloudObjectInfo)(uniCloudSpaceList),
  125. split: split !== false,
  126. disableSplitManifest: process.env.NODE_ENV !== 'development',
  127. inputDir: tempOutputDir,
  128. outputDir: outputDir,
  129. package: 'uni.' + (manifestJson.appid || utils_1.DEFAULT_APPID).replace(/_/g, ''),
  130. sourceMap: process.env.NODE_ENV === 'development',
  131. uni_modules: [...uni_cli_shared_1.utsPlugins],
  132. extApis: (0, uni_cli_shared_1.parseUniExtApiNamespacesOnce)(process.env.UNI_UTS_PLATFORM, process.env.UNI_UTS_TARGET_LANGUAGE),
  133. extApiComponents: [...(0, utils_1.getExtApiComponents)()],
  134. uvueClassNamePrefix: utils_1.UVUE_CLASS_NAME_PREFIX,
  135. autoImports: (0, uni_cli_shared_1.getUTSEasyComAutoImports)(),
  136. });
  137. if (res) {
  138. if (process.env.NODE_ENV === 'development') {
  139. const files = [];
  140. if (process.env.UNI_APP_UTS_CHANGED_FILES) {
  141. try {
  142. files.push(...JSON.parse(process.env.UNI_APP_UTS_CHANGED_FILES));
  143. }
  144. catch (e) { }
  145. }
  146. if (res.changed) {
  147. // 触发了kotlinc编译,且没有编译成功
  148. if (!res.changed.length && res.kotlinc) {
  149. throw new Error('编译失败');
  150. }
  151. files.push(...res.changed);
  152. }
  153. process.env.UNI_APP_UTS_CHANGED_FILES = JSON.stringify([
  154. ...new Set(files),
  155. ]);
  156. }
  157. else {
  158. // 生产环境,记录使用到的modules
  159. const modules = res.inject_modules;
  160. const manifest = (0, manifestJson_1.getOutputManifestJson)();
  161. if (manifest) {
  162. // 执行了摇树逻辑,就需要设置 modules 节点
  163. const app = manifest.app;
  164. if (!app.distribute) {
  165. app.distribute = {};
  166. }
  167. if (!app.distribute.modules) {
  168. app.distribute.modules = {};
  169. }
  170. if (modules) {
  171. modules.forEach((name) => {
  172. const value = app.distribute.modules[name];
  173. app.distribute.modules[name] =
  174. typeof value === 'object' && value !== null ? value : {};
  175. });
  176. }
  177. fs_extra_1.default.outputFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, 'manifest.json'), JSON.stringify(manifest, null, 2));
  178. }
  179. }
  180. }
  181. },
  182. };
  183. }
  184. exports.uniAppPlugin = uniAppPlugin;
  185. function normalizeFilename(filename, isMain = false) {
  186. if (isMain) {
  187. return 'main.uts';
  188. }
  189. return (0, utils_1.parseUTSRelativeFilename)(filename);
  190. }
  191. function normalizeCode(code, isMain = false) {
  192. if (!isMain) {
  193. return code;
  194. }
  195. const automatorCode = process.env.UNI_AUTOMATOR_WS_ENDPOINT &&
  196. process.env.UNI_AUTOMATOR_APP_WEBVIEW !== 'true'
  197. ? 'initAutomator();'
  198. : '';
  199. return `${code}
  200. export function main(app: IApp) {
  201. definePageRoutes();
  202. defineAppConfig();
  203. ${automatorCode}
  204. (createApp()['app'] as VueApp).mount(app);
  205. }
  206. `;
  207. }
  208. function checkUTSEasyComAutoImports(inputDir, bundle, ctx) {
  209. const res = (0, uni_cli_shared_1.getUTSEasyComAutoImports)();
  210. Object.keys(res).forEach((fileName) => {
  211. if (fileName.endsWith('.vue') || fileName.endsWith('.uvue')) {
  212. if (fileName.startsWith('@/')) {
  213. fileName = fileName.slice(2);
  214. }
  215. const relativeFileName = (0, utils_1.parseUTSRelativeFilename)(fileName, inputDir);
  216. if (!bundle[relativeFileName]) {
  217. const className = (0, __1.genClassName)(relativeFileName, utils_1.UVUE_CLASS_NAME_PREFIX);
  218. ctx.emitFile({
  219. type: 'asset',
  220. fileName: relativeFileName,
  221. source: `function ${className}Render(): any | null { return null }
  222. const ${className}Styles = []`,
  223. });
  224. }
  225. }
  226. });
  227. return res;
  228. }