Gathering detailed insights and metrics for webpack-target-webextension
Gathering detailed insights and metrics for webpack-target-webextension
Gathering detailed insights and metrics for webpack-target-webextension
Gathering detailed insights and metrics for webpack-target-webextension
WebExtension Target for Webpack 5. Supports code-splitting and HMR.
npm install webpack-target-webextension
Typescript
Module System
Min. Node Version
JavaScript (99.03%)
TypeScript (0.97%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
48 Stars
97 Commits
8 Forks
3 Watchers
4 Branches
5 Contributors
Updated on Apr 29, 2025
Latest Version
2.1.3
Package Id
webpack-target-webextension@2.1.3
Unpacked Size
70.06 kB
Size
17.85 kB
File Count
23
Published on
Dec 19, 2024
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
This webpack 5 plugin (works on rspack!) provides reasonable presets and fixes things that don't work for a Web Extension.
If you are looking for webpack 4 support, please install 0.2.1. Document for 0.2.1.
The list of things we fixed in this plugin:
If you are familiar with WebExtension and webpack, this is a quick guide on how to configure this plugin and your manifest.json
.
webpack.config.js
1module.exports = { 2 context: __dirname, 3 entry: { 4 background: join(__dirname, './src/background/index.js'), 5 content: join(__dirname, './src/content-script/index.js'), 6 options: join(__dirname, './src/options-page/index.js'), 7 }, 8 output: { 9 path: join(__dirname, './dist'), 10 }, 11 plugins: [ 12 new HtmlPlugin({ filename: 'options.html', chunks: ['options'] }), 13 new WebExtension({ 14 background: { pageEntry: 'background' }, 15 }), 16 new CopyPlugin({ 17 patterns: [{ from: 'manifest.json' }], 18 }), 19 ], 20}
manifest.json
1{ 2 "manifest_version": 3, 3 "name": "Your extension", 4 "version": "1.0.0", 5 "background": { 6 "service_worker": "./background.js" 7 }, 8 // ⚠ Those files can be accessed by normal websites too. 9 "web_accessible_resources": [ 10 { 11 "resources": ["/*.js"], 12 "matches": ["<all_urls>"] 13 }, 14 // only needed for development (hot module reload) 15 { 16 "resources": ["/hot/*.js", "/hot/*.json"], 17 "matches": ["<all_urls>"] 18 } 19 ], 20 "content_scripts": [ 21 { 22 "matches": ["<all_urls>"], 23 "js": ["./content.js"] 24 } 25 ], 26 "permissions": ["scripting"], 27 "host_permissions": ["<all_urls>"], 28 "options_ui": { 29 "page": "options.html", 30 "open_in_tab": true 31 } 32}
You can also refer to ./examples/react-hmr which is a working project.
To load an async chunk in content scripts, you need to configure the chunk loader.
import()
Compatibility: at least Firefox 89 and Chrome 63.
To disable this loader, you can set output.environment.dynamicImport
to false
.
You MUST add your JS files to web_accessible_resources
in the manifest.json
, otherwise the import()
call will fail.
[!WARNING] Adding files to
web_accessible_resources
allows normal websites to fetch them.
chrome.tabs.executeScript
(Manifest V2 only)This method requires options.background.pageEntry
to be configured and options.background.classicLoader
is not false (it defaults to true).
chrome.scripting.executeScript
(Manifest V3 only)chrome.tabs.executeScript
when there is no chrome.scripting
."scripting"
permission in the manifest.json
.options.background
to be configured.options.background.classicLoader
is not false (defaults to true).You must configure the content script by dynamic import()
. You also need to set output.publicPath
manually (like chrome-extension://jknoiechepeohmcaoeehjaecapdplcia/
, the full URL is necessary).
[!WARNING] This plugin does not work with
"background.type"
inmanifest.json
set to"module"
(native ES Module service worker). Tracking issue: #24
Code splitting is supported for background service workers, but it will load all chunks initially. See https://bugs.chromium.org/p/chromium/issues/detail?id=1198822.
To turn off this fix, set options.background.eagerChunkLoading
to false.
If you turn off this fix, loading an async chunk will be a runtime error.
[!WARNING] It's not possible to support HMR for Manifest V3 background workers.
You will see
"[HMR] Update check failed: NetworkError: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'chrome-extension://...' failed to load."
See https://bugs.chromium.org/p/chromium/issues/detail?id=1198822
[!WARNING] The HMR WebSocket server might be blocked by the Content Security Policy, which prevents the reset of the code from being executed. Please disable HMR if you experience this problem.
This plugin fixes Hot Module Reload and provides reasonable defaults for DevServer.
Please set devServer.hot
to false
to disable HMR support.
To disable this fix, set options.hmrConfig
to false.
You need to add *.json
to your web_accessible_resources
to make HMR work.
Example: Draw UI in the content scripts with React and get React HRM. ./examples/react-hmr
[!WARNING] No
eval
based source map is available in Manifest v3.
[!WARNING] DO NOT add
unsafe-eval
to your CSP in production mode!
To use source maps based on eval
, you must use Manifest v2 and have script-src 'self' 'unsafe-eval';
in your CSP (content security policy).
This plugin fixes the public path whether the output.path
is set or not.
Example:
1new WebExtensionPlugin({
2 background: { pageEntry: 'background', serviceWorkerEntry: 'background-worker' },
3})
1export interface BackgroundOptions { 2 noDynamicEntryWarning?: boolean 3 /** 4 * The entry point of the background page. 5 */ 6 pageEntry?: string 7 /** 8 * The entry point of the service worker. 9 */ 10 serviceWorkerEntry?: string 11 /** 12 * Only affects Manifest V3. 13 * 14 * Load all chunks at the beginning 15 * to workaround the Chrome bug 16 * https://bugs.chromium.org/p/chromium/issues/detail?id=1198822. 17 * 18 * NOT working for rspack. 19 * 20 * @defaultValue true 21 */ 22 eagerChunkLoading?: boolean 23 /** 24 * Add the support code that uses 25 * `chrome.scripting.executeScript` (MV3) or 26 * `chrome.tabs.executeScript` (MV2) when 27 * dynamic import does not work for chunk loading 28 * in the content script. 29 * @defaultValue true 30 */ 31 classicLoader?: boolean 32 /** 33 * Add a try-catch wrapper around the entry file of serviceWorkerEntry 34 * so if the initial code throws, you can still open the console of it. 35 * 36 * Does not work in rspack. 37 * 38 * @defaultValue true 39 */ 40 tryCatchWrapper?: boolean 41}
Default value: true
This option provides reasonable defaults for HMR and DevServer.
If you experienced a compatibility issue with any of the following plugins, please this option:
This is an experimental API. API might change at any time. Please provide feedback!
If you don't strictly rely on run_at, set it as the following
1export default { 2 entry: { 3 myContentScript: 'src/contentScript.ts', 4 }, 5 // ... 6 plugins: [ 7 // ... 8 new WebExtensionPlugin({ 9 // ... 10 experimental_output: { 11 myContentScript: 'cs.js' 12 }, 13 }) 14 ] 15}
1{ 2 // ... 3 "content_scripts": [ 4 { 5 "matches": ["..."], 6 "js": ["cs.js"] 7 } 8 ] 9}
If you cannot use asynchronous loading, set up like below.
This setup requires you to have a manifest.json
being emitted.
1export default { 2 entry: { 3 myContentScript: 'src/contentScript.ts', 4 }, 5 // ... 6 plugins: [ 7 // ... 8 new WebExtensionPlugin({ 9 // ... 10 experimental_output: { 11 myContentScript: (manifest, list) => { 12 manifest.content_scripts[0].js = list 13 } 14 }, 15 }) 16 ] 17}
1export default { 2 entry: { 3 background: 'src/background.ts', 4 }, 5 // ... 6 plugins: [ 7 // ... 8 new WebExtensionPlugin({ 9 // ... 10 experimental_output: { 11 background: { 12 file: 'sw.js', 13 touch(manifest, file) { 14 manifest.background.service_worker = file 15 } 16 }, 17 }, 18 }) 19 ] 20}
This is an experimental API. API might change at any time. Please provide feedback!
This option helps the initial chunk loading of content scripts/the background service worker,
usually needed when optimization.runtimeChunk
or optimization.splitChunks.chunks
is used.
This option accepts an object, where the keys are the entry name, and the value is described below.
This option replaces the HTMLWebpackPlugin where the background service worker and content scripts do not use HTML to load files.
If the value is a string
(an output file name), for content scripts, it creates an extra
entry file to load all initial chunks asynchronously via dynamic import.
This asynchronous loading behavior is limited to the platform limit and breaks
run_at.
If the value is a string
(an output file name), for the background service worker (specified
via options.background.serviceWorkerEntry
), it creates an extra entry file to load all
initial chunks synchronously.
The file name specified MUST NOT be any existing file.
If the value is a function
((manifest: any, chunks: string[]) => void
), it requires
a "manifest.json" in the emitted files and lets you edit it on the fly to include all
the initial chunks. This option does not apply to the background service worker because
manifest.json
does not accept multiple files.
If the value is an object
({ file: string; touch(manifest: any, file: string): void }
),
it generates a new file (see the behavior of string
above) and provides a callback to
edit the manifest.json
(see the behavior of function
above).
If the value is false
, it asserts that this entry does not have more than one initial file,
otherwise, it will be a compile error.
If the value is undefined
, it silences the warning for the background service worker.
You can also change your configuration to avoid optimization.runtimeChunk
or optimization.splitChunks.chunks
,
in this case, webpack only generates 1 initial file so you don't need this option.
Rspack support is provided as a best effort, please open an issue if you have encountered any problems.
Here are known issues:
experimental_output
is necessary for chunk splitting.No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
Found 2/30 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
17 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More