mrkeyoor.com_
Sat 19 Sept 08:53 UTC
npmCLI & Toolingupdated 19 Sept 2026

webpack review

webpack 5.109.2 starts from one or more module entries, builds a dependency graph, and emits browser, Node, or other target assets. Loaders translate matched modules; plugins join compiler phases for HTML, CSS extraction, caching, analysis, federation, and output work. The current patch fixes aliases aimed at package directories ending in .js, CSS source-map names, expired filesystem-cache cleanup, and dead CommonJS property access. Our browser-targeted esbuild check failed because webpack itself is Node build infrastructure, not code meant to ship in a page.

50.4Mdownloads / wk
Verdict

webpack 5.109.2 took 4.3 seconds, ran a native or compile step, and left 70 packages using 31 MB in our sandbox, with 0 audit findings. Keep it where loaders, plugins, Module Federation, or exact chunk control justify that machinery; start simpler for a new ordinary app or library.

We installed it

Lab card: what happened when we installed webpackScreenshot of webpack documentation
Install✓ · 4.3s70 packages on disk · 31 MB · native build step
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does webpack install cleanly?

Yes. In a fresh container with an empty cache, npm install webpack finished in 4 seconds, leaving 70 packages and 31 MB on disk, after a native build step. npm audit reported no known vulnerabilities.

Can webpack run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does webpack work with both ESM and CommonJS?

Yes. Both import 'webpack' and require('webpack') worked in Node 22 in our run. The package is published as CommonJS.

Does webpack include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

webpack or vite: which should you use?

vite: Choose it for a new web application that benefits from opinionated development serving and defaults. webpack 5.109.2 took 4.3 seconds, ran a native or compile step, and left 70 packages using 31 MB in our sandbox, with 0 audit findings.

When should you not use webpack?

A new conventional web app values quick startup and small configuration. Vite usually reaches that baseline with fewer decisions.

API stability4/5Webpack 5.109.2 preserves the version 5 configuration model for entries, output, module rules, plugins, optimization, targets, resolution, and cache settings. The patch corrects resolver, cache, source-map, dead-code, and type details without changing common config shapes. Custom plugins bind to compiler and compilation hooks, so they carry more upgrade risk than declarative rules and deserve compatibility tests on each update.
Docs4/5The official webpack 5 site separates concepts, configuration fields, guides, loaders, plugins, caching, code splitting, targets, optimization, and migration material. Most options include types and examples, and the concepts page explains the graph model. Search results still surface version 4 recipes and third-party loader behavior, so users must verify the webpack version and follow each loader's own current documentation before adopting a configuration.
Maintenance5/5The unarchived repository was pushed on August 26, 2026, and GitHub reported 132 open issues and pull requests. Version 5.109.2 shipped July 28 with fixes for .js directory aliases, CSS source maps, persistent-cache cleanup, dead CommonJS access, target reporting, and generated type annotations. Active patch work continues inside webpack 5 without requiring teams to move to an unfinished new major.
Ecosystem5/5npm counted 56,177,340 downloads from August 19 through 25, 2026, while GitHub showed 65,962 stars. Loaders and plugins cover Babel, TypeScript, CSS, Sass, HTML, assets, compression, analysis, frameworks, and federation. That catalog can preserve mature application investments, but every extra integration has an independent release schedule and may hold back webpack, Node, or framework upgrades.

Discussed on

  1. hnTurbopack, the successor to Webpack626 points
  2. hnIntroducing Webpack Dashboard441 points
  3. hnOur long term plan to make GitLab as fast as possible with Vue and Webpack374 points
  4. hnWhy we switched from Webpack to Vite355 points
  5. hnWebpack 5250 points

Use it if

  • An existing application depends on webpack loaders, plugins, framework adapters, or Module Federation.
  • One compiler must coordinate JavaScript, CSS, assets, WebAssembly, code splitting, and custom build hooks.
  • A platform team needs precise control over chunks, runtime code, externals, targets, resolution, and emitted filenames.
  • Large repeat builds justify a persistent filesystem cache whose invalidation inputs the team can maintain.
Skip it if

Setup reality

We installed webpack 5.109.2 in a fresh Node 22 Bookworm sandbox. npm took 4.3 seconds, ran a native or compile step, and left 70 packages occupying 31 MB. webpack itself was 9,988 KB unpacked with 20 direct dependencies and no peers. npm audit reported 0 known vulnerabilities. The package declares Node >=10.13.0, ships as CommonJS without an exports map, bundles declarations, and loaded through require() and ESM import.

