Source maps and per-environment configs

webpack · Practical · 12 min

Debuggable builds and maintainable configs both depend on these choices.

Source maps map bundled code back to your sources in DevTools and error trackers. The devtool option picks the strategy, trading build speed against quality:

  • eval-cheap-module-source-map (or eval-source-map): fast rebuilds with good mappings; typical for development.
  • source-map: full, separate .map files; best quality, slowest. Use in production if you serve or upload maps.
  • hidden-source-map: produces maps without the //# sourceMappingURL comment, so browsers do not download them but you can upload them to Sentry or similar.
  • false: no maps (production default).

Words in the name mean: eval (each module wrapped in eval, fast rebuilds), cheap (line-only mappings), module (maps through loaders to original sources), inline (embedded as data URLs, never in production).

Splitting config: as configs grow, keep webpack.common.js and merge mode-specific files with webpack-merge, or export a function and branch on argv.mode. Pick one approach and stay consistent.

Environment values: read process.env in the config (Node), then expose only what the client needs through DefinePlugin or EnvironmentPlugin. dotenv-webpack loads .env files. Again: everything defined ends up in the bundle.

Example

// webpack.common.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: "./src/index.js",
  plugins: [new HtmlWebpackPlugin()],
};

// webpack.prod.js
const { merge } = require("webpack-merge");
const webpack = require("webpack");
const common = require("./webpack.common.js");
module.exports = merge(common, {
  mode: "production",
  devtool: "hidden-source-map",            // maps for Sentry, not for browsers
  output: { filename: "[name].[contenthash].js", clean: true },
  plugins: [new webpack.EnvironmentPlugin({ API_URL: "https://api.example.com" })],
});

// webpack.dev.js: merge(common, { mode: "development", devtool: "eval-cheap-module-source-map" })
// package.json: "build": "webpack -c webpack.prod.js", "dev": "webpack serve -c webpack.dev.js"

Remember

  • Dev: eval-cheap-module-source-map; prod: source-map or hidden-source-map
  • inline maps never belong in production
  • webpack-merge composes common + mode-specific configs
  • EnvironmentPlugin/DefinePlugin expose only what the client needs

Watch out for

  • Shipping eval or inline source maps in production bundles.

Check yourself

  1. Which devtool creates maps that browsers won't load but an error tracker can use?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: webpack.js.org/configuration/devtool/