From 5f23f07d04073c06af530332c2d75b48d6c023a0 Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:53:04 +0530 Subject: Using different global variables for shared modules. --- config/webpack.config.js | 54 ++++++++++------------ config/webpack/loader/dynamic-imports-loader.js | 31 ------------- .../create-manifest-webpack-plugin/index.js | 14 ++++-- .../manifest-template.json | 9 +++- .../webpack/plugins/create-rules-webpack-plugin.js | 43 +++++++++++++++++ config/webpack/utils/file-name-hash.js | 11 ----- config/webpack/utils/filename-hash.js | 10 ++++ 7 files changed, 94 insertions(+), 78 deletions(-) delete mode 100644 config/webpack/loader/dynamic-imports-loader.js create mode 100644 config/webpack/plugins/create-rules-webpack-plugin.js delete mode 100644 config/webpack/utils/file-name-hash.js create mode 100644 config/webpack/utils/filename-hash.js (limited to 'config') diff --git a/config/webpack.config.js b/config/webpack.config.js index 010a51f..22544b9 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -11,11 +11,12 @@ global.production = process.env.NODE_ENV === "production"; global.webpackRequire = modulePath => require(path.resolve(CONFIG_DIR, "webpack", modulePath)); const CreateManifestPlugin = webpackRequire("plugins/create-manifest-webpack-plugin"); +const CreateRulesPlugin = webpackRequire("plugins/create-rules-webpack-plugin"); const InjectScriptPlugin = webpackRequire("plugins/inject-script-webpack-plugin"); const { inlineJavascript } = webpackRequire("utils/inline-javascript"); const { getScriptRuntimeFromType } = webpackRequire("utils/script-runtime"); -const { getFileNameHash } = webpackRequire("utils/file-name-hash"); +const { getFileNameHash } = webpackRequire("utils/filename-hash"); const scripts = webpackRequire("utils/scripts"); @@ -54,11 +55,16 @@ for (const scriptPath in scripts) { for (const sharedModule of sharedModules) { const sharedModuleNameHash = getFileNameHash(sharedModule, "shared"); + const sharedModuleGlobalVariableName = `$${sharedModuleNameHash.substring(sharedModuleNameHash.length - 16)}`; sharedModuleEntries[sharedModule] = { import: path.resolve(SOURCE_DIR, "shared", sharedModule), - filename: `shared/${sharedModuleNameHash}.js` + filename: `shared/${sharedModuleNameHash}.js`, + library: { + name: sharedModuleGlobalVariableName, + type: "var" + } }; - sharedModuleExternals[`@/shared/${sharedModule}`] = `/shared/${sharedModuleNameHash}.js`; + sharedModuleExternals[`@/shared/${sharedModule}`] = sharedModuleGlobalVariableName; } const commonOptions = { @@ -82,26 +88,27 @@ const commonOptions = { }, optimization: { minimize: process.env.NODE_ENV === "production" + }, + output: { + iife: true } }; const ecmaScriptModuleOptions = { experiments: { - outputModule: true, - topLevelAwait: true + outputModule: true } }; -const scriptOptions = { - output: { - iife: true - } +const sharedModuleOptions = { + externals: sharedModuleExternals, + externalsType: "var" }; const uninjectedScriptConfiguration = merge( commonOptions, ecmaScriptModuleOptions, - scriptOptions, + sharedModuleOptions, { entry: uninjectedScriptEntries, plugins: [ @@ -110,24 +117,13 @@ const uninjectedScriptConfiguration = merge( from: path.resolve(ROOT_DIR, "static"), to: "./" }] - }), - new CreateManifestPlugin() - ], - module: { - rules: [ - { - enforce: "post", - test: /\.(js|ts)$/, - loader: "./config/webpack/loader/dynamic-imports-loader" - } - ] - } + }) + ] } ); const injectedAfterScriptConfiguration = merge( commonOptions, - scriptOptions, { entry: injectedAfterScriptEntries, plugins: [ @@ -138,7 +134,6 @@ const injectedAfterScriptConfiguration = merge( const injectedBeforeScriptConfiguration = merge( commonOptions, - scriptOptions, { entry: injectedBeforeScriptEntries, plugins: [ @@ -150,14 +145,13 @@ const injectedBeforeScriptConfiguration = merge( const sharedModulesConfiguration = merge( commonOptions, ecmaScriptModuleOptions, + sharedModuleOptions, { - output: { - library: { - type: "module" - } - }, entry: sharedModuleEntries, - externals: sharedModuleExternals + plugins: [ + new CreateManifestPlugin(), + new CreateRulesPlugin() + ] } ); diff --git a/config/webpack/loader/dynamic-imports-loader.js b/config/webpack/loader/dynamic-imports-loader.js deleted file mode 100644 index 12eb5b7..0000000 --- a/config/webpack/loader/dynamic-imports-loader.js +++ /dev/null @@ -1,31 +0,0 @@ -const { ImportManager } = require("import-manager"); -const { getFileNameHash } = webpackRequire("utils/file-name-hash"); - -const sharedModules = webpackRequire("utils/shared-modules.js"); - -module.exports = source => { - const manager = new ImportManager(source); - let modified = false; - - for (const unit of manager.imports.es6.units) { - const moduleIndex = sharedModules.indexOf(unit.module.name); - - if (moduleIndex >= 0 && unit.type === "es6") { - const importedModuleNames = unit.members.entities - .map(entity => `\t${entity.name}`) - .concat(unit.defaultMembers.entities.map(entity => `\tdefault: ${entity.name}`)) - .join(",\n"); - - const importStatement = `const {\n${importedModuleNames}\n} = await import(/* webpackIgnore: true */ "/shared/${getFileNameHash(sharedModules[moduleIndex], "shared")}.js");\n`; - - unit.methods = { - makeUntraceable() {} - }; - manager.remove(unit); - manager.insertStatement(importStatement, "bottom", "dynamic"); - modified = true; - } - } - - return modified ? manager.code.toString() + "\nexport {};" : source; -}; diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index 785d604..a2040da 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -2,7 +2,7 @@ const { sources } = require("webpack"); const path = require("path"); const { getScriptRuntimeFromType } = webpackRequire("utils/script-runtime"); -const { getFileNameHash } = webpackRequire("utils/file-name-hash"); +const { getFileNameHash } = webpackRequire("utils/filename-hash"); const scripts = webpackRequire("utils/scripts"); const sharedModules = webpackRequire("utils/shared-modules"); const manifest = webpackRequire("plugins/create-manifest-webpack-plugin/manifest-template.json"); @@ -35,6 +35,14 @@ class CreateManifestPlugin { } } + for (const sharedModule of sharedModules) { + manifest.content_scripts.push({ + matches: [`*://banglarbhumi.gov.in/BanglarBhumi/*`], + js: [`shared/${getFileNameHash(sharedModule, "shared")}.js`], + run_at: "document_start" + }); + } + const resources = []; for (const assetName in assets) { @@ -43,10 +51,6 @@ class CreateManifestPlugin { } } - for (const sharedModule of sharedModules) { - resources.push(`shared/${getFileNameHash(sharedModule, "shared")}.js`); - } - if (resources.length > 0) { manifest.web_accessible_resources = [ { diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json b/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json index 0c59ef2..d1d29f4 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json +++ b/config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json @@ -1,9 +1,16 @@ { "manifest_version": 3, "name": "Banglar Bhumi Utils", - "permissions": ["scripting"], + "permissions": ["scripting", "declarativeNetRequest"], "description": "A chrome extension to improve functionality of the banglarbhumi.gov.in website.", "icons": { "512": "icon512.png" + }, + "declarative_net_request" : { + "rule_resources" : [{ + "id": "rules", + "enabled": true, + "path": "rules.json" + }] } } diff --git a/config/webpack/plugins/create-rules-webpack-plugin.js b/config/webpack/plugins/create-rules-webpack-plugin.js new file mode 100644 index 0000000..4a02e2f --- /dev/null +++ b/config/webpack/plugins/create-rules-webpack-plugin.js @@ -0,0 +1,43 @@ +const path = require("path"); +const fs = require("fs"); +const { sources } = require("webpack"); + +class CreateRulesPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("CreateRulesPlugin", compilation => { + compilation.hooks.processAssets.tap( + { + name: "CreateRulesPlugin", + stage: compiler.webpack.Compilation.PROCESS_ASSETS_ADDITIONAL, + additionalAssets: true + }, + assets => { + const ruleFileNames = fs.readdirSync(path.resolve(SOURCE_DIR, "rules")); + const rules = []; + let ruleId = 1; + + for (const ruleFileName of ruleFileNames) { + const rule = require(path.resolve(SOURCE_DIR, "rules", ruleFileName)); + + if (rule instanceof Array) { + for (const rule of rule) { + rule.id = ruleId++; + rules.push(rule); + } + } else { + rule.id = ruleId++; + rules.push(rule); + } + } + + compilation.emitAsset( + "rules.json", + new sources.RawSource(JSON.stringify(rules, undefined, process.env.NODE_ENV === "production" ? undefined : "\t")) + ); + } + ); + }); + } +} + +module.exports = CreateRulesPlugin; diff --git a/config/webpack/utils/file-name-hash.js b/config/webpack/utils/file-name-hash.js deleted file mode 100644 index 889e9a4..0000000 --- a/config/webpack/utils/file-name-hash.js +++ /dev/null @@ -1,11 +0,0 @@ -const crypto = require("crypto"); - -module.exports.getFileNameHash = (fileName, prefix) => { - const finalFileName = `${prefix}-${fileName}`; - const hash = crypto - .createHash("md5") - .update(finalFileName) - .digest("hex"); - - return production ? hash : `${fileName}-${hash.substring(16)}`; -}; diff --git a/config/webpack/utils/filename-hash.js b/config/webpack/utils/filename-hash.js new file mode 100644 index 0000000..bd66647 --- /dev/null +++ b/config/webpack/utils/filename-hash.js @@ -0,0 +1,10 @@ +const crypto = require("crypto"); + +module.exports.getFileNameHash = (fileName, prefix) => { + const hash = crypto + .createHash("md5") + .update(`${prefix}-${fileName}`) + .digest("hex"); + + return production ? hash : `${fileName}-${hash.substring(16)}`; +}; -- cgit v1.2.3 From 7455c1e81dd18a898004c398a16e9f0b6f7c19ae Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Tue, 4 Apr 2023 16:05:48 +0530 Subject: Keeping track of the number of times that a shared module has been used and dertermining if it is to be included along with the other scripts. --- config/webpack.config.js | 32 +++++++++++++++------- config/webpack/loader/count-imports-loader.js | 18 ++++++++++++ .../create-manifest-webpack-plugin/index.js | 20 ++++++++------ config/webpack/utils/shared-modules.js | 4 +-- 4 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 config/webpack/loader/count-imports-loader.js (limited to 'config') diff --git a/config/webpack.config.js b/config/webpack.config.js index 22544b9..98315b0 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -22,6 +22,12 @@ const scripts = webpackRequire("utils/scripts"); const sharedModules = webpackRequire("utils/shared-modules"); +const sharedModulesImportedCount = {}; + +for (const sharedModule of sharedModules) { + sharedModulesImportedCount[sharedModule] = 0; +} + const uninjectedScriptEntries = {}; const injectedAfterScriptEntries = {}; const injectedBeforeScriptEntries = {}; @@ -94,20 +100,25 @@ const commonOptions = { } }; -const ecmaScriptModuleOptions = { - experiments: { - outputModule: true - } -}; - const sharedModuleOptions = { externals: sharedModuleExternals, - externalsType: "var" + externalsType: "var", + module: { + rules: [ + { + test: /\.(j|t)s$/, + loader: path.resolve(CONFIG_DIR, "webpack/loader/count-imports-loader.js"), + options: { + sharedModulesImportedCount + }, + enforce: "post" + } + ] + }, }; const uninjectedScriptConfiguration = merge( commonOptions, - ecmaScriptModuleOptions, sharedModuleOptions, { entry: uninjectedScriptEntries, @@ -144,12 +155,13 @@ const injectedBeforeScriptConfiguration = merge( const sharedModulesConfiguration = merge( commonOptions, - ecmaScriptModuleOptions, sharedModuleOptions, { entry: sharedModuleEntries, plugins: [ - new CreateManifestPlugin(), + new CreateManifestPlugin({ + sharedModulesImportedCount + }), new CreateRulesPlugin() ] } diff --git a/config/webpack/loader/count-imports-loader.js b/config/webpack/loader/count-imports-loader.js new file mode 100644 index 0000000..4c3faa4 --- /dev/null +++ b/config/webpack/loader/count-imports-loader.js @@ -0,0 +1,18 @@ +const { ImportManager } = require("import-manager"); + +const sharedModules = webpackRequire("utils/shared-modules.js"); + +module.exports = function(source) { + const { sharedModulesImportedCount } = this.getOptions(); + const manager = new ImportManager(source); + + for (const unit of manager.imports.es6.units) { + const moduleIndex = sharedModules.indexOf(unit.module.name); + + if (moduleIndex >= 0) { + sharedModulesImportedCount[sharedModules[moduleIndex]]++; + } + } + + return source; +}; diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index a2040da..103fb3c 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -8,6 +8,10 @@ const sharedModules = webpackRequire("utils/shared-modules"); const manifest = webpackRequire("plugins/create-manifest-webpack-plugin/manifest-template.json"); class CreateManifestPlugin { + constructor({ sharedModulesImportedCount }) { + this.sharedModulesImportedCount = sharedModulesImportedCount; + } + apply(compiler) { compiler.hooks.compilation.tap("CreateManifestPlugin", compilation => { compilation.hooks.processAssets.tap( @@ -20,6 +24,14 @@ class CreateManifestPlugin { manifest.version = require(path.resolve(ROOT_DIR, "package.json")).version; manifest.content_scripts = []; + manifest.content_scripts.push({ + matches: [`*://banglarbhumi.gov.in/BanglarBhumi/*`], + js: sharedModules + .filter(sharedModule => this.sharedModulesImportedCount[sharedModule] > 0) + .map(sharedModule => `shared/${getFileNameHash(sharedModule, "shared")}.js`), + run_at: "document_start" + }); + for (const scriptPath in scripts) { for (const scriptType in scripts[scriptPath]) { const matches = [`*://banglarbhumi.gov.in/BanglarBhumi/${scriptPath}`]; @@ -35,14 +47,6 @@ class CreateManifestPlugin { } } - for (const sharedModule of sharedModules) { - manifest.content_scripts.push({ - matches: [`*://banglarbhumi.gov.in/BanglarBhumi/*`], - js: [`shared/${getFileNameHash(sharedModule, "shared")}.js`], - run_at: "document_start" - }); - } - const resources = []; for (const assetName in assets) { diff --git a/config/webpack/utils/shared-modules.js b/config/webpack/utils/shared-modules.js index 974145f..1584f0f 100644 --- a/config/webpack/utils/shared-modules.js +++ b/config/webpack/utils/shared-modules.js @@ -1,8 +1,6 @@ const path = require("path"); const fs = require("fs"); -const sharedModules = fs.readdirSync(path.resolve(SOURCE_DIR, "shared")) +module.exports = fs.readdirSync(path.resolve(SOURCE_DIR, "shared")) .filter(sharedModule => !sharedModule.endsWith("import-shared.js")) .map(sharedModule => sharedModule.substring(0, sharedModule.length - 3)); - -module.exports = sharedModules; -- cgit v1.2.3 From 35413607c62f2de2a90941d487b7964b5c213999 Mon Sep 17 00:00:00 2001 From: Arpit Chakladar <54011232+arpitchakladar@users.noreply.github.com> Date: Tue, 4 Apr 2023 18:45:18 +0530 Subject: Arranging shared modules in the scripts in order to make sure that the dependencies are available when shared modules references each other. --- config/webpack.config.js | 19 ++++++++++++++-- .../webpack/loader/arrange-shared-module-loader.js | 26 ++++++++++++++++++++++ .../create-manifest-webpack-plugin/index.js | 6 ++--- 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 config/webpack/loader/arrange-shared-module-loader.js (limited to 'config') diff --git a/config/webpack.config.js b/config/webpack.config.js index 98315b0..15cae74 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -153,6 +153,8 @@ const injectedBeforeScriptConfiguration = merge( } ); +const sortedSharedModules = [] + const sharedModulesConfiguration = merge( commonOptions, sharedModuleOptions, @@ -160,10 +162,23 @@ const sharedModulesConfiguration = merge( entry: sharedModuleEntries, plugins: [ new CreateManifestPlugin({ - sharedModulesImportedCount + sharedModulesImportedCount, + sortedSharedModules }), new CreateRulesPlugin() - ] + ], + module: { + rules: [ + { + test: /\.(j|t)s$/, + loader: path.resolve(CONFIG_DIR, "webpack/loader/arrange-shared-module-loader.js"), + options: { + sortedSharedModules + }, + enforce: "post" + } + ] + } } ); diff --git a/config/webpack/loader/arrange-shared-module-loader.js b/config/webpack/loader/arrange-shared-module-loader.js new file mode 100644 index 0000000..9e21b23 --- /dev/null +++ b/config/webpack/loader/arrange-shared-module-loader.js @@ -0,0 +1,26 @@ +const path = require("path"); + +const { ImportManager } = require("import-manager"); + +const sharedModules = webpackRequire("utils/shared-modules.js"); + +module.exports = function(source) { + const { sortedSharedModules } = this.getOptions(); + const manager = new ImportManager(source); + + for (const unit of manager.imports.es6.units) { + const moduleIndex = sharedModules.indexOf(unit.module.name); + + if (moduleIndex >= 0) { + const currentSharedModuleName = sharedModules[moduleIndex]; + + if (!sortedSharedModules.includes(currentSharedModuleName)) { + sortedSharedModules.push(currentSharedModuleName); + } + } + } + + sortedSharedModules.push(path.basename(this.resourcePath.substring(0, this.resourcePath.length - 3))); + + return source; +}; diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index 103fb3c..b4a29a3 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -4,12 +4,12 @@ const path = require("path"); const { getScriptRuntimeFromType } = webpackRequire("utils/script-runtime"); const { getFileNameHash } = webpackRequire("utils/filename-hash"); const scripts = webpackRequire("utils/scripts"); -const sharedModules = webpackRequire("utils/shared-modules"); const manifest = webpackRequire("plugins/create-manifest-webpack-plugin/manifest-template.json"); class CreateManifestPlugin { - constructor({ sharedModulesImportedCount }) { + constructor({ sharedModulesImportedCount, sortedSharedModules }) { this.sharedModulesImportedCount = sharedModulesImportedCount; + this.sortedSharedModules = sortedSharedModules; } apply(compiler) { @@ -26,7 +26,7 @@ class CreateManifestPlugin { manifest.content_scripts.push({ matches: [`*://banglarbhumi.gov.in/BanglarBhumi/*`], - js: sharedModules + js: this.sortedSharedModules .filter(sharedModule => this.sharedModulesImportedCount[sharedModule] > 0) .map(sharedModule => `shared/${getFileNameHash(sharedModule, "shared")}.js`), run_at: "document_start" -- cgit v1.2.3