Pedro Accorsi
Pedro Accorsi

Reputation: 925

How to generic copy a file with npm postbuild script

I'm running yarn run build, which will re-create the directory build of my project. The thing is: whenever this is done, I lose one file that I must have inside of build/, which I manually copy and paste there.

So, naturally, I created the following script inside of package.json in order to have it done automatically:

  "scripts": { 
    "build": "react-scripts build",
    "postbuild": "npm run copy", 
    "copy": "copy Staticfile build"
  },

Now the thing is: will it work on Mac? Linux? I only have an Windows so I don't know and cannot test either, but I assume that it wouldn't work since copy statement is native on windows but not on other OS...

So the question is: how to make it be generic and OS-independent?

Thank you!

Upvotes: 10

Views: 10254

Answers (1)

RobC
RobC

Reputation: 24982

"I assume that it wouldn't work since copy statement is native on windows but not on other OS"

Yes, your assumption is correct.

On UNIX-like platforms (Linux, macOS, etc...) the cp command is analogous to the copy command available on Windows.

For cross-platform compatibility consider utilizing either of the following two solutions - both essentially use node.js to copy the file (personally I'd choose "Solution A").


Solution A: Using a third party package

Utilize the shx package which is described as follows:

"shx is a wrapper around ShellJS Unix commands, providing an easy solution for simple Unix-like, cross-platform commands in npm package scripts."

  1. Firstly cd to your project directory and run the following command to install it:

    npm i -D shx
    
  2. Then redefine your copy script in the scripts section of your package.json as follows:

    "scripts": {
      ...
      "copy": "shx cp Staticfile build"
    }
    

Note: There are other packages that will meet your cross-platform requirement too, such as; copyfiles.


Solution B: Using a node.js built-in

Alternatively, if you wanted to avoid adding more dependencies to your project you could consider using the node.js built-in fs module. For example the following script utilizes the fs.readFileSync() and fs.writeFileSync() methods.

"scripts": {
  ...
  "copy": "node -e \"const fs = require('fs'); const data = fs.readFileSync('Staticfile'); fs.writeFileSync('build/Staticfile', data);\""
}

This copy script (above) utilizes the node.js command line option -e to evaluate the inline JavaScript as follows:

const fs = require('fs');
const data = fs.readFileSync('Staticfile');
fs.writeFileSync('build/Staticfile', data);

Note: If you wanted to take an approach similar to this previous example, i.e. excecute a custom node.js inside an npm script, you should probably consider using the fs.copyFile() method instead. I've just provided an example using fs.readFileSync() and fs.writeFileSync() because I know those methods work with very early versions on node.js - unlike fs.copyFile() which requires node.js >=8.5.0

Upvotes: 18

Related Questions