Webpack Target WebExtension

raw JSON →
2.1.3 verified Sat Apr 25 auth: no javascript

A Webpack 5 plugin (also works with Rspack) that provides presets and fixes for building Web Extensions (Chrome, Firefox). It enables code splitting via dynamic import() and classic loaders, Hot Module Reload, and correct public path handling. Current stable version is 2.1.3, released under the MIT license. Key differentiators: supports Manifest V2 and V3, works with both webpack and rspack, and includes built-in chunk loaders for content scripts and background scripts. Note: webpack 4 users must use version 0.2.1.

error Error: ChunkLoadError: Loading chunk 0 failed. (error: TypeError: Failed to fetch dynamically imported module: ...)
cause Dynamic import() in content script is blocked because JS files are not listed in web_accessible_resources.
fix
Add '"resources": ["/*.js"], "matches": ["<all_urls>"]' to your manifest.json's web_accessible_resources.
error TypeError: Cannot read properties of undefined (reading 'pageEntry')
cause The plugin requires a background page entry when using classic loader for background scripts.
fix
Configure the WebExtension plugin with background: { pageEntry: 'background' } in webpack config, and ensure the background entry exists.
error Error: webpack-target-webextension requires webpack >=5.0.0
cause Installed version incompatible with webpack 4.
fix
Downgrade to version 0.2.1: 'npm install webpack-target-webextension@0.2.1'.
error Module not found: Error: Can't resolve 'webpack-target-webextension'
cause Package not installed or not in node_modules.
fix
Run 'npm install webpack-target-webextension --save-dev'.
gotcha All JS files must be added to web_accessible_resources for dynamic import() to work in content scripts. This allows normal websites to fetch those files.
fix Add '/*.js' to web_accessible_resources in manifest.json with appropriate matches.
gotcha For Manifest V3, if you use chrome.scripting.executeScript, you must have 'scripting' permission and options.background configured with classicLoader not false.
fix Include 'scripting' in permissions and set background: { pageEntry: 'background' } with no classicLoader: false.
gotcha The plugin is designed for webpack 5; using it with webpack 4 will fail. Pin to version 0.2.1 for webpack 4 support.
fix Use 'npm install webpack-target-webextension@0.2.1' for webpack 4.
gotcha Hot Module Reload (HMR) requires additional web_accessible_resources entries for /hot/*.js and /hot/*.json files during development.
fix Add '"resources": ["/hot/*.js", "/hot/*.json"], "matches": ["<all_urls>"]' to web_accessible_resources.
gotcha The plugin's chunk loader for content scripts uses dynamic import() by default, which requires Firefox 89+ or Chrome 63+.
fix For older browsers, set output.environment.dynamicImport to false to use alternative methods, or use the classic loader.
npm install webpack-target-webextension
yarn add webpack-target-webextension
pnpm add webpack-target-webextension

Minimal webpack config for a Web Extension using the plugin. Sets up entries for background, content script, and options page, with HTML generation and manifest copy.

const path = require('path');
const HtmlPlugin = require('html-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const WebExtension = require('webpack-target-webextension');

module.exports = {
  context: __dirname,
  entry: {
    background: './src/background/index.js',
    content: './src/content-script/index.js',
    options: './src/options-page/index.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
  },
  plugins: [
    new HtmlPlugin({ filename: 'options.html', chunks: ['options'] }),
    new WebExtension({
      background: { pageEntry: 'background' },
    }),
    new CopyPlugin({
      patterns: [{ from: 'manifest.json' }],
    }),
  ],
};