10

I have updated an angular application from angular 10 to angular 12. After updating development mode works fine. But in production build I am getting "JIT compiler unavailable" error. I have imported '@angular/compiler'; in the main.ts file also. I couldn't find any possible reason for this issue.

Salahuddin Ahmed
  • 4,854
  • 4
  • 14
  • 35
Vidura Jayalath
  • 111
  • 1
  • 1
  • 5

8 Answers8

12

ANGULAR 13+ UPDATE

In addition to the steps below, the Angular Linker must now be used to process all .mjs files created by the Angular compiler or you'll see the JIT error again. See the Example Configuration.

Background

The JIT compiler unavailable error can occur when using an outdated plugin (i.e. one that still the uses View Engine instead of Ivy).

According to Google's Building Libraries with Ivy guide, libraries can be distributed in 3 formats: View Engine (now deprecated), Partial-Ivy (recommended), and Full-Ivy.

Ivy apps can still consume the View Engine format with NGCC, but View Engine is slated to be removed in Angular 13, so library authors should use the "partial-Ivy" format moving forward. Here's a deep dive about the change.

How To Fix (3 steps)

1. Identify the problematic plugin.

Important: If your TerserPlugin config uses ngDevMode: false, Angular will throw a generic JIT compiler unavailable error. Removing the flag (or using ngDevMode: true) should reveal a more useful error that mentions the plugin by name. If that doesn't help, try my debugging tips at the end of the answer. Be sure to set ngDevMode back to false once the issue is fixed; it can have a large impact on bundle size.

2. Ask the library author to update the plugin's tsconfig.prod.json file:

"angularCompilerOptions": {
   "enableIvy": false // Remove this line or use true
   "compilationMode": "partial" // Add this line
}

3. Consume the format by compiling the library using the Angular Linker, which is currently only available as a Babel plugin: @angular/compiler-cli/linker/babel

In short, add this to your Webpack config and replace ng-click-outside with your plugin(s):

rules: [
{
  // Explicit rule to run the linker over partial libraries
  test: /.*\.js$/,
  include: /node_modules\/ng-click-outside/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        configFile: false,
        plugins: ['@angular/compiler-cli/linker/babel'], // Required!
      }
    }
  ]
},
{
  // Regular rule for all non-library files
  test: /\.[jt]sx?$/,
  exclude: /node_modules/,
  use: [
    {loader: 'babel-loader'}, // Optional
    {
      loader: '@ngtools/webpack', // Required
      options: {
        directTemplateLoading: false, // See https://www.npmjs.com/package/@ngtools/webpack
      }
    },
    {loader: '@angular-devkit/build-optimizer/webpack-loader'}, // Optional
  ]
},

Credit for the webpack config goes to Robert van Hoesel from this Github issue.

Debugging Tips

1. While debugging the problem, you can add import '@angular/compiler'; in your main.ts file (as the OP has done), but this will output the JIT compiler in your prod build and isn't a real fix. Do not use the JIT compiler in production.

Note: Once you get things working, if you still see the Angular Compiler in your production webpack bundle, you can safely remove it using Webpack's 'externals' option. Some Angular versions require the compiler for JIT builds, but the compiler isn't needed for AOT builds.

2. If you still don't see a useful error message, remove Terser completely and make sure you're not suppressing build errors.

3. When fixing Webpack issues in general, it can sometimes be useful to create a new Angular CLI project, add your plugins (or other code), and see if it builds. If it does, then you know your Webpack config is the problem, not Angular. I also find it useful to compare Angular CLI's config files with my own (though it's tedious).

Stevethemacguy
  • 708
  • 7
  • 22
  • Making `"enableIvy" : false` worked for me – aniran mohammadpour Jan 20 '22 at 17:10
  • What if the library owner does not update the `tsconfig.prod.json`? Is there any way to get around this besides using the JIT compiler? – cip123 Jun 30 '22 at 13:07
  • @stevethemacguy How is this property 'include' is working ? I am having problems to point to my folder where i have the external library Please check my question and post an answer if you know the solution => https://stackoverflow.com/questions/74361440/how-can-i-point-to-specific-folder-in-node-modules-in-my-webpack-config – Andrej12345 Nov 08 '22 at 14:09
  • How do I identify the problematic plugin? – Eduardo Wada Dec 07 '22 at 11:43
  • @EduardoWada See my Debugging Tips above and check your browser console. Also, see the Angular 13 update I just added. – Stevethemacguy Dec 08 '22 at 00:04
  • @Stevethemacguy I see, but my problem is that I never manually added "Terser" into the project, I'm assuming this came in with the template when I created the project a few years ago, or it was added by ng update, but essentially I don't know how to remove Terser and then I don't get any useful message. – Eduardo Wada Dec 08 '22 at 16:27
  • @EduardoWada That sounds outside the scope of the original question. I suggest creating a separate SO question for help with your specific situation. – Stevethemacguy Dec 09 '22 at 01:14
  • is the babel linker still required for Angular 15? I would assume not, as Angular 15 uses Ivy by default? – Michahell Apr 20 '23 at 09:13
