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?
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
productionmode
@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
Most helpful comment
Use if you are coping JS file and want to minify