[Solved] NPM copy files to dist folder

Need a quick way to use NPM to copy files to the dist folder after build? Follow some suggestions in this post!

Jan 13, 2023 | Read time 10 minutes

🔔 Table of contents

Introduction

A common task with front-end development is after we have built our front end code (CSS, SASS, JavaScript, etc) we copy the minified artifacts to a dist folder.

Then the dist (short for distribution) folder is the one that will be deployed and served!

Using NPM copy files to dist folders can be done in the following steps:

  1. Open up the terminal and go to your root project directory
  2. Make sure you have NPM installed and run npm init
  3. In the package.json file, create a command "build": "cp -r ./src ./dist"
  4. Then, make sure you are in the root directory of the project and run npm run build

Note about folders

Most projects use a folder named dist. I have seen different implementations where people call it public or build

Package.json to use for copying files to dist

We can setup a front end project by using the following NPM command.

npm init

After that there will be a bunch of prompts that asks us how we want to setup our project. This data will then be in a package.json file in project root directory!

name: (project-name) project-name
version: (0.0.0) 0.0.1
description: The Project Description
entry point: //leave empty
test command: //leave empty
git repository: //the repositories url
keywords: //leave empty
author: // your name
license: N/A

The resulting package.json will look something similar to this

{
  "name": "project-name",
  "version": "0.0.1",
  "description": "Project Description",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "the repositories url"
  },
  "author": "your name",
  "license": "N/A"
}

Now to copy our source code files (CSS, JS) to the dist folder, we can update the package.json file to the following: (Assuming that we already have the code in src folder)

{
  "name": "project-name",
  "version": "0.0.1",
  "description": "Project Description",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "cp -r ./src  ./dist"
  },
  "repository": {
    "type": "git",
    "url": "the repositories url"
  },
  "author": "your name",
  "license": "N/A"
}

We can then use the command npm run build to start our build process. Keep in mind the cp command works for Linux distributions. The -r flag is there to indicate that we want to recursively go through all the folders.

Keep in mind that the above cp command is for Linux - if you want to use Windows, we can install Git Bash where cp should be available.

An alternative command if you are on Windows is the copy windows command (https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/copy).

So for windows, our package.json becomes the following:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "copy src  dist"
  }

We then do the same thing as before and use the command npm run build to start our build process.

A more advanced version of copy on Windows is xcopy.

XCOPY is similar to the COPY command except that it has additional switches to specify both the source and destination in detail.

The below, we use xcopy to copy the files in src folder to the dist folder:

"copyfiles": "xcopy c:\project\src c:\project\dist /e"

The format of xcopy is:

xcopy <source> <destination> /e

Cross OS support for copying files

Now if we want our build pipeline to be able to support multiple operating systems, we can use the NPM package “copyfiles” (https://github.com/calvinmetcalf/copyfiles)

The copyfiles NPM package is more robust and contains more features than the system cp or copy commands. It can filter out files, flatten output, slice paths, etc.

Using NPM copyfiles package

To get started using the NPM copyfiles package we can follow the below steps:

  1. npm install --save-dev copyfiles to install copyfiles package as your development dependency
  2. In your package.json “cpdir”: “npx copyfiles soruceDir destinationDir” - using npx you can execute your npm package binaries.
  3. Finally you run the copy script: npm run cpdir

Example 1: NPM copyfiles for only Javascript files

In the below example, we can use the command to filter out only JavaScript files .js (assuming that our source is in src/assets)

"copyjavascript": "copyfiles --flat src/assets/*.js destination"

Note: The --flat flag just tells copyfiles to flatten the output - taking just the files and not keeping any folders.

Example 2: NPM copyfiles for complex copying to folders

NPM copyfiles package lets you to do more complex copying of files to folders. Consider the following:

copyfiles foo foobar foo/scripts/*.js out

The above command, we have a destination folder called out. The command will copy all files from foo and foobar. Now notice that in our foo folder, we have a directory called scripts. With this command, we only copy the .js files in the scripts folder!

So as you can see, we can do fairly complex tasks with this NPM package that could not be done with cp (Linux) or copy (Windows)

Tip: Use a task runner or bundler (such as gulp or webpack)

Using cp or copy commands or even the NPM copyfiles is good for simple copy tasks, but if your project is going to be more complex in the future - its beneficial to setup your project with task runners such as gulp (https://gulpjs.com/) or bundlers such WebPack.

For example, your project in the future might require to use SASS for CSS, using post processing tasks such as minify CSS, JS or even optimizing images, etc.

These types of actions are pretty much built in with those libraries!

Copy files to folder with Gulp example

Just for example, we can do the copy files to a dist folder with Gulp in the steps:

Step 1: Install Gulp CLI

Firstly we need to install the Gulp CLI like so:

npm install --global gulp-cli

Note: If you’ve previously installed gulp globally, run npm rm --global gulp before following these instructions.

Step 2: Create project folder

Next we create our project folder using my-project as the folder name.

npx mkdirp my-project cd my-project

Step 3: Initialize the project with NPM

We then initialize our NPM project. npm init

This will give a bunch of prompts to setup the project and the result will create a package.json file similar to the following:

{
  "name": "my-project",
  "version": "0.0.1",
  "description": "Project Description",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "the repositories url"
  },
  "author": "your name",
  "license": "N/A"
}

Step 4: Create project folder

We then need to install Gulp and its plugins as a dev dependency:

npm install --save-dev gulp

Step 5: Create the gulp file

In the root project folder and create a file named gulpfile.js.

const { src, dest } = require("gulp");

function copy(cb) {
    src('src/*.js')
        .pipe(dest('dist'));
    cb();
}

exports.copy = copy;

Gulp’s design is very plugin driven, so you would need to know which plugin to perform the task you are after. In the above code, we are using the src and dest plugins from gulp to copy our files.

  • src reads JavaScript files from src/ and passes its contents into the pipeline,
  • pipe will take output of the previous command as pipe it as an input for the next,
  • dest writes the output of previous commands to the copies/ directory.

Step 6: Run the build

We can then run the copy task with the following command in the terminal:

gulp copy

Summary

In this post I went over a few ways we can copy files from the src folder to the dist folder. This is a common action in front-end build pipelines where we copy files such as images, CSS, JavaScript dist folder to deploy.

When we are on Linux, we can use the cp command and for Windows, the copy or the xcopy commands will work!

If we want to have more finer control, there is a NPM package called copyfiles that can do this and contains more features such as filtering, flatting out the files, etc.

It is recommended to use task runners such as Gulp or Webpack if your project becomes more complex and will require more control/features other than just copying files.

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube