Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] copy files after webpack has finished creating the bundles #15

Closed
jmlopez-rod opened this issue Jan 29, 2016 · 18 comments

Comments

@jmlopez-rod
Copy link

commented Jan 29, 2016

I was hoping that I could use this plugin to create copies of the generated bundles to other directories. It seems however that the copying starts while webpack is creating these bundles. As a result I end up with copies of the files with no content.

Is there a way to add an option so that the copying of the files happen after webpack has created the output files?

@jmlopez-rod

This comment has been minimized.

Copy link
Author

commented Jan 29, 2016

Ok, so after digging around I'm starting to believe that there is no easy way to do this with the current version of the plugin. In writeFileToAssets the file source gets attached to compilation.assets.

        compilation.assets[relFileDest] = {
          size: function() {
            return stat.size;
          },
          source: function() {
            return fs.readFileSync(absFileSrc);
          }
        };

The problem is, that the source may not yet be there since webpack hasn't written it to the file yet so the source will be empty. So the next thing to try would be, can we check if absFileSrc is in the assets and make it read that source? I'll post when I find out.

@jmlopez-rod

This comment has been minimized.

Copy link
Author

commented Jan 29, 2016

So here is a solution, I added a few lines to writeFileToAssets so that it can check if the file is in production then to just point to that asset.

Here is the whole function

function writeFileToAssets(opts) {
  var compilation = opts.compilation;
  var relFileDest = opts.relFileDest;
  var absFileSrc = opts.absFileSrc;
  var forceWrite = opts.forceWrite;
  var lastGlobalUpdate = opts.lastGlobalUpdate;

  if (compilation.assets[relFileDest] && !forceWrite) {
    return Promise.resolve();
  }

  var currentAssets = _.keys(compilation.assets);
  var inProduction = _.find(currentAssets, function(name) {
    return _.endsWith(absFileSrc, name);
  });

  return fs.statAsync(absFileSrc)
    .then(function(stat) {
      if (compilation.assets[inProduction]) {
        compilation.assets[relFileDest] = compilation.assets[inProduction];
      } else if (stat.mtime.getTime() > lastGlobalUpdate) {
        compilation.assets[relFileDest] = {
          size: function() {
            return stat.size;
          },
          source: function() {
            return fs.readFileSync(absFileSrc);
          }
        };
      }
    });
}

Would you mind incorporating this change?

jmlopez-rod added a commit to iOffice/copy-webpack-plugin that referenced this issue Feb 8, 2016

copy files in webpack stream: Issue webpack-contrib#15
Checking if the file we are trying to copy is one of the current assets
in webpack. If this is the case then we set the source of file to copy
to the one already in the assets. Otherwise we proceed as before.
@tobinibot

This comment has been minimized.

Copy link

commented Oct 29, 2016

In case it helps anyone else, I was interested in the same functionality as @jmlopez-rod and I ended up using https://www.npmjs.com/package/webpack-shell-plugin to accomplish it.

@jmlopez-rod

This comment has been minimized.

Copy link
Author

commented Oct 30, 2016

@tobinibot thanks for the link, I'll be using that one for sure.

@photonstorm

This comment has been minimized.

Copy link

commented Nov 24, 2016

@tobinibot thanks, I too hit this exact problem, and am now using the shell plugin instead.

@Anima-t3d

This comment has been minimized.

Copy link

commented Jan 11, 2017

@tobinibot How did you manage to copy files using the webpack-shell-plugin? I tried cp path/from path/to which works when I run it in terminal, but gives an error during shell execution.

.../node_modules/webpack-shell-plugin/lib/index.js:168
throw error;
^
1

@photonstorm

This comment has been minimized.

Copy link

commented Jan 11, 2017

@Anima-t3d don't know if it's any use to you, but this is the script I use (obviously the paths are specific to my project):

In my webpack.config:

    plugins: [

        new WebpackShellPlugin({
            onBuildEnd: 'node copy-to-examples.js'
        })

    ],

And this is my copy-to-examples file:

var fs = require('fs-extra');

var source = './dist/phaser.js';
var dest = '../../phaser3-examples/public/js/phaser.js';

fs.copy(source, dest, function (err) {

    if (err)
    {
        return console.error(err);
    }

    console.log('Copied to ' + dest);

});
@jmlopez-rod

This comment has been minimized.

Copy link
Author

commented Jan 11, 2017

@Anima-t3d I have a similar thing as @photonstorm but I use onBuildExit:

