21

My application takes a very long time to build for production using ng build --prod

Sometimes it even fails with

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Is there something I can do to reduce the build time?

Daniel
  • 10,641
  • 12
  • 47
  • 85

5 Answers5

42

There are some things that can be done to reduce the build time.

Increase the memory limit of the build process

The build command is executed by node where a single process has a maximum memory limit of 1.76 GB on 64bit machines. It can be increased by adding the --max-old-space-size argument to the build command

Since this argument must be passed to the node process itself, the command must be run directly with node. An example allocation 4096 MB (4GB) of RAM to the process would be:

node --max-old-space-size=4096 ./node_modules/@angular/cli/bin/ng build

Increasing the memory limit will also prevent the "heap out of memory" error.

There does appear to be a limit to how much memory the process uses. A project of mine had it's build time significantly reduced by a memory increase to 12GB - but increasing it to 32GB gave no further improvement.

Fix references to node_modules in .scss files

Referencing external stylesheets from node_modules using relative paths has a negative performance impact on the build process and should be avoided.

The build process uses Webpack's sass-loader, which supports a syntax where the location of node_modules is referenced with the tilde ~.

Using the tilde instead of the relative path greatly reduces build time. So instead of importing external css stylesheets with

import "../../../../../node_modules/x/whatever.css"

use

import "~node_modules/x/whatever.css"

Production optimizations

By default the production build uses the configuration from your angular.json file. The default values are

"production": {
  "fileReplacements": [
    {
      "replace": "src/environments/environment.ts",
      "with": "src/environments/environment.prod.ts"
    }
  ],
  "optimization": true,
  "outputHashing": "all",
  "sourceMap": false,
  "extractCss": true,
  "namedChunks": false,
  "aot": true,
  "extractLicenses": true,
  "vendorChunk": false,
  "buildOptimizer": true
}

Do not divert from the production build defaults unless you have a very good reason.

These are a big part of keeping the build time low (espescially disabling sourceMap and enabling buildOptimizer).

Update your Angular CLI version

The Angular CLI teamb continuously improves the speed of the build process.

Notibly the upgrade in build performance from version 6 to 7 is substantial, so keeping the @angular/cli library up to date is always a good idea.

External libraries

To have a fast building application you need to be very careful with which libraries you import.

Many popular libraries such as jQuery, lodash and moment are very large in size and not properly optimized for the Webpack building process.

Look for libraries that supports Webpack's Tree-Shaking to allow the build process to only bundle the parts of the library that is actually used in your application.

Also, don't fall into the trap of adding an entire utility library (such as lodash) if you only need to use a single function from it (like _get()).

Compressing assets

Compressing assets (often images) is largely a trivial task (just google "compress images online"), and it can increase the performance of the build process and the application itself.

Hardware optimizations

Since Javascript is a single-threaded the benefits of having multiple CPU cores won't speed up the build process.

In fact, if you monitor your CPU during the build you will see a single core is under 100% load almost during the entire process.

If you are regulary building your application with production flag as part of your continuous integration setup, you may consider using a machine equipped with high single-threaded performance (for benchmarks, see cpubenchmark.net)

Daniel
  • 10,641
  • 12
  • 47
  • 85
  • 4
    Why would compressing static assets like image impact build times (other than a smaller file to copy to the `/dist`)? – crush May 14 '19 at 22:00
  • 1
    well I'd still argue it may make sense to break up the build into parallelizable tasks – ciekawy Jun 13 '19 at 00:51
  • This require while running application by --prod also. node --max-old-space-size=4096 ./node_modules/@angular/cli/bin/ng s --prod – Rohit Parte Nov 01 '19 at 16:45
0

For windows 64 bit,

Resolution: We need to increase the default memory limit of the node.

Steps for the increasing the default node memory limit:

  • Open the cygwin
  • run the comment " npm config set max-old-space-size=1024 "

    • Based on your application need, your can increase your memory limit

    • node --max-old-space-size=1024 #increase to 1gb

    • node --max-old-space-size=2048 #increase to 2gb
    • node --max-old-space-size=3072 #increase to 3gb
    • node --max-old-space-size=4096 #increase to 4gb
    • node --max-old-space-size=5120 #increase to 5gb
    • node --max-old-space-size=6144 #increase to 6gb
    • node --max-old-space-size=7168 #increase to 7gb
    • node --max-old-space-size=8192 #increase to 8gb
saravana va
  • 1,081
  • 1
  • 13
  • 17
0

Add npm command in package.json to scripts like below:

"scripts": {<br/>
"ng": "ng",<br/>
"start": "ng serve",<br/>
**"go": "node --max_old_space_size=8192 ./node_modules/@angular/cli/bin/ng build",**<br/>
.<br/>
.<br/>

and then in command line or in terminal use npm run go

Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
Rehan Khan
  • 154
  • 6
0

Try running with npx. In my case: npx run build --prod

I had similar issues with running the build on a Google Cloud instance with the following specs: g1-small (1 vCPU, 1.7 GB memory). It was loading the CPU to 100% and the server was getting freeze and needed restart.

Only with npx I managed to make it work.

GarryOne
  • 1,430
  • 17
  • 21
0

In my case, I have replace Pool from 'ubantu-latest' to 'windows-latest' and it works

Jatin Dave
  • 734
  • 1
  • 7
  • 14