roots / palette-webpack-plugin

Generate a JSON file containing your color palette from existing Sass maps and/or Tailwind.
MIT License
46 stars 7 forks source link

Plugin emits too late when using Webpack5 #13

Closed Levdbas closed 2 years ago

Levdbas commented 3 years ago

Description

Hi, I am using this plugin for my webpack workflow. It seems that this plugin still uses the emit hook which causes the DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated. BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation. warning.

As pointed out in webpack/webpack#11425 something like this should be used to support webpack 4 and 5: webpack/webpack#11425 (comment). In my case this causes an issue with the webpack-manifest-plugin where the files generated by this plugin are not in the manifest.

Another plugin I use runs into the same issue as well and see the comment over there about the hook usage: https://github.com/WordPress/gutenberg/issues/27984

Steps to reproduce

Use this plugin in combination with the latest version of the manifest plugin. See that the manifest plugin doesn't contain the json/php file.

If needed I can make an example repo.

Expected behavior: The PHP/JSON file(s) also get added to the manifest.

Actual behavior: File(s) doesn't get added.

Reproduces how often: 100%

Versions

webpack: 5.15 palette-webpack-plugin:1.0.2 webpack-manifest-plugin: 3.0

Additional information

Any additional information, configuration or data that might be necessary to reproduce the issue.

Levdbas commented 3 years ago

Hi @Log1x ,

I found out when adding:

const webpack = require('webpack');

And expanding the code like this:

      if (webpack.version.startsWith('4')) {
        compiler.hooks.emit.tapAsync(this.constructor.name, (compilation) => {
          Object.assign(compilation.assets, {
            [this.options.output]: {
              source() {
                return palette;
              },
              size() {
                return palette.length;
              }
            }
          });

          callback();
        });
      } else {
        compiler.hooks.thisCompilation.tap(this.constructor.name, (compilation) => {
          Object.assign(compilation.assets, {
            [this.options.output]: {
              source() {
                return palette;
              },
              size() {
                return palette.length;
              }
            }
          });
        });
      }

the fisrt part only runs on Webpack4 and the second part on all other versions. This is the way suggested in https://github.com/webpack/webpack/issues/11425 and it seems to work. I got my pallete.json file written to disk with the correct contents and added to the manifest file. Not sure if anything has to change on the Mix side, but Webpack seems to work like this. Of course the code isn't DRY but since I am kind of new to this level of javascript coding I'd love to leave that to a pro.

Levdbas commented 3 years ago

Hi @Log1x ,

Can I help you driving this forward? I would like to submit a PR but since there isn't a testing suite I don't know if that is a good idea. Should be a fairly straightforward change though.