paint-brush
Upgrading Angular From v8 to v13by@windmateus
5,098 reads
5,098 reads

Upgrading Angular From v8 to v13

by Windson MateusMay 15th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Upgrading from Angular 8 to 13 - the most common errors and their respective solutions

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Upgrading Angular From v8 to v13
Windson Mateus HackerNoon profile picture


In this post, I will report what I learned in the migration of Angular applications v8 to v13.


In addition, I will show you the most common errors that you may encounter in the process as well as their respective solutions, indicating the sources when appropriate.


I spent 1 year and a half allocated in a division that worked with many applications and a suite of components built in Angular 8.


Angular JS

In the last 2 months of last year, we had meetings with the frontend working group where the subject of angular application migration has always been talked. Considered a critical issue, especially when we remembered the risk of recent cases such as the log4j vulnerability in Java and the discontinuity of the faker library that affected the projects in AngularJS, officially unsupported.


Then came an opportunity to work with technical debt. When we did this work the Angular version was 13 and because Google only supports up to 2 previous versions, Angular 2 through 10 were no longer supported.


Angular support policy and schedule

Initial guidelines


Keep Calm and NG Update

We take the experience we had in migrating the component project from Angular 8 to 13. These are the possible migration approaches:

  1. Run a ng update with each version because it is not possible through it to move from version 8 straight to 13, so you need to run this command to migrate from 8 to 9, from 9 to 10, and so on. The advantage is that it converts the code automatically, but the process of going through so many versions ends up being more costly and therefore it is not advised in our case where there was a gap of 5 versions. It may be the most appropriate option for future migrations.

  2. Create a new project in Angular 13 and copy the fonts from the old project into Angular 8. Then solve the problems as they arise. This approach has been adopted for the migration of our component project and is what we recommend in this situation.


Migration roadmap

1) Install the latest version of Angular


npm install -g @angular/cli


2) Create a new project


ng new novo-projeto


3) Copy fonts from an old project

When copying the fonts it is advised to keep the new package.json that was generated to include and resolve the various dependencies on demand so that at the end of the process only the ones really needed are included, thus also meeting the best safety standards.


Update angular versions of the package.json of the subprojects (if any) as well.


4) Modify tsconfig.lib.json settings

Update the tsconfig.lib.json files in the subprojects (if any) to align with the current tsconfig.json files

"target": "es2017",   "module": "es2020",   "lib": [   "es2020",   "dom"   ]


Common configuration errors and solutions

  • An unhandled exception occurred: The target entry-point "@novo-projeto" has missing dependencies: primeng/toast, primeng/button


Add the primeng to the package.json. This will be the most common error because it will occur for all the various dependencies that have not yet been included, such as bootstrap, ng-select, among others.


Try to always define the version of the dependency corresponding to the current version of Angular in the project.


Other situations that can be solved in this way are errors of the type:

Script file ____ does not exist.

or

An unhandled occurred exception: ENOENT: no such file or directory, lstat ______


  • "ng build" for library fails with "does not support the 'build' target


Copy angular.json file from the old project


  • npm WARN @angular-devkit/[email protected] requires a peer of ng-packagr@^10.0.0 but none is installed. You must install peer dependencies yourself.


The build-ng-packagr has been discontinued.


Remove the build-ng-packagr from package.json and modify the tasks in angular.json, so that where there is @angular-devkit/build-ng-packagr:build replace for @angular-devkit/build-angular:ng-packagr


  • Directory import '...\node_modules\@angular\compiler-cli\ngcc' is not supported resolving ES modules imported from ...\node_modules\ng-packagr\lib\utils\ng-compiler-cli.js. Did you mean to import @angular/compiler-cli/ngcc/index.js?


Resolves by modifying the version of ng-packagr in the package.json file to one corresponding to the Angular version of the project.


  • Cannot resolve type entity i5.Scrolling Module to symbol* ou *ERROR: The target entry-point "primeng/dropdown" has missing dependencies: @angular/cdk/scrolling


It is solved by adding the @angular/cdk to package.json.


  • ModuleError: Module Error (from ./node_modules/postcss-loader/dist/cjs.js) ... Can't resolve 'OpenSans-Regular.eot' in '...\dist\seus-components\css'


Install the postcss and postcss-cli:


npm install postcss postcss-cli


  • Error: Module not found: Error: Can't resolve 'chart.js/auto'


Install chart and ng2-charts, which is a wrapper of the first, running:


npm install --save ng2-charts and npm install --save chart.js


Common errors involving code change and solutions

  • Module error type: '"primeng"' has no exported member 'ConfirmDialogModule'


The earlier versions of primeng imports were like this:

import { Checkbox, MessageService, ConfirmDialogModule } from 'primeng/primeng';


References are now more specific, so they need to be corrected:

