How to copy non-ts files to dist when building typescript?
Asked Answered
I

10

79

I have Mail module in folder with this structure:

- Mail
  - templates
      - <Handlebars files>
  - mail.module.ts

When I build (compile) TypeScript project, my template folder is not included in build folder. How to move those kind of files into dist when building?

Is it different for development vs production builds?

Imperceptible answered 19/2, 2020 at 18:6 Comment(0)
V
36

You can also do this by adding an asset property in the nest-cli.json as mentioned in the documentation.

For your case, you can try something like this:

"assets":["**/Mail/templates/*"]

Or if your templates all have a specific filetype (I am assuming its called .template), this should also work:

"assets":["**/*.template"]

The 2nd example will copy all files of type .template from all sub directories to your dist folder with the same folder structure when you run a nest build. Similarly, you can use this to copy any filetype of your choice (.json, .proto, etc) by replacing .template in the glob pattern.

Vanquish answered 8/5, 2020 at 6:19 Comment(2)
just to mention, that "assets":["**/Mail/templates/*"] should be placed inside compilerOptions objectNear
Very important, thanks!Klaraklarika
S
22

TS compiler doesn't handle files that are other than TypeScript or JS (e.g. .ts, .js, .tsx, etc.).

One way of doing it, just running cp to copy those files after you compile NestJS. In your package.json replace the line

"build": "nest build",

with

"build": "nest build && cp ./Mail/templates ./build",

Ideally, I would switch to Webpack (or similar) to transpile TypeScript and copy artifacts. NestJs has a basic example on how to build with Webpack here. To extend it to have a "copy" phase, install copy-webpack-plugin npm package and add those additions in webpack config file:

const copyFiles = require('copy-webpack-plugin');
// ... omitted for abbreviation

module.exports = function(options) {
   return {
   // ... omitted for abbreviation
   ,
    plugins: [
      // ... omitted for abbreviation
      new copyFiles([
            { from: 'Mail/templates', to: 'templates' }
        ])
    ]
}
Slake answered 20/2, 2020 at 10:30 Comment(2)
FYI but cp is not necessarily cross platform compatible.Moly
It is not, this is why I thought webpack is a better optionSlake
M
21

A quick fix for your scenario would be to:

  1. npm install --save-dev copyfiles

  2. Modify your package.json so it includes a new script:

    "postbundle": "copyfiles -u 1 src/**/*.template dist/"

  3. Add or update your bundle script so it matches:

    "bundle": "tsc"

Another more advanced approach would be use to babel or webpack for compile work

Mannerly answered 22/2, 2021 at 17:13 Comment(0)
M
8

I was struggling with the same problem, and then created typescript-cp.

It detects the source and output directories based on your project's tsconfig.json (using typescript's own config parser, to work as smooth as possible) and copies the non-TS files to the outDir.

It has a very basic CLI, with similar arguments to typescript's tsc, but this is tscp. It also supports package references.

# Copy
$ tscp

# Copy for TS project references
$ tscp -b

# Watcher
$ tscp -w

# Watcher for TS project references
$ tscp -b -w

# Custom compiler settings
$ tscp -p tsconfig.production.json

# Help
$ tscp -h

Feel free to open an issue if something isn't working as expected.

Maturity answered 29/3, 2021 at 20:3 Comment(1)
solid approach, thanksReprobate
H
5

I had the same problem.

  • If your template directories are under the src folder, as Derryl Thomas said in the previous answer, you need to specify the path location of your assets in the nest-cli.json file.

NOTE:

The assets must be located in the src folder or they will not be copied.

  • If like me your template directories are at the same level as the src folder, you also need to update the sourceRoot property and the entryFile property of the nest-cli.json file.

To see what your configuration file should look like, you can download the cli diagram here


Here is the archive of my project:

enter image description here

Here is what my nest-cli.json file looks like

{
  "$schema" : "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot" : ".",
  "compilerOptions" : {
    "assets" : ["config.*.yaml", "assets/**"]
  },
  "entryFile" : "src/main"
}

Hawser answered 7/9, 2022 at 12:24 Comment(0)
S
1

If you want a hassle-free way of doing it, the popular ts-node package does that automatically! ts-node is the equivalent to running node but for TypeScript projects. If you're going to use ts-node, you won't have to compile the TypeScript files and run the js file, ts-node does that all in the background.

Switzerland answered 3/7, 2021 at 20:13 Comment(5)
It's worth mentioning that ts-node should NOT be used in production, at least not without adjusting it. See this: #60582117Rafaellle
@Rafaellle the link you posted literally says it can be used in production with the --transpile-only flagBattlefield
Some people just like to overcomplicate things that should be simple.Switzerland
@Nando - I already wrote it cannot be used as-is in production, and some steps should be taken (I also included an article about it)... How did your comment add any value, other than rephrasing my comment and demotivating me?Rafaellle
Because it actually can be used as-is in production. I have at least one public API using it now, without any compilation folder. The value my comment adds is to point out the distinction between the objective "can" and your "should".Battlefield
F
1

In my case I added the assets config to copy html files and it worked.

nest-cli.json

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "assets": ["**/*.html"]
  }
}
Fibroid answered 26/4, 2023 at 13:50 Comment(0)
M
0

Or you can use cp command in the build script :

"build": "pnpm i && tsc --build && cp public/legal.html dist/legal.html",
Microscopium answered 7/2 at 16:13 Comment(0)
S
0

I found myself in the same situation, coincidentally, mail templates as well. It took me a while to figure this out, but Typescript will absolutely do nothing for you here, you have to fix this outside of Typescript.

You'll also want to use a OS-independent way; most answers thusfar are OS specific (nice until you're moving to production), or are for NestJs.

The solution lies in two npm packages (DEV dependencies):

  • rimraf (to clean-up)
  • copyfiles (to copy files)

Using your preferred package manager:

pnpm add -D rimraf copyfiles
npm install --save-dev rimraf copyfiles
yarn add -D rimraf copyfiles

Then add two "scripts" to your package.json. In my project the target folder is called "build", yours might be called "dist", adjust as needed. Also, this assumes the "templates" folder is in your "src" folder, it could also be in your projects root, again adjust as needed.

"scripts": {
    ...
    "clean": "rimraf build/",
    "copyfiles": "copyfiles -u 1 src/templates/**/* build/"
},

At this point, you can test both commands. Using pnpm (I'm sure you can imagine the command for other managers):

pnpm copy-files
pnpm clean

If this worked, you can then go ahead and change your build script, adding the clean step before it, and the copy step after it. Work with your existing build script. In my case it was just calling tsc. Which would then look like:

"scripts": {
    ...
    "clean": "rimraf build/",
    "copyfiles": "copyfiles -u 1 src/templates/**/* build/",
    "build": "pnpm clean && tsc && pnpm copyfiles"
}

Documentation:

Smackdab answered 24/3 at 20:23 Comment(0)
R
-2

Firstly, you add bellow code to nest-cli.json:

  "compilerOptions": {
    "assets": ["*.proto"],
    "watchAssets": true
  }

And then the most important thing is you have to put the your files inside /src directory, not in project root directory.

Rottenstone answered 4/9, 2021 at 7:22 Comment(1)
You save me. All solution I tried is wrong except you.Sericin

© 2022 - 2024 — McMap. All rights reserved.