aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorArpit Chakladar <54011232+arpitchakladar@users.noreply.github.com>2023-02-08 13:54:04 +0530
committerArpit Chakladar <54011232+arpitchakladar@users.noreply.github.com>2023-02-08 13:54:04 +0530
commit4993aaf41e132dd0805bf6c487901d9f2aecfcfe (patch)
treea51ebf7bff551e9188d68f777d100e8ffb70922d /config
parent8234acb45cd99fc7bcd99df7f71cac02845bb534 (diff)
downloadbanglar-bhumi-utils-4993aaf41e132dd0805bf6c487901d9f2aecfcfe.tar.gz
banglar-bhumi-utils-4993aaf41e132dd0805bf6c487901d9f2aecfcfe.zip
Combining similar scripts into 1 for improved performence and less files in build.
Diffstat (limited to 'config')
-rw-r--r--config/webpack.config.js7
-rw-r--r--config/webpack/loaders/scoped-loader.js3
-rw-r--r--config/webpack/plugins/create-manifest-webpack-plugin/index.js34
-rw-r--r--config/webpack/plugins/inject-script-webpack-plugin.js52
-rw-r--r--config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js56
-rw-r--r--config/webpack/utils/generate-script-build-config.js37
6 files changed, 143 insertions, 46 deletions
diff --git a/config/webpack.config.js b/config/webpack.config.js
index f21d38f..e7ffaa7 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -2,6 +2,7 @@ const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
process.env.ROOT_DIR = path.resolve(__dirname, "..");
+process.env.CONFIG_DIR = path.resolve(process.env.ROOT_DIR, "config");
process.env.SOURCE_DIR = path.resolve(process.env.ROOT_DIR, "src");
const CreateManifestPlugin = require("./webpack/plugins/create-manifest-webpack-plugin");
@@ -12,9 +13,7 @@ const manifest = require(path.resolve(process.env.SOURCE_DIR, "manifest.json"));
let scripts = [];
for (const scriptType in manifest) {
- for (const scriptName in manifest[scriptType]) {
- scripts.push(generateScriptBuildConfig(scriptName, scriptType));
- }
+ scripts.push(generateScriptBuildConfig(scriptType));
}
scripts[scripts.length - 1].plugins = (scripts[scripts.length - 1].plugins || []).concat([
@@ -24,7 +23,7 @@ scripts[scripts.length - 1].plugins = (scripts[scripts.length - 1].plugins || []
to: "./"
}]
}),
- new CreateManifestPlugin(manifest)
+ new CreateManifestPlugin({ scripts: manifest })
]);
module.exports = scripts;
diff --git a/config/webpack/loaders/scoped-loader.js b/config/webpack/loaders/scoped-loader.js
new file mode 100644
index 0000000..701afc2
--- /dev/null
+++ b/config/webpack/loaders/scoped-loader.js
@@ -0,0 +1,3 @@
+module.exports = source => `(() => {
+${source}
+})();`;
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;
diff --git a/config/webpack/utils/generate-script-build-config.js b/config/webpack/utils/generate-script-build-config.js
index 2485e85..f8e1697 100644
--- a/config/webpack/utils/generate-script-build-config.js
+++ b/config/webpack/utils/generate-script-build-config.js
@@ -1,26 +1,31 @@
const fs = require("fs");
const path = require("path");
+const SanitizeScriptsImportPlugin = require("../plugins/sanitize-scripts-import-webpack-plugin");
const InjectScriptPlugin = require("../plugins/inject-script-webpack-plugin");
const manifest = require(path.resolve(process.env.SOURCE_DIR, "manifest.json"));
let count = 0;
-const generateScriptBuildConfig = (scriptName, scriptType) => {
- let entry = path.resolve(process.env.SOURCE_DIR, `scripts/${scriptName}.ts`);
- if (!fs.existsSync(entry)) {
- entry = path.resolve(process.env.SOURCE_DIR, `scripts/${scriptName}/index.ts`);
- if (!fs.existsSync(entry)) {
- entry = path.resolve(process.env.SOURCE_DIR, `scripts/${scriptName}.js`);
- }
- }
+const getImportStatementForScript = script => {
+ const importPath = path.resolve(process.env.SOURCE_DIR, "scripts", script);
+ return `import "${importPath}";`;
+};
+
+const getVirtualEntry = scriptType => {
+ const string = Object.keys(manifest[scriptType]).map(getImportStatementForScript).join("\n");
+ const base64 = Buffer.from(string).toString("base64");
+ return `data:text/javascript;base64,${base64}`;
+}
+
+const generateScriptBuildConfig = scriptType => {
return {
- entry,
+ entry: getVirtualEntry(scriptType),
mode: "production",
output: {
- filename: `${scriptName}.js`
+ filename: `${scriptType}.js`
},
resolve: {
extensions: ["", ".ts", ".js"],
@@ -36,15 +41,23 @@ const generateScriptBuildConfig = (scriptName, scriptType) => {
options: {
configFile: "config/tsconfig.json"
}
+ },
+ {
+ test: new RegExp(`^${path.resolve(process.env.SOURCE_DIR, "scripts")}`),
+ loader: path.resolve(process.env.CONFIG_DIR, "webpack/loaders/scoped-loader")
}
]
},
- plugins: scriptType.startsWith("injected")
+ plugins: [
+ new SanitizeScriptsImportPlugin()
+ ].concat(
+ scriptType.startsWith("injected")
? [new InjectScriptPlugin({
onload: scriptType === "injected_and_loaded",
isFirst: count++ <= 0
})]
- : undefined
+ : []
+ )
};
};