webpack-contrib / compression-webpack-plugin

Prepare compressed versions of assets to serve them with Content-Encoding
MIT License
1.41k stars 108 forks source link

TypeError: Cannot read property 'tapPromise' of undefined for webpack 5.6.0 #223

Closed raldone01 closed 3 years ago

raldone01 commented 3 years ago

Expected Behavior

The specified files are compressed.

Actual Behavior

Crash with the following error:

ERROR  TypeError: Cannot read property 'tapPromise' of undefined
TypeError: Cannot read property 'tapPromise' of undefined
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\compression-webpack-plugin\6.1.1_webpack@5.6.0\node_modules\compression-webpack-plugin\dist\index.js:349:41
    at SyncHook.eval [as call] (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:9:1)
    at SyncHook.lazyCompileHook (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\Hook.js:154:20)
    at Compiler.newCompilation (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:630:30)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:667:29
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\Hook.js:154:20)
    at Compiler.compile (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:662:28)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:321:11
    at Compiler.readRecords (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:529:11)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:318:10
    at eval (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:12:1)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\CachePlugin.js:50:13
    at _next0 (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:8:1)
    at eval (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:21:1)
    at run (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\fork-ts-checker-webpack-plugin\3.1.1\node_modules\fork-ts-checker-webpack-plugin\lib\index.js:248:13)

It appears that the processAssets hook doesn't exist?

Code

// vue.config.js
/* eslint-disable @typescript-eslint/no-var-requires, no-undef, import/no-extraneous-dependencies */
const zopfli = require('@gfx/zopfli')
const CompressionPlugin = require('compression-webpack-plugin')

module.exports = {
  filenameHashing: false,
  productionSourceMap: false,
  // publicPath: './', // Remove this if html5 history.pushState is used
  configureWebpack: config => {
    config.output.filename = '[name].js'
    config.output.webassemblyModuleFilename = 'webassembly.wasm'
    if (typeof process.env.PRODUCTION !== 'undefined')
      config.plugins.push(new CompressionPlugin({
        test: /\.(js|css|html|svg|wasm)$/,
        threshold: 2000,
        minRatio: 0.8,
        compressionOptions: {
          numiterations: 15
        },
        algorithm(input, compressionOptions, callback) {
          return zopfli.gzip(input, compressionOptions, callback)
        }
      }))
  },
  chainWebpack: config => {
    config.optimization.splitChunks(false)
  },
  css: {
    extract: {
      filename: '[name].css'
    }
  }
}

How Do We Reproduce?

pnpm run serve


Possibly related to #222.

alexander-akait commented 3 years ago

You still use webpack@4, nothing to fix on our side

raldone01 commented 3 years ago

I am pretty sure I am using webpack 5. I Patched the apply function of your plugin: I added the following line: console.log(`Reached webpack 5 code in the compresssion plugin: ${_webpack.version[0]}`)

apply(compiler) {
    const pluginName = this.constructor.name;

    if (CompressionPlugin.isWebpack4()) {
      // eslint-disable-next-line global-require
      const CacheEngine = require("./Webpack4Cache").default;

      const weakCache = new WeakMap();
      compiler.hooks.emit.tapPromise({
        name: pluginName
      }, compilation => // eslint-disable-next-line no-undefined
      this.compress(compilation, undefined, CacheEngine, weakCache));
    } else {
      // ADD LOG LINE
      console.log(`Reached webpack 5 code in the compresssion plugin: ${_webpack.version[0]}`)
      // eslint-disable-next-line global-require
      const CacheEngine = require("./Webpack5Cache").default;

      compiler.hooks.thisCompilation.tap(pluginName, compilation => {
        // eslint-disable-next-line global-require
        const Compilation = require("webpack/lib/Compilation");

        compilation.hooks.processAssets.tapPromise({
          name: pluginName,
          stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER
        }, assets => this.compress(compilation, assets, CacheEngine));
        compilation.hooks.statsPrinter.tap(pluginName, stats => {
          stats.hooks.print.for("asset.info.compressed").tap("compression-webpack-plugin", (compressed, {
            green,
            formatFlag
          }) => // eslint-disable-next-line no-undefined
          compressed ? green(formatFlag("compressed")) : undefined);
        });
      });
    }
  }

Output: See the Reached webpack 5 code in the compresssion plugin: 5 line in the following log.

C:\Users\_\Desktop\prmaster\vue\web\site>pnpm build

> @feather-ink/site@1.0.0 build C:\Users\_\Desktop\prmaster\vue\web\site
> set NODE_ENV=production && set PRODUCTION=true && node scripts/buildProd.js

-  Building for production...
Reached webpack 5 code in the compresssion plugin: 5
Starting type checking service...
Using 1 worker with 2048MB memory limit
 ERROR  TypeError: Cannot read property 'tapPromise' of undefined