1

We've faced similar issue while upgrading our Angular app to v12 from v11. The solution was to remove from tsconfig.json

"compilationMode": "partial" 

or set it to

"compilationMode": "full"

As "partial" value only required for the libraries and not the full angular apps.

user2837849
  • 319
  • 1
  • 3
  • 8
0

I had the same issue, it worked for me that re-install all angular dependencies with 12 version:

NGV=12.2.9
npm i \
@angular-devkit/build-angular@$NGV \
@angular-devkit/core@$NGV \
@angular/animations@$NGV \
@angular/common@$NGV \
@angular/compiler@$NGV \
@angular/core@$NGV \
@angular/forms@$NGV \
@angular/platform-browser@$NGV \
@angular/platform-browser-dynamic@$NGV \
@angular/router@$NGV \
@angular/cli@$NGV \
@angular/compiler-cli@$NGV \
typescript@4.2.3 \
zone.js@~0.11.4 --force

The above update all dependencies for compiling like webpack and typescript

Adán Escobar
  • 1,729
  • 9
  • 15
0

I have updated typescript and using Angular 13, actually all happened while I wanted to use mat-paginator and tables of material.

Solution that I found is to add code below to tsconfig.json file angularCompilerOptions :

  "enableIvy": false

My package.json configurations

{
"name": "client",
"version": "0.0.0",
"scripts": {
    "ng": "ng",
    "start": "ng build --watch",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
},
"private": true,
"dependencies": {
    "@angular/animations": "~13.0.0",
    "@angular/cdk": "^13.1.3",
    "@angular/common": "~13.0.0",
    "@angular/compiler": "~13.0.0",
    "@angular/core": "~13.0.0",
    "@angular/forms": "~13.0.0",
    "@angular/material": "^13.1.3",
    "@angular/platform-browser": "~13.0.0",
    "@angular/platform-browser-dynamic": "~13.0.0",
    "@angular/router": "~13.0.0",
    "@fortawesome/angular-fontawesome": "^0.9.0",
    "@fortawesome/fontawesome-svg-core": "^1.2.36",
    "@fortawesome/free-solid-svg-icons": "^5.15.4",
    "@ng-bootstrap/ng-bootstrap": "^11.0.0-beta.2",
    "@ngx-loading-bar/core": "^5.1.1",
    "@ngx-loading-bar/http-client": "^5.1.1",
    "@ngx-loading-bar/router": "^5.1.1",
    "bootstrap": "^5.0.0",
    "bootstrap-icons": "^1.7.2",
    "moment": "^2.29.1",
    "rxjs": "~7.4.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
},
"devDependencies": {
    "@angular-devkit/build-angular": "~13.0.2",
    "@angular/cli": "~13.0.2",
    "@angular/compiler-cli": "~13.0.0",
    "@types/jasmine": "~3.10.0",
    "@types/node": "^12.11.1",
    "jasmine-core": "~3.10.0",
    "karma": "~6.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "~1.7.0",
    "typescript": "~4.4.3"
}

}

My app.module.ts configuration:

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common

/http';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { LoadingBarModule } from '@ngx-loading-bar/core';
import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client';
import { LoadingBarRouterModule } from '@ngx-loading-bar/router';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
import { Api } from './services/api.service';
import { BrowserInterceptor } from './services/browser.interceptor';
import { PublicVars } from './services/publicVars.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';




@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    HomeComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserModule,
    AppRoutingModule,
    NgbModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,
    LoadingBarModule,
    LoadingBarRouterModule,
    LoadingBarHttpClientModule,
    FontAwesomeModule,
    BrowserAnimationsModule,


  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: BrowserInterceptor,
      multi: true,
    },
    Api,
    PublicVars,
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}
0