config.plugins.push(new WebpackShellPlugin({
    onBuildExit: [
      'echo "Transfering files ... "',
      'cp -r dist/* path/to/other/dist/',
      'cp -r src/* path/to/other/src/',
      'echo "DONE ... "',
    ],
  }));

cp: http://man7.org/linux/man-pages/man1/cp.1.html

EDIT:

Somehow the cp command changed on me and it does not like the * in the path. I think the webpack shell plugin is wrapping each argument in quotes and so the actual commands provided in the script are not the same as if you were to execute them from the command line. To fix this I did something similar to what photonstorm did, that is, I moved my commands to a bash file and then I called bash file from the shell plugin.

@Anima-t3d

This comment has been minimized.

Copy link

commented Jan 13, 2017

@jmlopez-rod due to copying to a relative path in the parent of where I run webpack I ended up using something more similar to what @photonstorm described:

var fs = require('fs-extra');
var read = require('fs-readdir-recursive');
var path = require('path');

// Setup the instructions on which folders to copy
var copyInstructions = [
// copy from one src sub folder to another
	{
		label: 'Copy external scripts',
		source: './src/react/scripts/externals',
		destination: './src/app/static/r/scripts'
	},
// copy the aggregated src sub folder to dist
	{
		label: 'Copy static to dist',
		source: './src/app/static/',
		destination: 'dist/static'
	}
];

// Copy all files
copyInstructions.map(function (instruction) {
	const {label, source, destination} = instruction;
	var files = read(source);
	/*if (label) {
		console.log(label);
	}*/
	files.forEach(file => {
		var sourcePath = source + '/' + file;
		var destinationPath = destination + '/' + file;

		fs.copy(path.resolve(sourcePath), path.resolve(destinationPath), function (err) {
			/*if (label) {
				console.log(label);
			}*/

	    if (err) {
	      return console.error(err);
	    }

	    console.log(`Copied ${file} to ${path.resolve(destinationPath)}`);
		});
	});
});

I did not manage to get the path right when using the cp command.

@JeffreyWay

This comment has been minimized.

Copy link

commented Mar 9, 2017

@kevlened Is there any chance of this being added?

I'd love to be able to copy a generated file that is only created after webpack finishes its build. Right now, I can't with your plugin.

@danchristian

This comment has been minimized.

Copy link

commented Jun 23, 2017

@kevlened This feature would be great, currently my production build fails due to this plug-in looking in an empty 'dist' folder as the HtmlWebpackPlugin hasn't finished building the files. Having the ability to copy a generated file post build would be ideal.

@AWolf81 AWolf81 referenced this issue Jul 25, 2017
3 of 3 tasks complete
@gregnb

This comment has been minimized.

Copy link

commented Sep 2, 2017

I also needed a feature like this and created plugin that could copy, delete, and move files/directories when a build starts or when a build finishes. https://github.com/gregnb/filemanager-webpack-plugin if you're interested

@d3viant0ne d3viant0ne removed the enhancement label Sep 29, 2017

@michael-ciniawsky michael-ciniawsky changed the title copy files after webpack has finished creating the bundles [Feature] copy files after webpack has finished creating the bundles Oct 5, 2017

@redaxmedia

This comment has been minimized.

Copy link

commented Oct 20, 2017

The FileManagerPlugin replaced CleanWebpackPlugin and CopyWebpackPlugin for me! Go for it...

@evilebottnawi

This comment has been minimized.

Copy link
Member

commented Feb 22, 2018

Out of scope this plugin, please use FileManagerPlugin or just run npm task after build

@airtonix

This comment has been minimized.

Copy link

commented May 2, 2018

FileManagerPlugin is broken too.

@LiMeii

This comment has been minimized.

Copy link

commented Aug 14, 2018

@evilebottnawi thanks! you save my day!!!

@alvinhtml

This comment has been minimized.

Copy link

commented Apr 1, 2019

@evilebottnawi thanks!

@Antoine-360pixel

This comment has been minimized.

Copy link

commented Apr 16, 2019

For me, filter files to change output work fine...

{...}
output: {
    path: path.revolve(__dirname, `build/static`),
    filename: (chunkData) => {
      return chunkData.chunk.name.includes('sw') ? 'bundle-[name].js': 'assets/bundle-[name].js';
    },
    sourceMapFilename: `[name].map`
  },
{...}

Hope help you for simple cases...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.