61

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?

Baterka
  • 3,075
  • 5
  • 31
  • 60

8 Answers8

29

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.

Derryl Thomas
  • 1,324
  • 12
  • 22
17

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' }
        ])
    ]
}
Jenya Y.
  • 2,980
  • 1
  • 16
  • 21
17

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

Alberto S.
  • 1,805
  • 23
  • 39
6

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.

bencergazda
  • 620
  • 8
  • 18
3

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"
}

Taur
  • 514
  • 3
  • 8
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.

Epic Speedy
  • 636
  • 1
  • 11
  • 25
  • 4
    It's worth mentioning that `ts-node` should NOT be used in production, at least not without adjusting it. See this: https://stackoverflow.com/questions/60581617/is-it-a-bad-practise-to-use-ts-node-in-production – A-S Oct 05 '21 at 13:55
  • 1
    @A-S the link you posted literally says it can be used in production with the --transpile-only flag – R-D Jul 13 '23 at 01:22
  • 1
    Some people just like to overcomplicate things that should be simple. – Epic Speedy Jul 14 '23 at 11:00
  • 1
    @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? – A-S Jul 18 '23 at 17:22
  • 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". – R-D Jul 19 '23 at 18:18
0

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"]
  }
}
nasy
  • 11
  • 3
-4

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.

ouflak
  • 2,458
  • 10
  • 44
  • 49