The command-line executable lives in webpack-cli, a separate package that webpack does not list as a peer. Most direct setups add webpack.config.js and specify mode, entry, output, target, rules, plugins, and resolution. Loader order is operational: use arrays execute from the final loader toward the first. Framework CLIs may generate or merge this configuration, so check their supported override path before adding a standalone file.

DefinePlugin performs source replacement at build time. Any credential placed there becomes readable in emitted JavaScript, so restrict it to public constants. Filesystem cache keys need the lockfile, Node version, webpack stack, config, and any local generators that affect output. Version 5.109.2 now removes unreferenced and expired cache packs more consistently, but CI still has to restore a compatible cache directory.

Dynamic import creates asynchronous chunks. Tree shaking works best with ESM, production optimization, and accurate sideEffects metadata; one CommonJS boundary or incorrect package metadata can retain code. Generate stats when output is surprising. Our attempt to bundle webpack itself for browsers failed, matching its Node-only compiler role. Keep webpack, its CLI, loaders, and plugins in development dependencies unless a production server invokes compilation at runtime, which also expands deployment weight and attack surface.

Patterns

Build one browser entry bundle-browser-entry

// webpack.config.js
const path = require('node:path');
module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: { path: path.resolve(__dirname, 'dist'), filename: 'app.js', clean: true },
};

output.clean removes stale assets inside the configured output directory before emitting the next build.

Run development and production builds add-cli-scripts

{
  "scripts": {
    "build": "webpack --mode production",
    "watch": "webpack --mode development --watch"
  }
}

Install webpack-cli separately because the core package has no CLI peer dependency.

Load CSS imports process-imported-css

module.exports = {
  module: { rules: [{ test: /\.css$/i, use: ['style-loader', 'css-loader'] }] },
};

Loaders execute right to left, so css-loader resolves CSS first and style-loader handles its result.

Copy imported files emit-static-assets

module.exports = {
  module: { rules: [{ test: /\.(png|svg|woff2)$/i, type: 'asset/resource' }] },
};

asset/resource emits a file and exports its final URL without the old file-loader package.

Create an asynchronous chunk lazy-load-feature

button.addEventListener('click', async () => {
  const { openEditor } = await import(
    /* webpackChunkName: "editor" */ './editor.js'
  );
  openEditor();
});

Older browser targets need Promise support for webpack's dynamic import runtime.

Replace a build-time value define-public-constant

const webpack = require('webpack');
module.exports = {
  plugins: [
    new webpack.DefinePlugin({ __API_ORIGIN__: JSON.stringify(process.env.PUBLIC_API_ORIGIN) }),
  ],
};

DefinePlugin writes the replacement into emitted code. A server credential placed here becomes public.

Enable filesystem caching persist-build-cache

module.exports = {
  cache: {
    type: 'filesystem',
    buildDependencies: { config: [__filename] },
  },
};

List local config and generator files whose changes must invalidate cached modules, and key CI caches on the lockfile and Node version.

Create production source maps emit-source-maps

module.exports = { mode: 'production', devtool: 'source-map' };

Public .map files can expose source. Upload them privately when only an error tracker should read them.

Leave a server package unbundled externalize-node-package

module.exports = {
  target: 'node',
  externals: { pg: 'commonjs pg' },
};

The deployment must provide pg at runtime because the output retains a require call.

Generate analyzer input export-build-stats

npx webpack --profile --json > stats.json

Stats reveal duplicated modules and unexpected chunks, but the file can expose source paths and module names.

Emit separate page bundles build-multiple-entries

module.exports = {
  entry: { admin: './src/admin.js', shop: './src/shop.js' },
  output: { filename: '[name].[contenthash].js' },
};

contenthash supports long cache lifetimes, and HTML generation must reference each newly emitted filename.

Read targets from Browserslist target-browser-policy

// webpack.config.js
module.exports = { target: 'browserslist' };

// package.json
// "browserslist": [">0.5%", "not dead"]

Webpack target controls its runtime assumptions. Transpiling application syntax can still require Babel or another loader.

Alternatives

PackageRegistryPick it when
vitenpmChoose it for a new web application that benefits from opinionated development serving and defaults.
rollupnpmChoose it for libraries and builds whose output model centers on ESM.
esbuildnpmChoose it when compilation speed and compact configuration matter more than webpack plugin compatibility.
rspacknpmChoose it when an existing webpack-shaped stack needs a faster Rust-based compiler and its plugins are compatible.

More cli & tooling guides

commander · chalk · typescript · esbuild · yargs · click · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.