webpack: Banner plugin is broken in production mode

Do you want to request a feature or report a bug?

Bug.

What is the current behavior?

Configuration:

module.exports = {
  plugins: [
    new webpack.BannerPlugin({
      banner: "foobar",
    }),
  ],
};

If compiled in production mode, the banner doesn’t appear in the output. It does appear in development and none modes.

If the current behavior is a bug, please provide the steps to reproduce.

See above. Attach the plugin to a build to test.

What is the expected behavior?

The banner should appear in the build.

If this is a feature request, what is motivation or use case for changing the behavior?

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.

Webpack 4.0.1.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 19
  • Comments: 31 (15 by maintainers)

Commits related to this issue

Most upvoted comments

Solution is here : webpack/webpack-cli#312

usage of variables is lost in production builds if you use this method, not a “real” fix

@Venipa: If by “usage of variables” you mean using a Function value for the banner property, I was able to workaround it with the following:

let inUserScriptHeader = false;

module.exports = {
  plugins: [
    new BannerPlugin({
      banner: ({ chunk }) => `// ==UserScript==
// @name ${chunk.name}
// ==/UserScript==`,
    }),
  ],
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          output: {
            comments: (_, comment) => {
              if (comment.value === " ==UserScript==") {
                inUserScriptHeader = true;
              } else if (comment.value === " ==/UserScript==") {
                inUserScriptHeader = false;
                return true;
              }

              return inUserScriptHeader;
            }
          }
        }
      })
    ]
  }
};

BannerPlugin doesn’t do magic, just inject comments/code in code…

Shouldn’t BannerPlugin be designed to just add banners and nothing else? Inserting code via BannerPlugin sounds like a hack for me and the whole discussion confirms that the current behavior - adding the banner before the minification - is not good for adding banners.

why closed, don’t see a simple solution

Maybe the option could be introduced, which would control when the banner will be added before or after minification?

Anyway, webpack.BannerPlugin should add a banner after the uglification takes place. Consider a case when each source file contains license at the beginning, but you want to have only one license in the bundle. That’s impossible right now. I had to change the final banner a little bit and add a regexp for webpack.BannerPlugin to preserve only the final license banner and remove other banners with same messages.

I don’t understand why this issue has been closed. This issue still exists in webpack v5.

I still happens with we in using webpack v5. Furthermore, @matzeeable solution did not preserve the comment injected by BannerPlugin for me. It just kept the comments on the licence files, but not on the js files. I use craco, by the way =).

I just wanted to use this plugin so I could see the App’s version when consuming the js chunks along with module federation.

Solved it this way by excluding @preamble from being extracted:

const config = {
    optimization: {
        minimizer: [
            // https://git.io/Jo5g3
            new TerserWebpackPlugin({
                terserOptions: {
                    compress: {
                        passes: 2
                    }
                },
                // https://git.io/Jo5Vf
                extractComments: (astNode, comment) => {
                    return (
                        (comment.type === "comment2" || comment.type === "comment1") &&
                        /@preserve|@lic|@cc_on|^\**!/i.test(comment.value) &&
                        comment.value.indexOf("@preamble") === -1
                    );
                }
            }),
            "..."
        ]
    },
    plugins: [
        new BannerPlugin({
            banner: "My banner\n\n@preamble"
        })
    ]
};

We need the new options for banner plugin, afterMinize: true | false and use other hook, feel free to send a PR, we have the same request for CSS too https://github.com/webpack-contrib/css-minimizer-webpack-plugin/issues/64

@ma2ciek BannerPlugin does not only inject comments. It can be used to inject JavaScript using raw option. That’s why it is ran before minification.

How do you fix this if you want license banners removed and your own banner, though?

EDIT: Now that I think about it, it probably could be achieved somehow with extractComments