From 4993aaf41e132dd0805bf6c487901d9f2aecfcfe Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Wed, 8 Feb 2023 13:54:04 +0530 Subject: Combining similar scripts into 1 for improved performence and less files in build. --- .../create-manifest-webpack-plugin/index.js | 34 +++++++++---- .../plugins/inject-script-webpack-plugin.js | 52 ++++++++++++-------- .../sanitize-scripts-import-webpack-plugin.js | 56 ++++++++++++++++++++++ 3 files changed, 112 insertions(+), 30 deletions(-) create mode 100644 config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js (limited to 'config/webpack/plugins') diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index 5dac1b2..4a07380 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -2,17 +2,31 @@ const path = require("path"); const { version } = require(path.resolve(process.env.ROOT_DIR, "package.json")); +const getRunAt = scriptType => { + switch (scriptType) { + case "before": + case "injected": + case "injected_and_loaded": + return "document_start"; + + case "rendered": + return "document_end"; + + case "loaded": + default: + return "document_idle"; + } +}; + class CreateManifestPlugin { - constructor(scripts) { + constructor({ scripts }) { this.scripts = {}; this.manifest = require("./manifest-template.json"); - this.scripts.document_start = { - ...(scripts.before || {}), - ...(scripts.injected || {}), - ...(scripts.injected_and_loaded || {}) - }; - this.scripts.document_end = scripts.rendered || {}; - this.scripts.document_idle = scripts.loaded || {}; + this.scripts.before = scripts.before || {}; + this.scripts.injected = scripts.injected || {}; + this.scripts.injected_and_loaded = scripts.injected_and_loaded || {}; + this.scripts.rendered = scripts.rendered || {}; + this.scripts.loaded = scripts.loaded || {}; } apply(compiler) { @@ -43,8 +57,8 @@ class CreateManifestPlugin { for (const scriptPath in paths) { this.manifest.content_scripts.push({ matches: [`*://banglarbhumi.gov.in/${scriptPath}`], - js: paths[scriptPath].map(scriptName => `${scriptName}.js`), - run_at: scriptType + js: [`${scriptType}.js`], + run_at: getRunAt(scriptType) }); } } diff --git a/config/webpack/plugins/inject-script-webpack-plugin.js b/config/webpack/plugins/inject-script-webpack-plugin.js index ca75213..6568514 100644 --- a/config/webpack/plugins/inject-script-webpack-plugin.js +++ b/config/webpack/plugins/inject-script-webpack-plugin.js @@ -1,5 +1,23 @@ +const { sources } = require("webpack"); const terser = require("terser"); +const propectualIndexOf = (string, characterList, start) => { + if (start > 0) { + let i = 0; + let x = start; + while (i < characterList.length) { + x = string.indexOf(characterList[i], x + 1); + if (x < 0) { + return -1; + } + i++; + } + return x; + } else { + return -1; + } +}; + class InjectScriptPlugin { constructor({ onload, isFirst }) { this.onload = !!onload; @@ -11,45 +29,39 @@ class InjectScriptPlugin { compilation.hooks.processAssets.tapPromise( { name: "InjectScriptPlugin", - stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE, + stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE, additionalAssets: true }, async assets => { for (const assetName in assets) { if (assetName.endsWith(".js")) { - const asset = assets[assetName]; - let content = asset._source._children; - let x = -1; - for (let i = 0; i < content.length; i++) { - if (typeof content[i] === "string" && content[i].indexOf("__webpack_exports__") >= 0) { - x = i; - break; - } - } - if (x == -1) { - throw Error("Failed to inject script."); - } - content[x] += ` + let currentAssetContent = compilation.getAsset(assetName).source.source(); + let start = ` const observer = new MutationObserver(mutations => { const script = document.querySelector("head > script:nth-child(54)"); if (script) { script.innerHTML `; + let end = ""; if (!this.isFirst) { - content[x] += "+"; + start += "+"; } - content[x] += "= `"; + start += "= `"; if (this.onload) { - content[x] += "document.addEventListener(\"DOMContentLoaded\", () => {"; - content[content.length - 3] += "});"; + start += "document.addEventListener(\"DOMContentLoaded\", () => {"; + end += "});"; } - content[content.length - 3] += `\`; + end += `\`; observer.disconnect(); } }); observer.observe(document, {childList: true, subtree: true}); `; - content[x + 1] = (await terser.minify(content[x + 1]._source._source._valueAsString.replaceAll("`", "\\`"))).code; + const content = (await terser.minify(currentAssetContent.replaceAll("`", "\\`"))).code; + compilation.updateAsset( + assetName, + new sources.RawSource(start + content + end) + ); } } } diff --git a/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js b/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js new file mode 100644 index 0000000..61ce804 --- /dev/null +++ b/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js @@ -0,0 +1,56 @@ +const { sources } = require("webpack"); + +const propectualIndexOf = (string, characterList, start) => { + if (start > 0) { + let i = 0; + let x = start; + while (i < characterList.length) { + x = string.indexOf(characterList[i], x + 1); + if (x < 0) { + return -1; + } + i++; + } + return x; + } else { + return -1; + } +}; + +class SanitizeScriptsImportPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("SanitizeScriptsImportPlugin", compilation => { + compilation.hooks.processAssets.tap( + { + name: "SanitizeScriptsImportPlugin", + stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE, + additionalAssets: true + }, + assets => { + for (const assetName in assets) { + if (assetName.endsWith(".js")) { + const currentAssetContent = compilation.getAsset(assetName).source.source(); + let previouslyEnded = 0; + let code = ""; + while (true) { + const start = propectualIndexOf(currentAssetContent, ["\n/***/", "\n/***/", "\n"], previouslyEnded + 1); + previouslyEnded = propectualIndexOf(currentAssetContent, ["\n/***/"], start + 1); + if (previouslyEnded < 0) { + break; + } else { + code += currentAssetContent.substring(start, previouslyEnded); + } + } + compilation.updateAsset( + assetName, + new sources.RawSource(code) + ); + } + } + } + ); + }); + } +} + +module.exports = SanitizeScriptsImportPlugin; -- cgit v1.2.3