From 61f9a69a60196abdc85afaa8658faf7736cf08a9 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:50:52 +0300 Subject: [PATCH] feat: reduce runtime code --- src/index.js | 5 +- src/plugins/sources-plugin.js | 13 +- src/runtime/getUrl.js | 16 +- src/utils.js | 95 +- .../esModule-option.test.js.snap | 1121 ++-- test/__snapshots__/loader.test.js.snap | 792 ++- .../minimize-option.test.js.snap | 1262 ++--- .../postprocessor-option.test.js.snap | 12 +- .../preprocessor-option.test.js.snap | 18 +- .../__snapshots__/sources-option.test.js.snap | 4653 ++++++++--------- .../runtime/__snapshots__/getUrl.test.js.snap | 62 - test/runtime/getUrl.test.js | 97 +- 12 files changed, 3540 insertions(+), 4606 deletions(-) diff --git a/src/index.js b/src/index.js index f67c0c4a..fff8dae7 100644 --- a/src/index.js +++ b/src/index.js @@ -80,8 +80,9 @@ export default async function loader(content) { html = await options.postprocessor(html, this); } - const importCode = getImportCode(html, this, imports, options); - const moduleCode = getModuleCode(html, replacements, { + const importCode = getImportCode(html, imports, options); + const moduleCode = getModuleCode(html, replacements, this, { + esModule: options.esModule, isTemplateLiteralSupported, }); const exportCode = getExportCode(html, options); diff --git a/src/plugins/sources-plugin.js b/src/plugins/sources-plugin.js index 28ce1d3c..9ed9eab8 100644 --- a/src/plugins/sources-plugin.js +++ b/src/plugins/sources-plugin.js @@ -139,15 +139,7 @@ export default (options) => let offset = 0; for (const source of sources) { - const { - name, - value, - isValueQuoted, - format, - runtime, - startOffset, - endOffset, - } = source; + const { name, value, isValueQuoted, startOffset, endOffset } = source; let request = value; @@ -172,7 +164,7 @@ export default (options) => importName = `___HTML_LOADER_IMPORT_${imports.size}___`; imports.set(request, importName); - options.imports.push({ format, importName, request }); + options.imports.push({ importName, request }); } const replacementKey = JSON.stringify({ request, isValueQuoted, hash }); @@ -187,7 +179,6 @@ export default (options) => importName, hash, isValueQuoted, - runtime, }); } diff --git a/src/runtime/getUrl.js b/src/runtime/getUrl.js index 2bc48ac9..f2b3b2cb 100644 --- a/src/runtime/getUrl.js +++ b/src/runtime/getUrl.js @@ -1,22 +1,12 @@ -module.exports = (url, options) => { - if (!options) { - // eslint-disable-next-line no-param-reassign - options = {}; - } - +module.exports = (url, maybeNeedQuotes) => { if (!url) { return url; } // eslint-disable-next-line no-underscore-dangle, no-param-reassign - url = String(url.__esModule ? url.default : url); - - if (options.hash) { - // eslint-disable-next-line no-param-reassign - url += options.hash; - } + url = String(url); - if (options.maybeNeedQuotes && /[\t\n\f\r "'=<>`]/.test(url)) { + if (maybeNeedQuotes && /[\t\n\f\r "'=<>`]/.test(url)) { return `"${url}"`; } diff --git a/src/utils.js b/src/utils.js index 4ed05467..fb2300e8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1218,43 +1218,21 @@ export function getFilter(filter) { }; } -const GET_SOURCE_FROM_IMPORT_NAME = "___HTML_LOADER_GET_SOURCE_FROM_IMPORT___"; - -export function getImportCode(html, loaderContext, imports, options) { +export function getImportCode(html, imports, options) { if (imports.length === 0) { return ""; } - // TODO simplify in the next major release - const getURLRuntime = require.resolve("./runtime/getUrl.js"); - const context = loaderContext.context || loaderContext.rootContext; - const fileURLToHelper = - typeof loaderContext.utils !== "undefined" && - typeof loaderContext.utils.contextify === "function" - ? loaderContext.utils.contextify(context, getURLRuntime) - : contextify(context, getURLRuntime); - - let code = options.esModule - ? `import ${GET_SOURCE_FROM_IMPORT_NAME} from "${fileURLToHelper}";\n` - : `var ${GET_SOURCE_FROM_IMPORT_NAME} = require("${fileURLToHelper}");\n`; + let code = ""; for (const item of imports) { - const { format, importName, request } = item; + const { importName, request } = item; - switch (format) { - case "import": - code += options.esModule - ? `import ${importName} from ${JSON.stringify(request)};\n` - : `var ${importName} = require(${JSON.stringify(request)});\n`; - break; - case "url": - default: - code += options.esModule - ? `var ${importName} = new URL(${JSON.stringify( - request, - )}, import.meta.url);\n` - : `var ${importName} = require(${JSON.stringify(request)});\n`; - } + code += options.esModule + ? `var ${importName} = new URL(${JSON.stringify( + request, + )}, import.meta.url);\n` + : `var ${importName} = require(${JSON.stringify(request)});\n`; } return `// Imports\n${code}`; @@ -1279,36 +1257,31 @@ export function convertToTemplateLiteral(str) { return `\`${escapedString}\``; } -export function getModuleCode(html, replacements, options) { +const GET_SOURCE_FROM_IMPORT_NAME = "___HTML_LOADER_GET_SOURCE_FROM_IMPORT___"; + +export function getModuleCode(html, replacements, loaderContext, options) { let code = html; - let replacersCode = ""; const { isTemplateLiteralSupported } = options; + let needHelperImport = false; + for (const item of replacements) { - const { runtime, importName, replacementName, isValueQuoted, hash } = item; + const { importName, replacementName, isValueQuoted, hash } = item; - if (typeof runtime === "undefined" || runtime === true) { - const getUrlOptions = [] - .concat(hash ? [`hash: ${JSON.stringify(hash)}`] : []) - .concat(isValueQuoted ? [] : "maybeNeedQuotes: true"); - const preparedOptions = - getUrlOptions.length > 0 ? `, { ${getUrlOptions.join(", ")} }` : ""; + if (!isValueQuoted && !needHelperImport) { + needHelperImport = true; + } - replacersCode += `var ${replacementName} = ${GET_SOURCE_FROM_IMPORT_NAME}(${importName}${preparedOptions});\n`; + const name = !isValueQuoted + ? `${GET_SOURCE_FROM_IMPORT_NAME}(${importName}${!isValueQuoted ? ", true" : ""})` + : importName; - code = code.replace(new RegExp(replacementName, "g"), () => - isTemplateLiteralSupported - ? `\${${replacementName}}` - : `" + ${replacementName} + "`, - ); - } else { - code = code.replace(new RegExp(replacementName, "g"), () => - isTemplateLiteralSupported - ? `\${${replacementName}}` - : `" + ${replacementName} + "`, - ); - } + code = code.replace(new RegExp(replacementName, "g"), () => + isTemplateLiteralSupported + ? `\${${name}}${typeof hash !== "undefined" ? hash : ""}` + : `" + ${name}${typeof hash !== "undefined" ? ` + ${JSON.stringify(hash)}` : ""} + "`, + ); } // Replaces "" to "<" + "script>" or "<" + "/script>". @@ -1316,7 +1289,23 @@ export function getModuleCode(html, replacements, options) { isTemplateLiteralSupported ? `\${"<" + "${s}"}` : `<" + "${s}`, ); - return `// Module\n${replacersCode}var code = ${code};\n`; + code = `// Module\nvar code = ${code};\n`; + + if (needHelperImport) { + // TODO simplify in the next major release + const getURLRuntime = require.resolve("./runtime/getUrl.js"); + const context = loaderContext.context || loaderContext.rootContext; + const fileURLToHelper = + typeof loaderContext.utils !== "undefined" && + typeof loaderContext.utils.contextify === "function" + ? loaderContext.utils.contextify(context, getURLRuntime) + : contextify(context, getURLRuntime); + code = options.esModule + ? `import ${GET_SOURCE_FROM_IMPORT_NAME} from "${fileURLToHelper}";\n${code}` + : `var ${GET_SOURCE_FROM_IMPORT_NAME} = require("${fileURLToHelper}");\n${code}`; + } + + return code; } export function getExportCode(html, options) { diff --git a/test/__snapshots__/esModule-option.test.js.snap b/test/__snapshots__/esModule-option.test.js.snap index 6fc82434..b9adfd40 100644 --- a/test/__snapshots__/esModule-option.test.js.snap +++ b/test/__snapshots__/esModule-option.test.js.snap @@ -4,7 +4,6 @@ exports[`'esModule' option should use a CommonJS export by default: errors 1`] = exports[`'esModule' option should use a CommonJS export by default: module 1`] = ` "// Imports -import ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___ from "../../src/runtime/getUrl.js"; var ___HTML_LOADER_IMPORT_0___ = new URL("./image.png", import.meta.url); var ___HTML_LOADER_IMPORT_1___ = new URL("/image.png", import.meta.url); var ___HTML_LOADER_IMPORT_2___ = new URL("aliasImg", import.meta.url); @@ -33,44 +32,8 @@ var ___HTML_LOADER_IMPORT_24___ = new URL("./nested/image3.png", import.meta.url var ___HTML_LOADER_IMPORT_25___ = new URL("/nested/image3.png", import.meta.url); var ___HTML_LOADER_IMPORT_26___ = new URL("./noscript.png", import.meta.url); var ___HTML_LOADER_IMPORT_27___ = new URL("./😀abc.png", import.meta.url); +import ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___ from "../../src/runtime/getUrl.js"; // Module -var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___); -var ___HTML_LOADER_REPLACEMENT_1___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { maybeNeedQuotes: true }); -var ___HTML_LOADER_REPLACEMENT_2___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_1___); -var ___HTML_LOADER_REPLACEMENT_3___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_2___); -var ___HTML_LOADER_REPLACEMENT_4___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_3___); -var ___HTML_LOADER_REPLACEMENT_5___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_4___, { hash: "#icon-chevron-with-circle-up" }); -var ___HTML_LOADER_REPLACEMENT_6___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_5___); -var ___HTML_LOADER_REPLACEMENT_7___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_6___); -var ___HTML_LOADER_REPLACEMENT_8___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_7___); -var ___HTML_LOADER_REPLACEMENT_9___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_8___); -var ___HTML_LOADER_REPLACEMENT_10___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_9___); -var ___HTML_LOADER_REPLACEMENT_11___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_10___); -var ___HTML_LOADER_REPLACEMENT_12___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_11___); -var ___HTML_LOADER_REPLACEMENT_13___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_12___); -var ___HTML_LOADER_REPLACEMENT_14___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_13___); -var ___HTML_LOADER_REPLACEMENT_15___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_14___); -var ___HTML_LOADER_REPLACEMENT_16___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_15___, { maybeNeedQuotes: true }); -var ___HTML_LOADER_REPLACEMENT_17___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_15___); -var ___HTML_LOADER_REPLACEMENT_18___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { hash: "#hash" }); -var ___HTML_LOADER_REPLACEMENT_19___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { hash: "#hash", maybeNeedQuotes: true }); -var ___HTML_LOADER_REPLACEMENT_20___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { hash: "#", maybeNeedQuotes: true }); -var ___HTML_LOADER_REPLACEMENT_21___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { hash: "#foo" }); -var ___HTML_LOADER_REPLACEMENT_22___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { hash: "#bar" }); -var ___HTML_LOADER_REPLACEMENT_23___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { hash: "#baz" }); -var ___HTML_LOADER_REPLACEMENT_24___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_15___, { hash: "#hash", maybeNeedQuotes: true }); -var ___HTML_LOADER_REPLACEMENT_25___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_16___); -var ___HTML_LOADER_REPLACEMENT_26___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_17___); -var ___HTML_LOADER_REPLACEMENT_27___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_18___); -var ___HTML_LOADER_REPLACEMENT_28___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_19___); -var ___HTML_LOADER_REPLACEMENT_29___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_20___); -var ___HTML_LOADER_REPLACEMENT_30___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_21___); -var ___HTML_LOADER_REPLACEMENT_31___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_22___); -var ___HTML_LOADER_REPLACEMENT_32___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_23___); -var ___HTML_LOADER_REPLACEMENT_33___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_24___); -var ___HTML_LOADER_REPLACEMENT_34___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_25___); -var ___HTML_LOADER_REPLACEMENT_35___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_26___); -var ___HTML_LOADER_REPLACEMENT_36___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_27___); var code = \`

My First Heading

@@ -104,134 +67,134 @@ var code = \` \${"<" + "script"}> console.log(1 + 2 + \\\`\\\${3 + 3}\\\`) \${"<" + "/script"}> - - - - - - - - - - + + + + + + + + + + -\${"<" + "script"} src="\${___HTML_LOADER_REPLACEMENT_4___}">\${"<" + "/script"}> +\${"<" + "script"} src="\${___HTML_LOADER_IMPORT_3___}">\${"<" + "/script"}> - + -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy -Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy +Elva dressed as a fairy Elva dressed as a fairy +" src="\${___HTML_LOADER_IMPORT_0___}" alt="Elva dressed as a fairy"> - - - Flowers + + + Flowers -