I saw the following error after upgrading from Angular 11 to 13:

enter image description here

After investigating my code, I found two @Component {...} decorator in one of my components. With Angular 11, two @Component in a single component had not created any error. It looked something like this:

import { Component, OnInit } from '@angular/core'.

@Component({
  selector: 'app-landing',
  templateUrl: './landing.component.html',
  styleUrls: ['./landing.component.scss']
})

@Component({
  selector: 'app-landing',
  templateUrl: './landing.component.html',
  styleUrls: ['./landing.component.scss']
})

export class LandingComponent implements OnInit {
....

After removing the extra @Component {...}, the error in Angular 13 was fixed.

RezaNikfal
  • 927
  • 11
  • 22
0

I had the same error for an ng build generation. The application would start but failing with components with call stack reporting "Jit compiler not found". Before I also had issues with components not fully AOT built, and keeping the templateUrl reference, reporting that Component wasn't compiled and if I did call resolveComponentResources() and wait for it. I did code to do that with compiler included. Still not working. It wasn't my expectation that the built files needed that. So I moved to the solution. The solution that worked for me, was the advice that @Stevethemacguy proposed - build a working standalone app with ng serve with the ng tools. That way I can compare my custom angular.json and tsconfig.json with the ones that worked. And I also can process and test code changes faster.

  1. When fixing Webpack issues in general, it can sometimes be useful to create a new Angular CLI project, add your plugins (or other code), and see if it builds. If it does, then you know your Webpack config is the problem, not Angular. I also find it useful to compare Angular CLI's config files with my own (though it's tedious).

I added the compiler to see application working and other things besides, and then proceeded to solve reasons for needing the compiler. After that I removed the compiler and it's working.

This is my configuration:

  1. My project uses a Websphere to serve the application and iterating with trial and error on AOT builds, with websphere, is very morose.
  2. The goal was to migrate a non-AOT deployment from angular v12 to v14 AOT build. But I was getting lots of errors when executing.
  3. Therefore I changed to a standalone app running with ng serve.
  4. I mocked the services that produced json from websphere and then I could execute it standalone.
  5. I migrated a sample app at version v12 with angular recommended command ng update @angular/core@14 @angular/cli@14 at angular update v13 to v14 to see the code changes, being UntypedFormBuilder import one of them.
  6. I also looked at the webpack generated code, to check ɵfac, ɵcmp, ɵinj and other methods declared for generated javascript for Component and NgModule annotated classes. Some Components didn't have those methods, which means the compiler wasn't processing them.
  7. Before removing angularCompilerOptions the compiled class for bootstrap Component didn't have template property. On compiled code that property contains the javascript compiled template. Something was wrong with my build. Removing the angularCompilerOptions and copying the tsconfig.json plus tsconfig.app.json to my target app did part of the trick.
  8. I also have, for the full app, a working non-AOT build using JIT Compiler for v14 with all modules imported using systemjs with systemjs.babel shims and import map to solve import paths. But that build is very slow to start app on browser (10 seconds on localhost and 315 plus GET requests) and anyway is only meant for development workflows. So the AOT build is imperative. Now application start time on localhost is under 1 second.

When standalone app was working I compared it with previous repo configuration and code files. With that I fixed the original sources and could get the project working.

Some major changes:

  1. I removed specialized angularCompilerOptions from tsconfig.app.json
  2. I added import of CommonModule on every module that includes my Components. It doesn't seem to work without it. Browser reports that can't understand an 'ngIf' and it is a consequence of that. It was working on v12 non-AOT.
  3. I added UntypedFormBuilder import to every Component I used, since my legacy code doesn't use Typed FormBuilder yet, which is a new feature for angular v14.
Bruno M
  • 1
  • 1
-1

I had the same error, in my case it was due to the tsconfig.app.json file with a wrong config.

I have created a new project with the last Angular version (v14), copy the new tsconfig.app.json inside my project. And it is working now.

user1075296
  • 581
  • 3
  • 10
-2

Make sure you have already imported '@angular/compiler' at the very top of your main.ts file. After that run this in your package.json.

scripts{
 "postinstall": "ngcc --properties es5 browser module main --first-only"
}
Salahuddin Ahmed
  • 4,854
  • 4
  • 14
  • 35