TypeError: Cannot read property 'tapPromise' of undefined
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\compression-webpack-plugin\6.1.1_webpack@5.6.0\node_modules\compression-webpack-plugin\dist\index.js:350:41
    at SyncHook.eval [as call] (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:9:1)
    at SyncHook.lazyCompileHook (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\Hook.js:154:20)
    at Compiler.newCompilation (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:630:30)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:667:29
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\Hook.js:154:20)
    at Compiler.compile (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:662:28)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:321:11
    at Compiler.readRecords (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:529:11)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\Compiler.js:318:10
    at eval (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:12:1)
    at C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\webpack\4.44.2_93ca2875a658e9d1552850624e6b91c7\node_modules\webpack\lib\CachePlugin.js:50:13
    at _next0 (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:8:1)
    at eval (eval at create (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\tapable\1.1.3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:21:1)
    at run (C:\Users\_\Desktop\prmaster\vue\web\common\temp\node_modules\.pnpm\registry.npmjs.org\fork-ts-checker-webpack-plugin\3.1.1\node_modules\fork-ts-checker-webpack-plugin\lib\index.js:248:13)
 ERROR  Command failed with exit code 1.

Even if I was using webpack 4 shouldn't it work? Is webpack 4 not supported? Please consider reopening this issue.

alexander-akait commented 3 years ago

fork-ts-checker-webpack-plugin is incompatibility with webpack@5, it patched webpack and do it in wrong way, so I don't think what we should fix here, another related issue - https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/540

raldone01 commented 3 years ago

Thank you for this information. I didn't notice this at all as I was using vue and it implicitly adds the fork-ts-checker-webpack-plugin. I was really confused while checking your code. I have read the webpack plugin documentation and everything seemed correct. So it is not your fault sorry.

alexander-akait commented 3 years ago

Don't worry, plugins are power and weakness, we have been working for a long time to provide as much api as possible to avoid patching, but some plugins still use this, so developers got these problems :disappointed:

nirmalhk7 commented 3 years ago

Sorry, I'm getting the same error and I'm a bit lost. Here's the log:

TypeError: Cannot read property 'tapPromise' of undefined
    at /ROOT/PROJECT/node_modules/compression-webpack-plugin/dist/index.js:269:39
    at SyncHook.eval [as call] (eval at create (/ROOT/PROJECT/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:17:1)
    at SyncHook.lazyCompileHook (/ROOT/PROJECT/node_modules/tapable/lib/Hook.js:154:20)
    at Compiler.newCompilation (/ROOT/PROJECT/node_modules/webpack/lib/Compiler.js:631:26)
    at /ROOT/PROJECT/PROJECT/node_modules/webpack/lib/Compiler.js:667:29
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/ROOT/PROJECT/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:4:1)
    at AsyncSeriesHook.lazyCompileHook (/ROOT/PROJECT/node_modules/tapable/lib/Hook.js:154:20)
    at Compiler.compile (/ROOT/PROJECT/node_modules/webpack/lib/Compiler.js:662:28)
    at /ROOT/PROJECT/node_modules/webpack/lib/Watching.js:77:18
    at _next0 (eval at create (/ROOT/PROJECT/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:32:1)
    at eval (eval at create (/ROOT/PROJECT/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:44:1)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! PROJECT@3.0.0 start: `node scripts/start.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the PROJECT@3.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

I'm using Webpack 4.44.2 in my React app (Built over CRA). I find CompressionPlugin as a common 'webpack' way to reduce my bundle size, but whenever I add CompressionPlugin to my webpack.config.js, I get this error.

alexander-akait commented 3 years ago

https://github.com/webpack-contrib/compression-webpack-plugin/releases/tag/v7.0.0

minimum supported webpack version is ^5.1.0

tiaanduplessis commented 3 years ago

For anyone running into this issue using create-react-app version 4, it uses webpack 4 so compression-webpack-plugin needs to be locked to version 6.1.1.

ValeSauer commented 3 years ago

Same for vue-cli 4.5.11

dvcrn commented 3 years ago

I am on webpack 4 through CRA 4, but pinning the plugin to 6.1.1 is still giving me the tapPromise error. Tried a bunch of different versions as well but no luck.

TypeError: Cannot read property 'tapPromise' of undefined
    at CompressionPlugin.apply (/<root>/node_modules/compression-webpack-plugin/dist/index.js:337:27)
    at /<root>/node_modules/webpack/node_modules/enhanced-resolve/lib/ResolverFactory.js:345:10
    at Array.forEach (<anonymous>)
    at Object.exports.createResolver (/<root>/node_modules/webpack/node_modules/enhanced-resolve/lib/ResolverFactory.js:344:10)
    at ResolverFactory._create (/<root>/node_modules/webpack/lib/ResolverFactory.js:57:28)
    at ResolverFactory.get (/<root>/node_modules/webpack/lib/ResolverFactory.js:49:28)
    at NormalModuleFactory.getResolver (/<root>/node_modules/webpack/lib/NormalModuleFactory.js:521:31)
    at /<root>/node_modules/webpack/lib/NormalModuleFactory.js:165:32
    at /<root>/node_modules/webpack/lib/NormalModuleFactory.js:129:4
    at /<root>/node_modules/webpack/lib/NormalModuleFactory.js:400:5
    at AsyncSeriesWaterfallHook.eval [as callAsync] (eval at create (/<root>/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:18:1)
    at AsyncSeriesWaterfallHook.lazyCompileHook (/<root>/node_modules/tapable/lib/Hook.js:154:20)
    at NormalModuleFactory.create (/<root>/node_modules/webpack/lib/NormalModuleFactory.js:381:28)
    at /<root>/node_modules/webpack/lib/Compilation.js:1063:18
    at Semaphore.acquire (/<root>/node_modules/webpack/lib/util/Semaphore.js:29:4)
    at Compilation._addModuleChain (/<root>/node_modules/webpack/lib/Compilation.js:1062:1
alexander-akait commented 3 years ago

run npm ls webpack and you will see

dvcrn commented 3 years ago

What are you hinting at?

├─┬ compression-webpack-plugin@6.1.1
│ └─┬ webpack@4.44.2
│   └─┬ terser-webpack-plugin@1.4.5
│     └── webpack@4.44.2 deduped
└─┬ react-scripts@4.0.3
  ├─┬ @pmmmwh/react-refresh-webpack-plugin@0.4.3
  │ └── webpack@4.44.2 deduped
  ├─┬ babel-loader@8.1.0
  │ └── webpack@4.44.2 deduped
  ├─┬ css-loader@4.3.0
  │ └── webpack@4.44.2 deduped
  ├─┬ eslint-webpack-plugin@2.5.4
  │ └── webpack@4.44.2 deduped
  ├─┬ file-loader@6.1.1
  │ └── webpack@4.44.2 deduped
  ├─┬ html-webpack-plugin@4.5.0
  │ └── webpack@4.44.2 deduped
  ├─┬ mini-css-extract-plugin@0.11.3
  │ └── webpack@4.44.2 deduped
  ├─┬ optimize-css-assets-webpack-plugin@5.0.4
  │ └── webpack@4.44.2 deduped
  ├─┬ sass-loader@10.2.0
  │ └── webpack@4.44.2 deduped
  ├─┬ style-loader@1.3.0
  │ └── webpack@4.44.2 deduped
  ├─┬ terser-webpack-plugin@4.2.3
  │ └── webpack@4.44.2 deduped
  ├─┬ url-loader@4.1.1
  │ └── webpack@4.44.2 deduped
  ├─┬ webpack-dev-server@3.11.1
  │ ├─┬ webpack-dev-middleware@3.7.3
  │ │ └── webpack@4.44.2 deduped
  │ └── webpack@4.44.2 deduped
  ├─┬ webpack-manifest-plugin@2.2.0
  │ └── webpack@4.44.2 deduped
  ├── webpack@4.44.2 deduped
  └─┬ workbox-webpack-plugin@5.1.4
    └── webpack@4.44.2 deduped
alexander-akait commented 3 years ago

check global installed packages, you can use webpack-cli globally installed and npm v5 automatically install webpack v5

dvcrn commented 3 years ago

Thanks for the quick reply, no I don't have any global webpack related packages besides create-react-app, which is also pinned to the latest v4

It tries to use the emit hook which doesn't exist in my compiler.hooks

    if (CompressionPlugin.isWebpack4()) {
      // eslint-disable-next-line global-require
      const CacheEngine = require("./Webpack4Cache").default;

      const weakCache = new WeakMap();
      compiler.hooks.emit.tapPromise({
        name: pluginName
      }, compilation => // eslint-disable-next-line no-undefined
        this.compress(compilation, undefined, CacheEngine, weakCache));
    }
dvcrn commented 3 years ago

I figured it out. I added the plugin to the wrong section, so it got called with the resolver instead of compiler, sorry!

MadShura commented 3 years ago

Same for vue-cli 4.5.13. so i must use compression-webpack-plugin on version 6.1.1. ? thanks your help first !

alexander-akait commented 3 years ago

yes, for webpack v4 you need to use 6.1.1

LiuduZero commented 2 years ago

@alexander-akait

Here is my dependencies

image

And I use 6.1.1 it appear

image
alexander-akait commented 2 years ago

Please use compression-webpack-plugin@4 for webpack v4

LiuduZero commented 2 years ago

@alexander-akait thanks for your timely reply, but it not work as expect

image