webpack-contrib/compression-webpack-plugin

Sourcemaps are not emitted when excluded with `deleteOriginalAssets` option

sibiraj-sr opened this issue · 15 comments

  • Operating System: MacOs Catalina
  • Node Version: 14.15
  • NPM Version: 6.14.8
  • webpack Version: 5.4.0
  • compression-webpack-plugin Version: 6.0.5

Expected Behavior

Sourcemap should be emitted with deleteOriginalAssets when excluded from compression.

Actual Behavior

When deleteOriginalAssets is enabled and map files are excluded from the compression. It is expected that js files are compressed with the same filename and map files are emitted as it is. but the map files are not emitted.

Code

// webpack.config.js
const CompressionPlugin = require('compression-webpack-plugin')
const FileManagerPlugin = require('filemanager-webpack-plugin')

module.exports = {
  mode: 'production',
  devtool: 'source-map',
  plugins: [
    new FileManagerPlugin({
      events: {
        onStart: {
          delete: ['dist/']
        }
      }
    }),
    new CompressionPlugin({
      filename: '[file]',
      exclude: /.map$/,
      minRatio: 10,
      deleteOriginalAssets: true
    })
  ]
}

How Do We Reproduce?

Run webapck with the given config. the dist folder should have a compressed main.js and uncompressed main.js.map, but the map file is not emitted.

Expected, remove original source means remove source maps too

Thanks @evilebottnawi .

Anyway we could achieve this? I believe this is a general expectation. If this can't be fixed. Compression has to be done outside webpack I guess.

I was just thinking deleteOriginalAssets should have been something like overwriteOriginalAssets 🤔 .

No new options, we can improve this, deleteOriginalAssets: true | false | 'keep-source-map', but it will not easy task

Sounds good. I can give it a try. Can you put out a help wanted label. Incase you are busy. Someone can take this?

Yes, but nobody will take 😄 because it OSS

I think I was wrong here, look at https://github.com/webpack-contrib/compression-webpack-plugin/blob/master/src/index.js#L303, it is easy:

if (this.options.deleteOriginalAssets) {
  if (this.options.deleteOriginalAssets === 'keep-source-map) { 
     CompressionPlugin.updateAsset(
              compilation,
              name,
              inputSource,
              // Here we have link on source map file, we should just remove it from object and webpack keep source maps
              {}
    );

  }

  CompressionPlugin.deleteAsset(compilation, name);
}

You can try, it should be really easy

Sure. Thanks for the tip.

const newAssetInfo = {
  ...info,
  related: { ...info.related, sourceMap: null },
};

CompressionPlugin.updateAsset(compilation, name, inputSource, newAssetInfo);

@evilebottnawi . removing the sourceMap property doesn't work. some value has to be set for the sourceMap else the default gets applied. I am setting it to null. Is that fine?

Let's use delete newAssetInfo.related.sourceMap, you should do it before https://github.com/webpack-contrib/compression-webpack-plugin/blob/master/src/index.js#L303 and webpack will not touch source map files

Actually thats what I did first.

if (this.options.deleteOriginalAssets) {
  if (this.options.deleteOriginalAssets === "keep-source-map") {
    const { sourceMap, ...related } = info.related || {}; // <--- Removing the source map property.
    const newOriginalInfo = {
      ...info,
      related,
    };

    CompressionPlugin.updateAsset(
      compilation,
      name,
      inputSource,
      newOriginalInfo
    );

    console.log(newOriginalInfo);
  }

  const currentAsset = CompressionPlugin.getAsset(compilation, name);
  console.log(currentAsset.info); // <--- Still having source-map property in related info

  CompressionPlugin.deleteAsset(compilation, name);
} else {
  // existing logic
}

only setting a new value to it works. else the property is added back again.

Do it work?

Setting it to null works. but I am just little not sure if it, whether it will create any unintended sideeffects?

No side effect, here simple logic, when something removed webpack automatically remove all related, so if you want keep something just remove it from related