import { Checkbox } from 'primeng/checkbox';   import { MessageService } from 'primeng/api';   import { ConfirmDialogModule } from 'primeng/confirmdialog';


  • error TS1323: Dynamic imports are only supported when the '--module' flag is set to 'es2020'


In order to support dynamic imports, add this line to tsconfig.json:


"module": "esnext",


  • When working with observables, error Error TS2554: Expected 1 arguments, but got 0 may arise

Occurs after migration to rxjs 7. It can be solved by passing a fake value:


this.subject.next("");


  • Error: Module not found: Resolving to directories is not possible with the exports field (request was ./)


It usually occurs after migration to Angular 12. It is solved by removing the "/" at the end of imports or replacing double quotes with a single. Example:


Before:

import { MsgCenterModule } from '@seu-componente/etc-client/';


After:


import { MsgCenterModule } from '@seu-componente/etc-client'; 


Before:


import { ABCEnum, XYZEnum } from "../../tabela.constants";


After:


import { ABCEnum, XYZEnum } from '../../tabela.constants'; 


  • An error of the type: Module not found: Error: Can't solve 'dayjs' / Error: Module not found: Error: Can't solve 'inputmask'


Installing this library because even though it is not directly used in the application, it is necessary in some cases because it is referenced by the component used:


npm install dayjs --save

npm install inputmask --save


  • Type error: Object is possibly 'null'. TS2531 for window.document


The typescript compiler is indicating that window.document.getElementById('content') may return NULL.


Since it is a migrated code that already worked previously, just add the ! to this code:


document.getElementById('content')!. innerHTML = '';


  • error NG8002: Can't bind to 'minWidth' since it isn't a known property of 'p-dialog'.


From primeng 9 some properties must be set in style. Therefore, in html, where it has

[width]="600" [minWidth]="200" change to [style]="{width: '600px', minWidth: '200px'}". Look at the brackets or a CSS-style setar error occurs.


  • error TS7006: Parameter 'perfis' implicitly has an 'any' type


This is because variables now need to have some type defined, so it is necessary at all points in the code to set them to any or for a more specific type.


A sometimes pointed solution is to set "noImplicitAny" to false in the tsconfig.json, but it is not advised.


  • error TS2564: Property 'titulo' has no initializer and is not definitely assigned in the constructor


Starting with version 2.7 the typescript compiler requires that the property/variable be initialized.


To solve this there are several approaches but we chose to add the "!" in the definition of the variable:

public container!: ViewContainerRef;


We did this because we have assurances that this was initialized because it worked on the previous project in Angular 8 since the previous code ran without errors during runtime.


Note: In tsconfig.json, compilerOptions can be defined as "strictPropertyInitialization": false, to ignore these errors and speed up this phase of migration, but it is recommended to go back to true later.


  • error TS2322: Type 'string | null' is not assignable to type 'string | undefined'.


Very common when setting an interface property as optional, solved with "!" just like the previous error.


  • error TS2322: Type 'Boolean' is not assignable to type 'boolean' ... 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible


Newer versions of typescript are more rigid. In this case, you will need to modify the code to use the boolean primitive type.


  • error NG3001: Unsupported private class MsgCenterComponent. This class is visible to consumers via SistemaClientModule -> MsgCenterComponent, but is not exported from the top-level library entrypoint.


It usually happens from version 9 of Angular. Add it to the public_api.ts the line corresponding to the class in question, in this example:


export * from './lib/msg-center/msg-center.component';


  • error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s)


Change the code as follows, in this example:


static forRoot(): ModuleWithProviders<XYZClientModule>


  • error TS7030: Not all code paths return a value.


Ensure that the value is returned to the code in question. It usually occurs in more extensive if-clauses.


  • error TS2339: Property 'throw' does not exist on type 'typeof Observable'


Change the call to:


return throwError(() => response);


  • error TS1192: Module '".../node_modules/@types/uuid/index"' has no default export.


Install dependency:


npm i --save-dev @types/uuid


Modify the call in the code to:


import * as uuid from 'uuid';


  • error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'. No index signature with a parameter of type 'string' was found on type '{}'


You need to define the type of index that the object has by modifying the code to:

pagesStatus: {[index: string]:any} = {}


  • error TS2322: Type 'string' is not assignable to type 'number'


This can occur in html tag attributes. For example, where there were:


<p-fileUpload mode="advanced" name="demo[]" maxFileSize=1000000 multiple=true chooseLabel="Buscar arquivo" (onUpload)="onUpload($event)"></p-fileUpload>


Place the brackets:

<p-fileUpload mode="advanced" name="demo[]" [maxFileSize]="1000000" [multiple]="true" chooseLabel="Buscar arquivo" (onUpload)="onUpload($event)"></p-fileUpload>


After upgrading

  • Code entryComponents Removal: From Angular 13 on, the use of entryComponents is no longer required


  • Remove [responsive] attributes from p-dialog. In the new version, such components are fully responsive and so the attribute has been discontinued.



Also published here.