Webpack problem generating sourcemaps -- only generated when a particular plugin is disabled

Viewed 98

I'm using my own custom plugin to strip some optional code from a build. This works well, but for some reason it seems to be blocking generation of source maps.

My best guess is that the fact that I'm modifying the index.js output file interferes with the ability to generate a map of for that file. If I comment out the plugin, my source maps come back.

Is there perhaps something I can do to change order of plugin execution that will fix this? Or perhaps a way to strip code from source file input streams (not from the files themselves) rather than from the generated output?

I've tried explicitly adding SourceMapDevToolPlugin to my plugins, but that didn't help.

Here's my webpack.config.cjs file:

const { Compilation, sources } = require('webpack');
const { resolve } = require('path');

module.exports = env => {
  const esVersion = env?.esver === '5' ? 'es5' : 'es6';
  const dir = env?.esver === '5' ? 'web5' : 'web';
  const chromeVersion = env?.esver === '5' ? '23' : '51';

  // noinspection JSUnresolvedVariable,JSUnresolvedFunction,JSUnresolvedFunction
  return {
    mode: env?.dev ? 'development' : 'production',
    target: [esVersion, 'web'],
    entry: {
      index: './dist/index.js'
    },
    output: {
      path: resolve(__dirname, 'dist/' + dir),
      filename: `index.js`,
      libraryTarget: 'umd',
      library: 'tbTime'
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          use: {
            loader: 'babel-loader',
            options: { presets: [['@babel/preset-env', { targets: { chrome: chromeVersion } }]] }
          },
          resolve: { fullySpecified: false }
        }
      ]
    },
    resolve: {
      mainFields: ['esm2015', 'es2015', 'module', 'main', 'browser']
    },
    externals: { 'by-request': 'by-request' },
    devtool: 'source-map',
    plugins: [
      new class OutputMonitor {
        // noinspection JSUnusedGlobalSymbols
        apply(compiler) {
          compiler.hooks.thisCompilation.tap('OutputMonitor', (compilation) => {
            compilation.hooks.processAssets.tap(
              { name: 'OutputMonitor', stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE },
              () => {
                const file = compilation.getAsset('index.js');
                let contents = file.source.source();
                // Strip out dynamic import() so it doesn't generate warnings.
                contents = contents.replace(/return import\(.*?\/\* webpackIgnore: true \*\/.*?tseuqer-yb.*?\.join\(''\)\)/s, 'return null');
                // Strip out large and large-alt timezone definitions from this build.
                contents = contents.replace(/\/\* trim-file-start \*\/.*?\/\* trim-file-end \*\//sg, 'null');
                compilation.updateAsset('index.js', new sources.RawSource(contents));
              }
            );
          });
        }
      }()
    ]
  };
};

Full project source can be found here: https://github.com/kshetline/tubular_time/tree/development

1 Answers

I think using RawSource would disable the source map. The right one for devtool is supposed to be SourceMapSource so the idea looks like following:

const file = compilation.getAsset('index.js');

const {devtool} = compiler.options;

let contents = file.source.source();
const {map} = file.source.sourceAndMap();

// your replace work
// ...

compilation.updateAsset(
  'index.js', 
  devtool
    // for devtool we have to pass map file but this the original one
    // it would be wrong since you have already changed the content 
    ? new sources.SourceMapSource(contents, 'index.js', map)
    : new sources.RawSource(contents)
);

Related