When working with Node.js and TypeScript, it’s common to encounter the need to include non-code files like JSON, text files, or even Markdown files in your build output. These files, essential for configurations, data, or documentation, often need to be copied into your dist
folder during the build process. However, the TypeScript compiler (tsc
) only compiles .ts
files and doesn’t handle copying non-code files. To ensure these files are available post-build without manual copying, automating this process is key.
Thank me by sharing on Twitter 🙏
In this post, I’ll explain how I automated the copying of these files during my build process using the copyfiles
package, ensuring the folder structure is preserved while excluding unnecessary root directories. I’ll walk through how you can set up a simple, efficient workflow that streamlines this task.
Why Automate Copying Non-Code Files?
In most Node.js projects, non-code files like .json
and .txt
often contain critical information such as configurations, data, or documentation that the application requires at runtime. These files need to be transferred to the build folder (dist
) after the TypeScript files are compiled to ensure the complete application is bundled correctly.
Without automating this step, you might find yourself copying these files manually after every build, which is not only tedious but prone to human error. Automating this process makes sure everything is copied to the correct location without additional manual steps.
The Solution: Using copyfiles
To handle copying non-code files, I used the copyfiles
package. It’s lightweight and straightforward, allowing me to specify patterns for files I want to copy, and it preserves the folder structure. Importantly, copyfiles
also lets me remove certain top-level directories during the copy, which is especially useful when I want to drop the src
folder while maintaining the internal folder structure.
Highwings 8K 10K 4K HDMI Cable 48Gbps 6.6FT/2M, Certified Ultra High Speed HDMI Cable Braided Cord-4K@120Hz 8K@60Hz, DTS:X, HDCP 2.2 & 2.3, HDR 10 Compatible with Roku TV/PS5/HDTV/Blu-ray
$9.99 (as of January 9, 2025 10:16 GMT +00:00 - More info)The Microsoft Office 365 Bible: The Most Updated and Complete Guide to Excel, Word, PowerPoint, Outlook, OneNote, OneDrive, Teams, Access, and Publisher from Beginners to Advanced
$34.17 (as of January 11, 2025 10:31 GMT +00:00 - More info)Teeind USB Type C Cable Fast Charging, Tpc001 5 Pack(6Ft 3A) Braided C Charger Cables Compatible with Samsung S10e/note 9/s10/s9/s8 Plus/A80/A50/A20
$9.99 (as of January 9, 2025 10:16 GMT +00:00 - More info)Step 1: Installing copyfiles
The first step is to install the copyfiles
package as a development dependency. Since it’s used only during the build process, it doesn’t need to be included in the production environment.
To install it, run:
npm install --save-dev copyfiles
This installs the package, and you can now use it in your build scripts.
Step 2: Setting Up the Build Script with -u 1
In a typical TypeScript project, your build script in package.json
might look something like this:
{
"scripts": {
"build": "tsc"
}
}
This script compiles the TypeScript files, but as mentioned earlier, it leaves out other important files such as .json
, .txt
, and .md
. I needed a way to copy these files into the dist
folder, maintaining their internal folder structure but excluding the src
folder itself.
To do this, I updated the build script to include copyfiles
with the -u 1
flag. This flag tells copyfiles
to drop the top-level directory (src
), so the files inside src
are copied to the dist
folder while maintaining their subdirectory structure.
Here’s the updated build script:
{
"scripts": {
"build": "tsc && copyfiles -u 1 './src/**/*.{json,txt,md}' dist"
}
}
Let’s break this down:
tsc
compiles the TypeScript files into JavaScript and places them in thedist
folder.copyfiles -u 1 './src/**/*.{json,txt,md}' dist
copies all.json
,.txt
, and.md
files fromsrc
todist
, preserving the folder structure while dropping the top-levelsrc
directory.
For example, a JSON file located at src/config/settings.json
will be copied to dist/config/settings.json
, but without the extra src/
in the destination path.
Step 3: Running the Build Script
With the build script set up, you can run the build process with the following command:
npm run build
After running this, all .ts
files will be compiled to .js
, and the .json
, .txt
, and .md
files will be copied to the dist
folder, preserving the subdirectories.
For instance, if your folder structure looks like this:
src/
config/
settings.json
data/
sample.txt
docs/
readme.md
After running the build, the dist
folder will look like this:
dist/
config/
settings.json
data/
sample.txt
docs/
readme.md
As you can see, the folder structure under src/
is preserved in dist/
, but the src/
folder itself is excluded.
Common Pitfalls and Troubleshooting
During the setup, I encountered a few common issues that are worth mentioning.
- Incorrect Usage of the
-u
Flag:
If you set the-u
flag too high (e.g.,-u 2
), you’ll get an error like:Error: cant go up that far
. This error occurs becausecopyfiles
tries to remove more directory levels than exist in the path. To fix this, ensure the-u
value matches the number of top-level directories you want to exclude. In this case,-u 1
removes only thesrc
folder. - File Path Issues:
If the files aren’t being copied as expected, double-check the file patterns you’re using. For example,./src/**/*.{json,txt,md}
ensures that all.json
,.txt
, and.md
files insidesrc
and its subdirectories are copied. Forgetting the**
part of the pattern will only copy files from the top-levelsrc
directory, ignoring subdirectories. - Cross-Platform Compatibility:
If you’re working in a cross-platform team, or deploying to both Linux and Windows environments, make sure your paths are compatible. For example, the forward slash (/
) in the path works universally in most environments, but for Windows, ensure you use the correct escape characters if needed.
Conclusion
By using copyfiles
and the -u 1
flag, I was able to automate the process of copying important non-code files such as JSON, TXT, and Markdown files during my TypeScript build process. This method ensures that my build folder includes all the necessary files while maintaining the correct directory structure, without manual intervention or complex scripts.
This small change to my build workflow has saved me time and reduced the risk of errors during deployment. If your project involves any non-code assets that need to be copied into your build output, automating the process using copyfiles
is a simple yet effective solution that you can set up in just a few minutes.