Copy-webpack-plugin: Uglify output

Created on 12 Jan 2016  路  23Comments  路  Source: webpack-contrib/copy-webpack-plugin

I'm using copy-webpack-plugin to copy a file into a public directory, and I'm hoping to have it minified in the process (during production builds).

I'm using webpack.optimize.UglifyJsPlugin, but that only operates on the output of chunks, and the assets of copy-webpack-plugin don't belong to chunks so they aren't minified.

Do you know of a way to get Webpack to minify Javascript files copied using this plugin?

Most helpful comment

let uglifyJsContents = require('uglify-js');
module.exports = {
   // .... 
    plugins: [
        new CopyWebpackPlugin([{
            from: './src/static/',
            to: '../static',
            transform: function(fileContent, path) {
                     return uglifyJsContents.minify(fileContent.toString()).code.toString()
            }
        }])
    ]
};

Use if you are coping JS file and want to minify

All 23 comments

I haven't found how to convert these assets to chunks. You're right that this should fix the issue (and possibly showing changes during webpack --watch). Any references (or a PR!) would be helpful

This is an issue with UglifyJsPlugin rather than copy-webpack-plugin. copy-webpack-plugin operates on assets, i.e. individual files. Chunks are code fragments and do not have 1-to-1 relation with files.

What you can do is: add a custom plugin that iterates through each asset in stat.compilation.assets and decorates the source method (and size) using webpack.optimize.UglifyJsPlugin or whatever else processor. However, this is outside the scope of copy-webpack-plugin.

Could the plugin provide the possibility to define a transform method as part of the options, which would be called with the contents of each copied file?

You still wouldn't be able to use the webpack loaders this way, but you would be able to use the underlying modules to do the transformation, e.g. uglify-js.

Made a basic proof-of-concept here: https://github.com/jstougaard/copy-webpack-plugin

any update on minifying the copied files at build ?

Could the plugin provide the possibility to define a transform method as part of the options, which would be called with the contents of each copied file?

Yes, thats possible. PR is welcome.

When is this feature published to npm?

The transform feature is included in v4.0.0, which is now pushed to npm.

I saw the transform property there:

function(content, path) {
  return content;
}

Does it mean that I need to call new webpack.optimize.UglifyJsPlugin() here in order to get the file uglified?

This is my current settings
And how to uglify that content here easily?
Couldn't get it work.
Or do I need to use a separate a lib to do this, and invoke them here?
Seems can't use UglifyJsPlugin(), because it doesn't take a single file parameter
Thanks

new CopyWebpackPlugin([
            {
                from: 'client/static/index.html',
                transform: function(fileContent, path) {
                    return fileContent;
                },
                to: 'index.html' }
        ]),

Did you get your answer on this?

@Albert-Gao @pbrain19
I also have the same requirement. I use jsonminify

const jsonminify= require('jsonminify');

module.exports = {
   // .... 
    plugins: [
        new CopyWebpackPlugin([{
            from: './src/static/',
            to: '../static',
            transform: function(fileContent, path) {
                let pattJSON = /\.json$/gi; // filter json file
                if(pattJSON.test(path)){
                    return jsonminify(fileContent.toString());
                }
                return fileContent;
            }
        }])
    ]
};
let uglifyJsContents = require('uglify-js');
module.exports = {
   // .... 
    plugins: [
        new CopyWebpackPlugin([{
            from: './src/static/',
            to: '../static',
            transform: function(fileContent, path) {
                     return uglifyJsContents.minify(fileContent.toString()).code.toString()
            }
        }])
    ]
};

Use if you are coping JS file and want to minify

@kumarranjansingh how do you handle ECMAScript 2015 or above transformation in this case? As uglifyjs cannot handle it. Thx for your help

Hey @natterstefan, you should have a look at terser to replace uglify js. It is basically used the same way.

Good luck ;)

I'm running webpack 4.29.6, copy-webpack-plugin 0.1.19 & ugilfy-js-webpack-plugin 2.0.1
The solution mentioned by @kumarranjansingh gave me an error. P.S. Thanks @kumarranjansingh for posting the solution.
Once I made a slight modification, it worked like a charm. Posting here in case this helps someone else.

let uglifyJsContents = require('uglify-js'); module.exports = { // .... plugins: [ new CopyWebpackPlugin([{ from: './src/static/', to: '../static', transform: function(fileContent, path) { return uglifyJsContents.minify(fileContent.toString()).code } }]) ] };

Will be fixed in next release

const terser = require('terser');

module.exports = {
  plugins: [
    new CopyWebpackPlugin([
      {
        from: 'src/api/',
        to: 'output/api/',
        transform: content => terser.minify(content.toString()).code
      }
    ])
  ]
};

I have been unable to reproduce this solution for my react project created using create-react-app
My project folder structure:

|--|--src
|--|--public
|--package.json
|--webpack.config.js
|--craco.config.js

my webpack file plugin code looks like :

module.exports = {
...
plugins: [
    new Copy({
      patterns:[
        {
          from: 'public/',
          to: 'public/',
          transform: content => terser.minify(content.toString()).code
      }
      ]
    }),
   ...
  ]
}

I get the following error trying this out.

$ webpack
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type undefined
    at Function.from (buffer.js:207:11)
    at writeOut (path/to/folder/web-app-frontend/node_modules/webpack/lib/Compiler.js:457:26)
    at /path/to/folder/web-app-frontend/node_modules/mkdirp/index.js:30:20
    at FSReqWrap.args [as oncomplete] (fs.js:140:20)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

What could I be doing wrong here?

You don't need it anymore (update copy-webpack-plugin and terser-webpack-plugin to latest), now we use hook before terser, so all JS files will be uglified in the production mode

You don't need it anymore (update copy-webpack-plugin and terser-webpack-plugin to latest), now we use hook before terser, so all JS files will be uglified in the production mode

@evilebottnawi I am using the latest copy-webpack-plugin, latest terser-webpack-plugin, and latest cssnano-webpack-plugin. None of the copied files are getting picked up for minification automatically. Is there an example somewhere with a working configuration? Otherwise, I'm also going to have to rely on the transform option.

@ZDTaylor terser-webpack-plugin is 3 version? cssnano-webpack-plugin is not official and will not work due https://github.com/lneveu/cssnano-webpack-plugin/blob/master/src/index.js#L26, it is invalid hook

Yes, terser-webpack-plugin is 3.0.6, copy-webpack-plugin is 6.0.3.
The relevant configs are here:
webpack.config.base.js:

optimization: {
            minimize: localEnv.production ? true : false,
            minimizer: [
                new TerserPlugin({
                    cache: true,
                    parallel: true,
                    terserOptions: {
                        compress: false,
                        ecma: 5,
                        mangle: true,
                    },
                    sourceMap: true,
                }),
                new CssnanoPlugin({
                    sourceMap: true,
                }),
            ],
        },

webpack.config.statics.js:

plugins: [
            new CopyPlugin({
                patterns: [
                    { from: "./scripts/legacy/**/*.+(min.js|js)", context: srcRoot },
                    { from: "./scripts/vendor/**/**/*", context: srcRoot },
                ],
            }),
        ],

return merge(baseConfig, staticsConfig);

@ZDTaylor Can you open an new issue with simple reproducible test repo? Should work fine, need investigate

@evilebottnawi Opened #515 to track

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lewayjack picture lewayjack  路  5Comments

jbruni picture jbruni  路  3Comments

alex88 picture alex88  路  4Comments

padinko picture padinko  路  3Comments

amgohan picture amgohan  路  5Comments