main.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.transformMain = void 0;
  4. const source_map_js_1 = require("source-map-js");
  5. const trace_mapping_1 = require("@jridgewell/trace-mapping");
  6. const gen_mapping_1 = require("@jridgewell/gen-mapping");
  7. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  8. const descriptorCache_1 = require("../descriptorCache");
  9. const script_1 = require("./script");
  10. const utils_1 = require("../../utils");
  11. const template_1 = require("../code/template");
  12. const template_2 = require("./template");
  13. async function transformMain(code, filename, options, pluginContext, // 该 transformMain 方法被vuejs-core使用,编译框架内置组件了,此时不会传入pluginContext
  14. isAppVue = false) {
  15. if (!options.compiler) {
  16. options.compiler = require('@vue/compiler-sfc');
  17. }
  18. const { descriptor, errors } = (0, descriptorCache_1.createDescriptor)(filename, code, options);
  19. const relativeFilename = descriptor.relativeFilename;
  20. if (errors.length) {
  21. if (pluginContext) {
  22. errors.forEach((error) => pluginContext.error((0, uni_cli_shared_1.createRollupError)('', filename, error, code)));
  23. }
  24. return null;
  25. }
  26. const className = (0, uni_cli_shared_1.genUTSClassName)(relativeFilename, options.classNamePrefix);
  27. // script
  28. const { code: scriptCode, map: scriptMap, bindingMetadata, } = await genScriptCode(descriptor, {
  29. ...options,
  30. className,
  31. });
  32. let templatePreambleCode = undefined;
  33. let templateCode = '';
  34. let templateMap = undefined;
  35. let templateImportsCode = '';
  36. let templateImportEasyComponentsCode = '';
  37. let templateImportUTSComponentsCode = '';
  38. if (!isAppVue) {
  39. // template
  40. const isInline = !!descriptor.scriptSetup;
  41. const templateResult = (0, template_1.genTemplateCode)(descriptor, (0, template_2.resolveGenTemplateCodeOptions)(relativeFilename, code, descriptor, {
  42. mode: 'module',
  43. inline: isInline,
  44. className,
  45. rootDir: options.root,
  46. sourceMap: process.env.NODE_ENV === 'development',
  47. bindingMetadata,
  48. }));
  49. templatePreambleCode = templateResult.preamble;
  50. templateCode = templateResult.code;
  51. templateMap = templateResult.map;
  52. const { easyComponentAutoImports, elements, importEasyComponents, importUTSComponents, imports, } = templateResult;
  53. templateImportEasyComponentsCode = importEasyComponents.join('\n');
  54. templateImportUTSComponentsCode = importUTSComponents.join('\n');
  55. templateImportsCode = imports.join('\n');
  56. Object.keys(easyComponentAutoImports).forEach((source) => {
  57. (0, uni_cli_shared_1.addUTSEasyComAutoImports)(source, easyComponentAutoImports[source]);
  58. });
  59. if (process.env.NODE_ENV === 'production') {
  60. (0, utils_1.addExtApiComponents)(elements.filter((element) => {
  61. // 如果是UTS原生组件,则无需记录摇树
  62. if ((0, uni_cli_shared_1.parseUTSComponent)(element, 'kotlin')) {
  63. return false;
  64. }
  65. return true;
  66. }));
  67. }
  68. }
  69. // styles
  70. const stylesCode = await genStyleCode(descriptor, pluginContext);
  71. const utsOutput = [
  72. scriptCode ||
  73. `
  74. export default {}
  75. `,
  76. templateCode,
  77. `/*${className}Styles*/\n`,
  78. ];
  79. if (templatePreambleCode) {
  80. utsOutput.push(templatePreambleCode);
  81. }
  82. let resolvedMap = undefined;
  83. if (options.sourceMap) {
  84. if (scriptMap && templateMap) {
  85. // if the template is inlined into the main module (indicated by the presence
  86. // of templateMap), we need to concatenate the two source maps.
  87. const gen = (0, gen_mapping_1.fromMap)(
  88. // version property of result.map is declared as string
  89. // but actually it is `3`
  90. scriptMap);
  91. const tracer = new trace_mapping_1.TraceMap(
  92. // same above
  93. templateMap);
  94. const offset = (scriptCode.match(/\r?\n/g)?.length ?? 0) + 1;
  95. (0, trace_mapping_1.eachMapping)(tracer, (m) => {
  96. if (m.source == null)
  97. return;
  98. (0, gen_mapping_1.addMapping)(gen, {
  99. source: m.source,
  100. original: { line: m.originalLine, column: m.originalColumn },
  101. generated: {
  102. line: m.generatedLine + offset,
  103. column: m.generatedColumn,
  104. },
  105. });
  106. });
  107. // same above
  108. resolvedMap = (0, gen_mapping_1.toEncodedMap)(gen);
  109. // if this is a template only update, we will be reusing a cached version
  110. // of the main module compile result, which has outdated sourcesContent.
  111. // resolvedMap.sourcesContent = templateMap.sourcesContent
  112. }
  113. else {
  114. // if one of `scriptMap` and `templateMap` is empty, use the other one
  115. resolvedMap = scriptMap ?? templateMap;
  116. }
  117. }
  118. // handle TS transpilation
  119. const utsCode = utsOutput.join('\n');
  120. if (resolvedMap && pluginContext) {
  121. pluginContext.emitFile({
  122. type: 'asset',
  123. fileName: (0, uni_cli_shared_1.removeExt)(relativeFilename) + '.map',
  124. source: JSON.stringify(resolvedMap),
  125. });
  126. }
  127. const jsCodes = [
  128. templateImportEasyComponentsCode,
  129. templateImportUTSComponentsCode,
  130. templateImportsCode,
  131. ];
  132. if (scriptCode) {
  133. jsCodes.push(await (0, utils_1.parseImports)(scriptCode, resolvedMap && pluginContext
  134. ? createTryResolve(filename, pluginContext.resolve, resolvedMap,
  135. // 仅需要再解析script中的import,template上边已经加入了
  136. (source) => source.includes('/.uvue/'))
  137. : undefined));
  138. pluginContext?.emitFile({
  139. type: 'asset',
  140. fileName: relativeFilename,
  141. source: utsCode,
  142. });
  143. }
  144. if (stylesCode) {
  145. jsCodes.push(stylesCode);
  146. }
  147. jsCodes.push(`export default "${className}"
  148. export const ${(0, uni_cli_shared_1.genUTSComponentPublicInstanceImported)(options.root, relativeFilename)} = {}`);
  149. const jsCode = jsCodes.filter(Boolean).join('\n');
  150. return {
  151. code: jsCode,
  152. map: {
  153. mappings: '',
  154. },
  155. // 这些都是 vuejs-core 需要的
  156. errors,
  157. uts: utsCode,
  158. descriptor,
  159. };
  160. }
  161. exports.transformMain = transformMain;
  162. async function genScriptCode(descriptor, options) {
  163. let scriptCode = `export default {}`;
  164. let map;
  165. const script = (0, script_1.resolveScript)(descriptor, options);
  166. if (script) {
  167. scriptCode = script.content;
  168. map = script.map;
  169. }
  170. return {
  171. code: scriptCode,
  172. map,
  173. bindingMetadata: script?.bindings,
  174. };
  175. }
  176. async function genStyleCode(descriptor, pluginContext) {
  177. let stylesCode = ``;
  178. if (descriptor.styles.length) {
  179. for (let i = 0; i < descriptor.styles.length; i++) {
  180. const style = descriptor.styles[i];
  181. if (style.src && pluginContext) {
  182. await linkSrcToDescriptor(style.src, descriptor, pluginContext);
  183. }
  184. const src = style.src || descriptor.filename;
  185. // do not include module in default query, since we use it to indicate
  186. // that the module needs to export the modules json
  187. const attrsQuery = attrsToQuery(style.attrs, 'css');
  188. style.scoped = false; // fixed by xxxxxx 强制不scoped
  189. const srcQuery = style.src
  190. ? style.scoped
  191. ? `&src=${descriptor.id}`
  192. : '&src=true'
  193. : '';
  194. const directQuery = ``;
  195. const scopedQuery = style.scoped ? `&scoped=${descriptor.id}` : ``;
  196. const query = `?vue&type=style&index=${i}${srcQuery}${directQuery}${scopedQuery}`;
  197. const styleRequest = src + query + attrsQuery;
  198. stylesCode += `\nimport ${JSON.stringify(styleRequest)}`;
  199. }
  200. // TODO SSR critical CSS collection
  201. }
  202. return stylesCode;
  203. }
  204. /**
  205. * For blocks with src imports, it is important to link the imported file
  206. * with its owner SFC descriptor so that we can get the information about
  207. * the owner SFC when compiling that file in the transform phase.
  208. */
  209. async function linkSrcToDescriptor(src, descriptor, pluginContext) {
  210. const srcFile = (await pluginContext.resolve(src, descriptor.filename))?.id || src;
  211. // #1812 if the src points to a dep file, the resolved id may contain a
  212. // version query.
  213. (0, descriptorCache_1.setSrcDescriptor)(srcFile.replace(/\?.*$/, ''), descriptor);
  214. }
  215. // these are built-in query parameters so should be ignored
  216. // if the user happen to add them as attrs
  217. const ignoreList = [
  218. 'id',
  219. 'index',
  220. 'src',
  221. 'type',
  222. 'lang',
  223. 'module',
  224. 'scoped',
  225. 'generic',
  226. ];
  227. function attrsToQuery(attrs, langFallback, forceLangFallback = false) {
  228. let query = ``;
  229. for (const name in attrs) {
  230. const value = attrs[name];
  231. if (!ignoreList.includes(name)) {
  232. query += `&${encodeURIComponent(name)}${value ? `=${encodeURIComponent(value)}` : ``}`;
  233. }
  234. }
  235. if (langFallback || attrs.lang) {
  236. query +=
  237. `lang` in attrs
  238. ? forceLangFallback
  239. ? `&lang.${langFallback}`
  240. : `&lang.${attrs.lang}`
  241. : `&lang.${langFallback}`;
  242. }
  243. return query;
  244. }
  245. function createTryResolve(importer, resolve, resolvedMap, ignore) {
  246. return async (source, code, { ss, se }) => {
  247. if (ignore && ignore(source)) {
  248. return false;
  249. }
  250. const resolved = await (0, utils_1.wrapResolve)(resolve)(source, importer);
  251. if (!resolved) {
  252. const { start, end } = (0, uni_cli_shared_1.offsetToStartAndEnd)(code, ss, se);
  253. const consumer = new source_map_js_1.SourceMapConsumer(resolvedMap);
  254. const startPos = consumer.originalPositionFor({
  255. line: start.line,
  256. column: start.column,
  257. });
  258. if (startPos.line != null &&
  259. startPos.column != null &&
  260. startPos.source != null) {
  261. const endPos = consumer.originalPositionFor({
  262. line: end.line,
  263. column: end.column,
  264. });
  265. if (endPos.line != null && endPos.column != null) {
  266. startPos.column = startPos.column + 1;
  267. endPos.column = endPos.column + 1;
  268. throw (0, utils_1.createResolveError)(consumer.sourceContentFor(startPos.source), (0, uni_cli_shared_1.createResolveErrorMsg)(source, importer), startPos, endPos);
  269. }
  270. }
  271. }
  272. };
  273. }