11 min to read
Angular 13!
Angular 13 Migration
How are you doing? We are back with a new angular migration!!!
Today’s post is dedicated to the experiences during a specific migration from our previous Angular 12 to Angular 13, with news, tips, errors, warnings and their respective fixes to renew us and get it out with fries!
Guide
To begin with, let’s go to the official guide here. In this case, coming from version 12, we do not need to apply changes to our code BEFORE executing the command in order to migrate. Therefore, we can start:
ng update @angular/core@13 @angular/cli@13
Note: add the –force if necessary! So far in every migra it seems to cry out for it!
Most of the required changes we apply with the command. The rest of the possible changes you have to make, will depend as always on the project you are working on and this guide is for those manual changes, here we go! You will also see differences as to whether you are working on an app, or a publishable library by the type of compilation, which we will see later.
ModuleWithProviders migration
If you have modules with providers implementing ModuleWithProviders, the schematic may not be able to determine the type, so it is necessary to migrate those that require the type like this:
@NgModule({…})
export class MyModule {
static forRoot(config: SomeConfig): ModuleWithProviders<SomeModule> {
return {
ngModule: SomeModule,
providers: [
{provide: SomeConfig, useValue: config }
]
};
}
}
More info here!
Rxjs
If you were using RxJS v6.x, you must manually install 7.4:
npm install rxjs@7.4
For fresh projects and apps in this version of Angular, they will install rxjs 7.4 by default. What’s new in Rxjs here!
Of course this does not end here, there are some breaking changes and some deprecations that can impact your project, usually resolved in a short time. Example :
RxJS 7 allow to call 'next' without parameters (Typescript checks).
If you are doing a next in a Subject without params like this:
const updateSubject = new Subject();
updateSubject.next();
can be solved by adding the type
private subject$ = new Subject<void>();
More info here!
Compilermode
Angular library
If you are working on an npm publishable library, you may encounter this error:
Unsupported private class
This class is visible to consumers via SomeModule -> SomeComponent, but is not exported from the top-level library entrypoint
To solve it, you will have to look for components and modules that are not properly exported in the public_api.ts.
This can happen because with Ivy, it is a requirement that if we want to export a module from a library endpoint, we must manually re-export all the elements involved as well (components, pipes, directives, everything!). Before with View Engine, this was automatic. But with Ivy we must explicitly do it, remember that Ivy is here to stay and View Engine in this version is officially deprecated.
More info here! Angular libraries official docs here!
Error para Angular library: NG3003: Import cycles would need to be created to compile this component
Also known as:
One or more import cycles would need to be created to compile this component, which is not supported by the current compiler configuration.
is used in the template but importing it would create a cycle
If you ran into this cyclic error, it only occurs in angular library, if you are not working in a publishable library, you are safe and you earned the direct pass to the next section, get out of here! This error could mean a change of low/medium complexity depending on the case, since we must take into account if it is a matter of imports with circular dependencies (low complexity) or if we need to apply refactor (medium complexity not so cheap). For example in a case where in certain situations, component A embeds component B, and where component B may embed component A. Most likely we will have to refactor if we have the latter case. The explanation of the error and possible suggestions to fix it from official Angular here!
This occurs because of the type of compilation, being either “partial” or “full” in our
tsconfig.lib.prod.json.
Being in a library, we must use “partial” because we need the backward compatibility of consumers with or without Ivy. In an app (no library), the compilation type will be “full” and you won’t see this beautiful error ever. Now, what if we are working on an Angular library, and we manually modify to “full” compilation mode? Do we cheat the npm publish yes or no?
ERROR: Trying to publish a package that has been compiled by Ivy in full compilation mode. This is not allowed.
Please delete and rebuild the package with Ivy partial compilation mode, before attempting to publish.
The build will tell you yes yes yes and when you run the npm publish
it will welcome you with that error above… so no, don’t even try, compile in partial
and don’t waste valuable time on this.
Unless you want to super investigate these types of compilation and why, I leave you with this one. artículo which is very good, with graphics and everything is clear.
Errors/Warnings
In general and in each new version of Angular, errors and/or warnings are becoming more restrictive in several points but they are also becoming more descriptive, so they could be solved from the same suggestions that they offer us. That is why, I preferred to focus this post to the errors that are not so easy to solve and also to those that take us more time of analysis and investigation for its resolution. Remember to always run and compile the production build to exterminate the remaining bugs.
Storybook
If you are using Storybook in your project, there is a great migra also with several manual settings to keep Storybook up to date. The most important thing in this version: We have Angular compiler for storybook, so from our angular.json we are going to leave it configured. As always I suggest the official Storybook migration guide:
Another issue that happened to me, was one of the problems in storybook compilation, of this style:
preview.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
So I had to apply changes to the .storybook/tsconfig.json
for the includes, such as here!
And if you see this: can only be default-imported using the'allowSyntheticDefaultImports' flag
You can solve it by adding that flag in the tsconfig of the root project (not storybook like the previous one):
"allowSyntheticDefaultImports": true,
If the compilation problems persist and we see this:
```
UnhandledPromiseRejectionWarning: TypeError: The 'compilation' argument must be an instance of Compilation
```
you can check that you don’t have the sourceMap on for debugging, in the angular.json it should look like this:
"sourceMap": false,
More info here!
If we still see this evil:
UnhandledPromiseRejectionWarning: TypeError: The 'compilation' argument must be an instance of Compilation
Vamos a tener que revisar y verificar las versiones de webpack de angular y webpack de storybook, para eso seguimos estos pasos:
1. `npm ls webpack`
2. search for the version of webpack for `@angular-devkit/build-angular`
3. `npm install` exact version at dev dependencies
4. `npm dedupe` // WTF? yup, this tries to simplify the package deps tree
More info here!
Jest
If you’ve decided to say goodbye to Jasmine and Karma, and started to delve into the magical world of Jest, here are the necessary adjustments for this version!
To begin with, in my experience I migrated all of Jest to these new versions:
"@types/jest": "27.4.1",
"jest": "^27.4.7",
"jest-preset-angular": "^11.0.1",
"ts-jest": "^27.1.2",
To migrate and update our jest.config.js by npm command we execute:
npx ts-jest config:migrate jest.config.js
Other ways here:
Also, you may need to follow these steps to migrate according to the changelog
I’ve seen this one:
Need to call TestBed.initTestEnvironment() first
and this other one too:
Zone is needed for the waitForAsync() test helper but could not be found. Please make sure that your environment includes zone.js
Both fixed at test.ts like this:
import "jest-preset-angular";
import "zone.js";
import "zone.js/testing";
import { TestBed } from "@angular/core/testing";
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from "@angular/platform-browser-dynamic/testing";
TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
More info here!
Some changes may only affect you depending on the version of Jest and jest-preset-angular you are currently using, just in case you check them out here.
If you see this:
[Package subpath './src/ngtsc/reflection' is not defined by "exports" in /node_modules/@angular/compiler-cli/package.json](https://stackoverflow.com/questions/70306517/package-subpath-src-ngtsc-reflection-is-not-defined-by-exports-in-node-mo)
You could check if the jest versions need another change as they indicate here.
Another error I found was:
Cannot configure the test module when the test module has already been instantiated. Make sure you are not using `inject` before `R3TestBed.configureTestingModule`
To fix it, you would need to add the teardown to your tests under configureTestingModule like:
teardown: { destroyAfterEach: false },
More info here!
Advantages and changes in this version
From Official Blog we have all the data of the changes coming with Angular 13, so I highlight and summarize some very interesting points:
- Ivy everywhere, View Engine is deprecated.
- Component API updates: to create dynamic components, the boilerplate was reduced and the component factory resolver we used was deprecated, so we can only use the viewContainerRef and the createComponent for this purpose!
- End of IE11 support: beautiful news although we can also say something melancholic for some, a few last words: there are many of us who still surely remember when we supported the old IE with those conditionals and I don’t know how many hacks in CSS to make it look just like what we wanted, it was not much to ask, but I assure you that it was harder than a Cuphead boss.
- Improvements to the Angular CLI: cache build by default!
- RxJS: now in new apps with Angular 13, RxJS version 7.4 will be installed by default, for manual migration you must install
npm install rxjs@7.4
. - TypeScript 4.4: Changes here and breaking changes here!
-
Improvements in Angular tests: using Jasmine, now improved and a DOM cleanup is done in each test, optimizing them:
teardown: { destroyAfterEach: true }
- Accessibility issues: if you use Angular Material, there are several accessibility improvements! All the details here
- Inline Fonts: Since Angular 11 they gave inline support to Google Fonts. In this version 13, they extend the support to Adobe Fonts.
- Changes and contributions from the community: among them changes to enable/disable validators in dynamic forms, and the restoration of the browser history in the RouterModule by ` { canceledNavigationResolution: ‘computed’ },`.
Happy coding!!!