angular-cli
angular-cli copied to clipboard
Production build errors with type-only imports inside curlys and emitDecoratorMetadata on
🐞 Bug report
Command (mark with an x)
- [ ] new
- [x] build
- [ ] serve
- [ ] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] extract-i18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc
Is this a regression?
Yes, the previous version in which this bug was not present was: ~~12.x.x~~ (we were using tslint before, so I'm not really sure)Description
A clear and concise description of the problem...🔬 Minimal Reproduction
- Run
ng new test-app - Apply the below patch, which just imports
OnChangesandSimpleChangesas type-only imports and addsemitDecoratorMetadata: trueto tsconfig.json - Run
npx ng build(succeeds on development build) - Run
npx ng build --configuration production:
./src/app/app.component.ts - Error: Module build failed (from ./node_modules/@angular-devkit/build-angular/src/babel/webpack-loader.js):
SyntaxError: /Users/********/dev/temp/test-type-modifier/src/app/app.component.ts: Unexpected token, expected "," (1:14)
> 1 | import { type SimpleChanges, } from '@angular/core';
| ^
2 | import * as i0 from "@angular/core";
3 | import * as i1 from "@angular/common";
4 | import * as i2 from "@angular/router";
Patch for minimum reproduction:
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 0e696fa..36f0caf 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,10 +1,18 @@
-import { Component } from '@angular/core';
+import {
+ Component,
+ type OnChanges,
+ type SimpleChanges,
+} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
-export class AppComponent {
+export class AppComponent implements OnChanges {
title = 'test-type-modifier';
+
+ ngOnChanges(changes: SimpleChanges): void {
+ console.log(changes);
+ }
}
diff --git a/tsconfig.json b/tsconfig.json
index ff06eae..b5be6c7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,6 +14,7 @@
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2020",
🔥 Exception or Error
./src/app/app.component.ts - Error: Module build failed (from ./node_modules/@angular-devkit/build-angular/src/babel/webpack-loader.js):
SyntaxError: /Users/******/dev/temp/test-type-modifier/src/app/app.component.ts: Unexpected token, expected "," (1:14)
> 1 | import { type SimpleChanges, } from '@angular/core';
| ^
2 | import * as i0 from "@angular/core";
3 | import * as i1 from "@angular/common";
4 | import * as i2 from "@angular/router";
🌍 Your Environment
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 14.1.0
Node: 16.15.0
Package Manager: npm 8.5.5
OS: darwin arm64
Angular: 14.1.0
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1401.0
@angular-devkit/build-angular 14.1.0
@angular-devkit/core 14.1.0
@angular-devkit/schematics 14.1.0
@schematics/angular 14.1.0
rxjs 7.5.6
typescript 4.7.4
Anything else relevant?
The problem only exists with:
- A type-only import which uses the
typekeyword inside the curly braces emitDecoratorMetadataistruein tsconfig.json- Certain type imports
- Production build
Details:
This problem happens when you use type-only imports (using the type keyword) using the syntax introduced in TypeScript 4.5 where you use the type keyword inside the curly braces:
import { type SimpleChanges } from '@angular/core';
and does not happen when you use the type keyword outside the curly braces:
import type { SimpleChanges } from '@angular/core';
We enable emitDecoratorMetadata in tsconfig.json due to eslint rules which require type information (otherwise it thinks DI classes in the constructor should be type-only imports, for example, but they can't be)
This problem only happens with certain imports, and only with @angular imports. Known failing types:
import { type SimpleChanges } from '@angular/core'import { type Route } from '@angular/router'
Known types that don't cause the error:
import { type Routes, type CanLoad } from '@angular/router'import { type OnInit, type OnChanges } from '@angular/core';import { type HttpHeaders, type HttpParams } from '@angular/common/http'- any other npm module, e.g.
import { type Observable } from 'rxjs'- this works fine - any local module, e.g.
import { type MyInterface } from './interface'- this works fine
This problem only happens on production builds. Regular development builds and ng serve work without issue.
For anyone else who experiences this, there is a workaround.
Leave emitDecoratorMetadata set to true in tsconfig.json.
The CLI will use the regular tsconfig.app.json (with this setting set to true) for development and linting.
Create a new tsconfig.app.prod.json file:
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"emitDecoratorMetadata": false
}
}
And in angular.json under the build configuration for production, tell it to use this new tsconfig file:
{
"projects": {
"app": {
"architect": {
"build": {
"configurations": {
"production": {
"tsConfig": "tsconfig.app.prod.json"
}
}
}
}
}
}
}
Alternatively, you can leave emitDecoratorMetadata set to false in tsconfig.app.json and turn it on only for linting in eslintrc.json:
{
"root": true,
"extends": [],
"parserOptions": {
"emitDecoratorMetadata": true
}
}
We are investigating a fix for the issue. However, emitDecoratorMetadata should generally be avoided when possible due to it having known design limitations that can lead to temporal dead zone errors during application runtime. These limitations are not Angular specific.
The last workaround mentioned above of adding the option into the eslint configuration is most likely the ideal option as it avoids the use of the option for built code.
This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.