How to produce readable stack trace in production Webpack build from source maps and minified bundles? Are source maps included in code split bundles?

Viewed 1923

Hi I am learning React in a Typescript environment with Webpack and trying to display error stack trace in production.

I have enabled sourceMaps in tsconfig.json and have dev-tools: source-map setting in my production webconfig. I am performing minification using the Terser plugin with source maps enabled as follows:

optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        sourceMap: true,
....

I can see that the source map url is included as a comment at the end of a minified bundle file, e.g.

//# sourceMappingURL=course-list.6ccadc639a7a607e7b4e.bundle.js.map%  

I can also see that the minified map files are produced in the dist folder as expected. However, when I display a stack trace and error message for an Error thrown, the message is unreadable using minified content.

http://localhost:8080/vendors~course-list.3042c44300bc08021f63.bundle.js:2:6029
http://localhost:8080/vendors~course-list.3042c44300bc08021f63.bundle.js:2:5067

in w in b in withRouter(b) in e in e in Suspense in div in e in e in S

How do I display readable stack trace for users in production environments?

Further Information 1 I am testing that a network connection error is thrown (in production environment) by the axios library when trying to connect to a local rest API endpoint. If I run in a development environment I can see further details in stack trace relating to Network connection failure. Details are sparse and garbled in production environment with minified bundle and devtool option set to source-map.

The bundle report generated from the production build is as follows: bundle report

Further Information 2 I have used code splitting at the route level to create some bundles. Running source-map-explorer for the route code split bundle that throws the error:

npx source-map-explorer dist/vendors~course-list.3042c44300bc08021f63.bundle.js

results in error message:

dist/vendors~course-list.3042c44300bc08021f63.bundle.js
  Unable to map 265/14948 bytes (1.77%)

This is the bundle that contains axios library to make the REST API request. The source map analyse report for the bundle is illustrated in the image below: enter image description here

My production webpack config is as follows:

module.exports = merge(config.CommonConfig, {
  devtool: 'source-map',
  mode: 'production', // https://webpack.js.org/configuration/mode/#mode-production
  module: {
    rules: [
      {
        // link css modules
        test: /\.css$/,
        include: path.resolve(constants.dir.SRC, 'app'),
        use: [
          { loader: MiniCssExtractPlugin.loader },
          {
            loader: require.resolve('css-loader'),
            options: {
              modules: {
                localIdentName: '[hash:base64]',
              },
              importLoaders: 1,
              sourceMap: true,
            },
          },
        ],
      },
      {
        // link global css module in styles
        test: /\.css$/,
        include: path.resolve(constants.dir.SRC, 'styles'),
        use: [
          { loader: MiniCssExtractPlugin.loader },
          {
            loader: require.resolve('css-loader'),
            options: { sourceMap: true },
          },
        ],
      },
    ],
  },
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        sourceMap: true,
        terserOptions: {
          output: {
            comments: false,
          },
          extractComments: false,
        },
      }),
      new OptimizeCSSAssetsPlugin(),
    ],
  },
  plugins: [
    // inject react and react-dom CDN to scripts in index.html
    new WebpackCdnPlugin({
      modules: {
        react: [
          { name: 'react', version: 16, path: 'umd/react.production.min.js' },
          {
            name: 'react-dom',
            version: 16,
            path: 'umd/react-dom.production.min.js',
          },
        ],
      },
      prod: true,
    }),

    // extract css to file, minimize in optimization
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
      ignoreOrder: false,
    }),

    // use brotli compression to compress resources larger than ~10K
    new CompressionPlugin({
      filename: '[path].br[query]',
      algorithm: 'brotliCompress',
      test: /\.(css|gif|html|jpg|jpeg|js|png|svg|)$/,
      compressionOptions: { level: 11 },
      threshold: 10240,
      minRatio: 0.8,
      deleteOriginalAssets: false,
    }),

    // use gzip compression to compress resources larger than ~10K
    new CompressionPlugin({
      filename: '[path].gz[query]',
      algorithm: 'gzip',
      test: /\.(css|gif|html|jpg|jpeg|js|png|svg|)$/,
      compressionOptions: { level: 9 },
      threshold: 10240,
      minRatio: 0.8,
      deleteOriginalAssets: false,
    }),
  ],
  externals: [
    // add libraries to be excluded from bundle add here
    // for example loaded from CDN
    { react: 'React' },
    { 'react-dom': 'ReactDOM' },
  ],
});
0 Answers
Related