Skip to content

Commit

Permalink
feat: reduce runtime code
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait authored Jul 25, 2024
1 parent a2463ca commit 61f9a69
Show file tree
Hide file tree
Showing 12 changed files with 3,540 additions and 4,606 deletions.
5 changes: 3 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 2 additions & 11 deletions src/plugins/sources-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 });
Expand All @@ -187,7 +179,6 @@ export default (options) =>
importName,
hash,
isValueQuoted,
runtime,
});
}

Expand Down
16 changes: 3 additions & 13 deletions src/runtime/getUrl.js
Original file line number Diff line number Diff line change
@@ -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}"`;
}

Expand Down
95 changes: 42 additions & 53 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
Expand All @@ -1279,44 +1257,55 @@ 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 "<script>" or "</script>" to "<" + "script>" or "<" + "/script>".
code = code.replace(/<(\/?script)/g, (_, s) =>
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) {
Expand Down
Loading

0 comments on commit 61f9a69

Please sign in to comment.