Angular CLI 1.7.0 is out with some nice new features!

If you want to upgrade to 1.7.0 without pain (or to any other version, by the way), I have created a Github project to help: angular-cli-diff. Choose the version you’re currently using (1.2.1 for example), and the target version (1.7.0 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/1.2.1…1.7.0. You have no excuse for staying behind anymore!

Let’s see what new features we have!

App budgets

One of the major new features is the ability to set budgets for your applications. In .angular-cli.json, you can now add a new section looking like:

"apps": [
  {
    "budgets": [
      { "type": "bundle", "name": "main", "baseline": "300kb", "warning": "30kb" },
      { "type": "bundle", "name": "races", "maximumWarning": "360kb" },
      { "type": "allScript", "baseline": "1.4mb", "maximumError": "100kb" },
      { "type": "initial", "baseline": "1.6mb", "error": "100kb" },
      { "type": "any", "maximumError": "500kb" }
     ],

As you can see, there are several types of budget:

  • bundle, a specific bundle that you name;
  • allScript, all your application scripts;
  • all, all the application;
  • initial, the initial size of the application;
  • anyScript, any one of the script;
  • any, any one of the files.

The sizes are compared to the baseline you specify. If you don’t specify a baseline, then the baseline used is 0.

There are several types of error:

  • maximumWarning: warns you if size > baseline + maximumWarning;
  • minimumWarning: warns you if size < baseline - minimumWarning;
  • warning: same as defining the same maximumWarning and minimumWarning;
  • maximumError: errors if size > baseline + maximumError;
  • minimumError: errors if size < baseline - minimumError;
  • error: same as defining the same maximumError and minimumError.

This is a pretty cool feature, as it allows to keep the size in check without additional tooling (like bundlesize)! And these may be the only budgets your app won’t go over ;)

ng update

Good news, we have now a command to automatically update the Angular dependencies of our CLI applications.

If you use the new CLI 1.7, just run:

ng update

And all your @angular/* dependencies will be updated to the latest stable! This includes all the core packages in your dependencies and devDependencies, but also the CLI itself, and other Angular packages like Material, or DevKit. It does so recursively, so dependencies like rxjs, typescript or zone.js are automatically updated too!

The command does not have a lot of options (only a dry-run option and a next option to update not to the latest stable, but to the next version), so it’s currently an all or nothing process.

But it relies on a schematic (introduced in CLI 1.4, see our blog post), called package-update, that you can use directly. In broad lines, a schematic is a package that contains tasks allowing developers to create code (a full project, a component, a service…) and/or to update code (like updating configuration or classes, adding a dependency, etc…). All the “classic” tasks and blueprints of Angular CLI are in the @schematics/angular package, but the CLI team is gradually rolling in a few new ones to add features, like @schematics/package-update.

This new schematic offers 4 tasks:

  • @angular to update the Angular packages
  • @angular/cli to update the CLI
  • @angular-devkit to update the DevKit
  • all to update all at once

The ng update command calls the all task of the schematic, but you can use the schematic directly if you need or want to.

I’ve never really explained how to do so, so let’s take an example: you only want to update the Angular packages but not the CLI version.

First, install the schematic:

yarn add --dev @schematics/package-update

Add a schematics script in your package.json:

"scripts": {
  "ng": "ng",
  "schematics": "schematics"
  // ...
},

and run:

yarn schematics @schematics/package-update:@angular

And you’ll only have your Angular packages (and their own dependencies) updated.

You can also specify a version to the schematic:

yarn schematics @schematics/package-update:@angular --version 5.2.3

Configuration simplifications

I usually don’t mention that a few files have changed in the project template, but for once it comes with a few simplifications and new options, so you should definitively take a careful look at all the changes, especially in the:

  • test.ts file (new zone.js import, simplified logic)
  • polyfills.ts file (shows how to use some zone.js capabilities)
  • tslint.json file (rules added and removed)
  • package.json file (lots of dependency bumps)

You can easily see these changes with our angular-cli-diff repository, for example between an old version and the last one: angular-cli-diff/compare/1.2.1…1.7.0

E2e test suites

The e2e task can now take a --suite option, to run only part of your e2e tests. You can define suites of tests in your protractor.conf.js configuration file:

exports.config = {
  suites: {
    perf: 'e2e/perf/**/*.e2e-spec.ts',
    regression: [
      'e2e/regression/**/*.e2e-spec.ts',
      'e2e/bugs/**/*.e2e-spec.ts'
    ]
  },

And then run:

yarn e2e --suite perf,regression

Service worker safety

Service workers are a really nice feature of modern browsers, and Angular offers a package to help you use them, introduced in Angular 5 (see our blog post). Angular CLI also has a very good support for them, as we explained in our blog post.

But they can also be tricky, as everything involving caching in our industry… If you need to deactivate an already installed service worker, @angular/service-worker will include a safety-worker.js script starting with Angular 6, and the CLI 1.7 adds support to automatically include it in the production bundle. You must then serve the content of this script at the URL of the service worker you want to unregister.

Angular 6 support

As Angular 6 stable is right around the corner (end of March if everything goes well), the CLI is now compatible with it, meaning you can give a try to version 6 right now!

Angular Compiler options

The Angular Compiler options are now supported!

That means if you try to use for example the fullTemplateTypeCheck option introduced in Angular 5.0 (see our blog post), you can now just update the tsconfig.json file of your CLI project, and when you will run ng serve --aot or ng build --prod the option will be picked up!

TypeScript 2.5 and 2.6 support

As Angular 5.1 supports TypeScript 2.5 (see our blog post) and Angular 5.2 now supports TypeScript 2.6 (see our other blog post) , the CLI will no longer complain if you use these TS versions.

Webpack 4 support

As you may know, the CLI uses Webpack under the hood. Webpack is currently in version 3 but the version 4 should not be far away, bringing in some performance enhancements and some nice features (like the side-effect feature which should reduce our bundle sizes, better defaults, WebAssembly support, etc…).

The CLI is getting ready to switch to Webpack 4, and we should enjoy some of these nice features (reduce bundle sizes, faster builds) soon!

Better, faster, higher

The tasks have been slightly improved with the introduction of caching, so your build should be faster!

Check out our ebook, online training (Pro Pack) and training if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Angular 5.2.0 is here!

Angular logo

Let’s see what 5.2 has in stock for us!

Templates

Angular 5.0 introduced the fullTemplateTypeCheck option in the compiler. When activated, the Angular compiler will be stricter when checking your templates and catch potential type errors (check our Angular 5.0 blog post to learn more). The feature is really powerful but sometimes you can run into expressions in your templates that you know will work at runtime, even if the compiler can’t type-check them.

Angular 5.2 introduces a new function you can use in your templates, called $any(). $any() can be used in binding expressions to disable type checking of this expression. This is really similar to as any in TypeScript, and allows expressions that work at runtime but do not type-check.

interface PonyModel {
  name: string;
}

@Component({
  template: '<p>Hello {{ $any(ponyModel).age }}'
})
export class PonyComponent {
  ponyModel: PonyModel;
  // ponyModel has no field age, so the template should not compile
}

As for any in TypeScript, I’m not really a fan of using this: I usually prefer to have a correct type instead of “cheating” with any or $any(). So this is not really for the day to day use.

This is rather intended to help the applications using fullTemplateTypeCheck which can raise type errors hard to fix, usually from third party libraries. For example, we use ng-bootstrap and there were two errors in 1.0.0-beta.7. We fixed them, so if you use ng-bootstrap@1.0.0-beta.8 or a more recent one, you should be OK!

This was also introduced for internal use in the framework (see below).

Compiler

Still regarding this feature, some work has been done to have more accurate errors in your template if you use the strictNullChecks option form the TypeScript compiler (see our blog post about Angular 4.1 to learn more about this) with fullTemplateTypeCheck.

For example, the compiler was not really good at determining a situation like this one:

@Component({
  template: `<div *ngIf="ponyModel">{{ ponyModel.name }}</div>`
})
export class PonyComponent {
  // ponyModel can be a pony or null
  @Input() ponyModel: PonyModel | null;
}

Here, using strictNullChecks and fullTemplateTypeCheck, the compiled template would raise an error, as the TypeScript code generated could not see that, because of the *ngIf wrapping it, the evaluation of ponyModel.name was safe. The expression is only evaluated if ponyModel is not null, so there is no risk, but the compiler could not see it and was considering ponyModel to be PonyModel | null:

src/app/pony/pony.component.html(1,25): : Object is possibly 'null'.

Some work has been done by the Angular team to fix this: now the TypeScript code generated will take into account the *ngIf guard, and automatically consider ponyModel as a not null entity inside the *ngIf! So where we used to “cheat” and write:

{{ ponyModel!.name }}`

We can now simply write:

{{ ponyModel.name }}

and the compiler will understand the situation!

Note that this a generic feature: if you write your own structural directive, that works like an *ngIf, you can also leverage this type guard feature by adding a static field called ngIfUseIfTypeGuard to your directive.

Router parameters inheritance

Previously, the router would merge path and matrix params, as well as data/resolve, with special rules (only merging down when the route was an empty path, or was component-less).

Angular 5.2 adds an option called paramsInheritanceStrategy which can take different values:

  • when set to always, it makes child routes unconditionally inherit params from parent routes;
  • when set to emptyOnly, the default, it only inherits parent params for path-less or component-less routes (the former behavior).

Project Ivy: a faster and smaller renderer

This release doesn’t have many features because part of the team is currently rewriting one piece of the framework: the renderer.

We don’t know much about this project (codename Ivy) as the design doc is not public right now, except that it should make the renderer smaller and faster, with a simpler design, allowing a better incremental compilation (faster builds for us \o/), and will be fully backwards compatible (hopefully no breaking changes \o/). We’ll keep you up to date when this feature is ready (it’s still in early stages).

That’s all this release!

All our materials (ebook, online training (Pro Pack) and training) are up-to-date with these changes if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Angular CLI 1.6.0 is out with some nice new features!

If you want to upgrade to 1.6.0 without pain (or to any other version, BTW), I have created a Github project to help: angular-cli-diff. Choose the version you’re currently using (1.2.1 for example), and the target version (1.6.0 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/1.2.1…1.6.0. You have no excuse for staying behind anymore!

Let’s see what new features we have!

Service Worker

A new flag has been added to the ng new command and allows to generate an application with service workers already enabled and configured. Service workers are a great new API in the browser, acting like a “client-side proxy”: when your application requests an asset, it will first “ask” the service worker if it is available, before really hitting the network if it isn’t. It can really speed up the second and following visits to your application, and can even be a step to working offline, and towards what’s called a Progressive Web Application (PWA).

This new flag uses the brand new @angular/service-worker package released in v5.0.0. Older versions of the CLI only work with the older version of this package: if you want to use the brand new one, you’ll have to update to the CLI v1.6.

The flag will add a file named ngsw-config.json which is the configuration file for the Angular Service Worker package.

The file looks like this:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html"
      ],
      "versionedFiles": [
        "/*.bundle.css",
        "/*.bundle.js",
        "/*.chunk.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }]
}

This means that the main file is index.html, that you want to prefetch some resources, some of which have a fixed name, while some others are versioned. Some other resources are less critical assets and are loaded lazily (only when needed).

The flag will also add an import to your main module:

imports: [
  BrowserModule,
  ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })
],

This will activate the ServiceWorkerModule if you are in “prod” mode, and register the service worker generated by the CLI based on the previous config. As the worker is only enabled in “prod” mode, you won’t see a difference using ng serve. It’s only when building your application with ng build --prod that you’ll see a few new files in your dist directory.

As this module is in @angular/service-worker, it will also add this package to your dependencies. And it will turn on the serviceWorker option in your .angular-cli.json.

This is pretty straightforward and gives a great basis. Even if you have an existing application, you can follow these steps and end up with the same result!

You can go much further, and add configuration for your API calls by selecting the strategy you want: always call the server (freshness), or always from cache (performance), etc.

"dataGroups": [
  {
    "name": "races-api",
    "urls": ["/api/races"],
    "cacheConfig": {
      "strategy": "performance",
      "maxSize": 10,
      "maxAge": "30m",
      "timeout": "5s"
    }
  }
]

Here I cache the calls to /api/races for 30 minutes, meaning all requests to this endpoint in the next half hour will return the same result as the first one, even if offline.

You can also add external resources like fonts to the configuration to also cache them.

To give it a try, build your app with ng build --prod, then serve your dist directory with a static HTTP server, like http-server. Open your application with Chrome, and go the Developer Tools in the Application tab. You should see the service worker registered in the Service Worker section! And you can see which parts are cached in the Cache Storage section.

Note that the service worker really caches your application, meaning that a new version deployed in production will not be seen immediately by your users. If you deploy a new version, the application will fetch the new NGSW file on reload, but will use the old one, until your user refreshes the page another time. That’s why you see on some websites a small popup “A new version is available, do you want to refresh?”. If you want to implement such a process, Angular can help you with its service SwUpdate:

export class AppComponent implements AfterViewInit {

  @ViewChild('modal')
  private modalContent: ElementRef;

  constructor(private swUpdate: SwUpdate, private modalService: NgbModal) {
  }

  ngAfterViewInit() {
    if (this.swUpdate.isEnabled) {
      this.swUpdate.available.subscribe(event =>
        // update available: ask the user to reload
        this.modalService.open(this.modalContent).result.then(
          () => this.swUpdate.activateUpdate()
            .then(() => document.location.reload()), // load the update
          () => {} // do nothing if the user wants to refresh later
        )
      );
    }
  }
}

Here I’m subscribing to the available observable exposed by SwUpdate. As soon as a new version of the application is available, the observable will emit an event. In the example above, I chose to open a modal with ng-bootstrap to ask the user to reload the application. If he/she chooses to do so, we load the new version with activateUpdate() and reload the page. If not, we do nothing. You can of course display what you want (just an alert, a toast…).

Universal

One of the main features of this release is the ability to add server side rendering capacity to your application with a simple command. Server-side rendering (called “universal” in Angular) is possible since quite some time, but the CLI had no automated way to do it.

This is now fixed: you just have to run ng generate universal server-app and Angular CLI automatically sets things up for you:

  • creates a new module app.server.module.ts, which uses ServerModule instead of BrowserModule;
  • creates a main file main.server.ts;
  • creates a TypeScript config tsconfig.server.ts
  • adds a dependency to your package.json @angular/platform-server;
  • updates .angular-cli.json to add a new “app”, called “server-app” in my example, in your project;
  • updates your main module to use the brand new (Angular 5) BrowserModule.withServerTransition() which ensures the client app has a smooth transition when it boots;
  • wraps the bootstrap call in a DOMContentLoaded event handler.

You can customize pretty much everything:

  • the application name, by default the one you gave in the command line
  • the clientApp name, by default 0, as you usually have only one app in your CLI project
  • the appId, used by withServerTransition(), by default serverApp
  • and the name of every files mentioned above!

Note that you’ll have to add the deprecated @angular/http package even if you don’t use it, because @angular/platform-server still depends on it.

Now you should be able to build the application!

ng build --prod --app=server-app

And you’ll get the bundles in dist-server/. Than it’s up to you to set up a server to use these, probably a NodeJS server, using something like Express and its ngExpressEngine (that’s the official example in the documentation). The job of the server will be to answer a request with an HTML generated using the JS bundles from dist-server.

Or you can continue reading, and discover another new feature of the CLI ;). You won’t be able to use ng serve with this app though (not yet, but I think it’s coming!).

Application Shell

The other new feature is the Application Shell. A new schematic has been added allowing to generate a “shell” - an index.html containing a static rendering of your application. This uses the universal part I mentioned above for the server-side rendering.

ng g app-shell appShell --universal-app=server-app

The command here uses the serverApp I created above. If you did not create it, the CLI will generate it for you ;)

The command will:

  • update .angular-cli.json to add the appShell key with its configuration "appShell": { "app": "server-app", "route": "shell" };
  • add an AppShellComponent to your application;
  • update the app.server.module.ts to add a route with the path specified pointing to the AppShellComponent.

Now when you’ll build the application with ng build --prod the dist and dist-server directories will be generated, and the index.html file in dist will contain the prerendered AppShellComponent. This means you’ll have a meaningful content served right away when deploying to production (as you can of course put whatever you want in the shell component). When the application is done starting, it will be displayed as usual.

The three features can be combined nicely: you can add a universal/server-side rendering capability to your application, add an application shell to have a fast first render using this capability, and use service worker for the following renderings!

These features are still very new (application shell was still quite buggy when I tested it…), but look promising for the applications that need to start faster.

Check out our ebook, online training (Pro Pack) and training if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


À l’heure des étrennes de fin d’année, c’est le moment idéal pour faire un point sur notre argent (i.e. l’argent que vous nous avez donné), et sur la meilleure façon de le dilapider en toute sérénité morale.

Donations sur les ventes d’ebook

Dès notre premier ebook sur AngularJS, nous avions souhaité un mode de vente plus participatif : non seulement l’ebook serait sans DRM, mais nous le vendrions en direct sans éditeur, à prix libre*, et avec un don optionnel à une association caritative. L’association alors choisie fut Docteur Souris, qui offrait aux patients hospitalisés un accès Internet, et notamment aux enfants pour poursuivre leur scolarité et rester en contact avec leurs amis.

Docteur Souris propose un accès Internet aux enfants hospitalisés

Si nous en parlons au passé, c’est que Docteur Souris a dû malheureusement fermer ses portes en 2017. Après avoir déjà effectué un premier don de plus de 2000€, il restait encore plus de 1400€ à reverser, puisque vous aviez choisi de donner 24% en moyenne à l’association, comme vous pouvez le constater sur nos chiffres de ventes publics.

Nous avons donc dû choisir une association alternative. Pour ne pas trahir la finalité de vos dons, nous nous sommes arrêtés sur Le Rire Médecin, qui a pour mission d’aider les enfants hospitalisés et leurs parents à dépasser leur angoisse et leur solitude.

Et voici que nous venons de leur reverser 1400€ ! 👏

Si ce don ouvre droit à des déductions fiscales, nous ne l’exercerons pas. Nous ne donnons pas l’argent de Ninja Squad, mais celui reçu des acheteurs : on ne veut pas voler l’état de revenus qui n’ont aucune raison de nous revenir.

Pour un Internet libre

Avec le deuxième ebook sur Angular (Angular 2, Angular 4, Angular 5…), nos ambitions s’envolaient : nous visions l’international, avec un ebook écrit en anglais (et aussi traduit en français). Il nous fallait alors une association au périmètre plus large, connue dans le monde entier, dans laquelle non seulement nos fans autochtones pourraient se reconnaître, mais aussi nos nouveaux amis transatlantiques, et potentiellement tous ceux de la centaine de pays qui l’ont finalement acheté 👋💋. Nous avons alors choisi l’Electronic Frontier Foundation, qui défend un internet libre (et avec la volonté actuelle du congrès américain de vouloir tuer la neutralité du net, cela nous semble toujours terriblement important et actuel 😓).

Nous n’avions jusqu’alors pas encore reversé vos dons. C’est désormais chose faite : 4500€ ($5.140) viennent d’être donnés à l’EFF. C’est formidable, merci à vous ! ✌️

Donation de Ninja Squad d'un montant de 4500€ ($5.140) à l'Electronic Frontier Foundation

Développement solidaire bénévole

Une autre forme de contribution associative : le développement bénévole d’application pour ceux qui en ont besoin sans les moyens associés.

Notre siège social est dans la Loire, pas loin de Saint-Étienne. On y connait Globe42, un espace social et de santé participatif. Accueillant des migrants âgés, ils assuraient jusqu’alors la gestion de leurs membres sans l’aide de l’informatique, pour écarter toute faille de confidentialité qu’un non-spécialiste peut craindre, notamment vis-à-vis du cloud (qui n’est que l’ordinateur de quelqu’un d’autre).

Nous avons alors voulu les aider. En proposant bénévolement nos services de développeurs, non seulement nous nous offrions un side-project pour pratiquer les technologies du moment (Angular 5, Spring Boot 2, JUnit 5, …) sur une vraie application, tout en aidant une association qui le méritait, et dont on pouvait ainsi faciliter le travail.

Make the World a better place... through scalable fault-tolerant distributable databases with ACID transactions (Silicon Valley, the TV series)

Si cela vous intéresse, le code est sur Github.

Un engagement caritatif plus large

Chez Ninja Squad, on aime bien tout faire nous-même. Alors quand se pose chaque année la question de quoi faire de nos bénéfices, nous n’avions pas le courage d’engager des avocats spécialisés pour organiser notre évasion fiscale dans des paradis fiscaux, comme c’est normalement la tradition dans le business.

Nous avons alors décidé de nous doter d’un nouvel outil de dilapidation du capital de l’entreprise pour le bien de l’Humanité : chaque salarié se voit doté d’une enveloppe caritative annuelle.

Pour le moment, nous commençons modestement : Ninja Squad offrira 500€ par salarié à l’association de son choix.

Pourquoi une enveloppe d’entreprise, alors que chaque salarié pourrait donner à titre personnel, quitte à augmenter nos salaires d’autant ? Question légitime.
Quand l’entreprise verse un salaire, les charges patronales et salariales viennent le diviser par ~2. Et il semblerait que les déductions fiscales accordées aux entreprises sur les donations soient plus lâches que pour les particuliers (notamment envers les établissements publics d’enseignement, mais cela reste à confirmer formellement).

Prenons un exemple. On voudrait donner 1000€ à une association :

  • Ninja Squad donne 1000€.
  • Avec les déductions fiscales (60% dans la limite de 0,5% du chiffre d’affaire), cela lui coûte 400€.
  • Si ce montant de 400€ devait être versé en salaire pour être donné à titre personnel par le salarié, cela équivaudrait à ~200€ nets.

Ainsi, en donnant par l’entreprise, on a virtuellement multiplié le don par 5 ! Certes, c’est au détriment de l’impôt. C’est pourquoi, si comme nous on croit aux valeurs du service public, il convient de rester dans des montants raisonnables, marginaux par rapport aux salaires et bénéfices, ce qu’assure déjà partiellement le plafond de 0,5% du chiffre d’affaire.
Dans notre cas, pour un chiffre d’affaires de ~300 000€, la limite de déduction est donc à 1500€.

En donnant 500€ par salarié, on maximise ainsi la contribution aux associations, sans grever la contribution de Ninja Squad aux impôts nationaux.

Et plus globalement, nous trouvions tout simplement séduisante cette idée d’enveloppe caritative, non sans une certaine fierté d’avoir créé une entreprise commerciale qui contribue au tissu associatif. 💪✊

A bientôt pour de nouvelles aventures fiduciaires 🤓, et n’hésitez pas à suggérer à votre patron de faire de même ! 😘


* Les purs libristes vous expliqueraient mieux que nous qu’imposer un prix minimal n’est pas un prix libre mais seulement un artifice marketing. 🤷‍


Cyril Lacôte


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Angular 5.1.0 is here!

Angular logo

This is a fairly small release, with some bugfixes but not a lot of features.

Let’s see what 5.1 has in stock for us!

i18n

The registerLocaleData method now has an optional parameter to set the locale id. This allows to use a custom locale id or locales that Angular does not support. You can now do something like:

registerLocaleData(localeFr, 'fr-ZZ');

and the french locale data will be available for the (fake) locale id fr-ZZ.

Service worker

The @angular/service-worker package evolves a little, with the possibility to register the ServiceWorkerModule without crashing the application even if the Service Worker API is not supported by the browser. The register method has now also a new option to enable the service worker or not. Previously you would have registered your service worker like this:

providers: [
  environment.production ? ServiceWorkerModule.register('/ngsw-worker.js') : [],
  // ...
]

which would have made the Service Worker services like SwUpdate only available to dependency injection in production. That was forcing us to use a trick like Optional to not crash the application in development:

constructor(@Optional() private swUpdate: SwUpdate) {
  // test if swUpdate is not null
}

With 5.1, we can do better:

providers: [
  ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }),
  // ...
]

With this new enabled option, the services will always be available to dependency injection, making the Optional trick no longer necessary. The services like SwUpdate now also has an isEnabled field to know if they are enabled or not:

constructor(private swUpdate: SwUpdate) {
  if (swUpdate.isEnabled) {
    // ...
  }
}

Compiler

It’s worth noting that behind the scenes, some work has been done to enable AoT unit testing. Currently units test are run using the JiT compiler. But as you may know, the Angular team is working to make this JiT compiler obsolete. It’s been recommended for a long time to use the AoT mode in production, and, starting with Angular 5.0, it’s no longer necessary to use JiT even in development as AoT has become faster (even it’s still slower than JiT right now). The last place where JiT is required is for unit testing. That should no longer be the case soon, as some key pieces are falling into place in the framework.

Another interesting point for the compiler: the error messages should now be clearer (especially when you make a mistake in a decorator)!

Angular now also officially supports TypeScript 2.5.x.

That’s all for this small release!

All our materials (ebook, online training (Pro Pack) and training) are up-to-date with these changes if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Tons of Angular projects are using the Angular CLI. This tool is really great as it wraps all the Webpack complexity, and helps you build, test and serve your application. It can also generate components, services, pipes… with their associated tests.

A few maintainers are working full-time to evolve the CLI, fix bugs and introduce awesome new features. As a developer relying on the CLI, you’ll want to update the CLI version your project depends on as often as possible.

Sadly, there is no automated way to do it. You may think that bumping the package version in your package.json is enough, but… no…

There are also often configuration files to update, and even if the committers do their best to guide us through the updates, it can be hard to track exactly what you need to change between your current version and the new shiny one. And these new releases happen quite often as you can see!

Some time ago, the CLI had an init command that was trying to help you in the upgrade, but it was an “all or nothing” process: you just could overwrite the file or ignore it. The command has been removed in later versions, so you don’t have a lot of help right now.

That’s why we built a small script that generates a bare application with every CLI version. The result is angular-cli-diff, a repository that allows you to see exactly what changed between your version and another one!

For example, you are currently using 1.0.3 and want to test the release 1.5.2?

Here you go: https://github.com/cexbrayat/angular-cli-diff/compare/1.0.3…1.5.2

As you can see there are some differences that you might have missed (new dependencies, new polyfill, new unit test configuration, new types, new linter rules…).

You can, of course, compare any version you want. They are listed in the README of the repository and new versions are added a few hours/days after the official release.

This problem is not really original, and similar repositories exist for tools like React Native with rn-diff (from a good friend of mine Nicolas Cuillery) which was definitely an inspiration!

It has been quite useful to us these last weeks to update our code samples and online training exercises, we hope it will help you too.

Check out our ebook, online training (Pro Pack) and training if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Angular CLI 1.5.0 is out with some nice new features!

If you want to upgrade to 1.5.0 without pain (or to any other version, BTW), I have created a Github project to help: angular-cli-diff. Choose the version you’re currently using (1.2.1 for example), and the target version (1.5.0 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/1.2.1…1.5.0. You have no excuse for staying behind anymore!

Let’s see what new features we have!

Support for Angular 5 and its new compiler

This is probably the biggest feature of this release! As Angular 5 ships with an improved compiler (check out our article about that if you missed it), the CLI can now use it (and will automatically if your project uses ng 5). It gives us faster builds, and even an AoT mode that starts to be usable in development (using the incremental rebuild).

For example, on a medium-sized application, where ng serve rebuilds in ~400ms, you can see the difference between the versions if you use AoT compilation:

  • ng serve --aot with ng 4.4 and CLI 1.4: ~4000-8000ms
  • ng serve --aot with ng 5.0 and CLI 1.5: ~1800-3600ms

As you may know, building with the AoT mode also compiles the templates, and thus detects errors at build time that you would only discover (hopefully) at runtime in JIT mode. Which is pretty useful, but used to be too slow to be usable in development. Now it starts to be more bearable, even if it’s still slower than JiT compilation, but the Angular team is working hard on this, and it starts to show (even if it is still too slow on big projects).

By default, the build-optimizer plugin (which does a little bit of extra work on your generated code, like removing unneeded decorators, adding hints for dead code removals, etc.) will now be applied to your build if you are using Angular 5 and building in AoT.

That means that your build command:

ng build --prod --build-optimizer

can be simplified to:

ng build --prod

once you have upgraded to the CLI 1.5 and Angular 5.

ES2015 as a target

The CLI now supports ES2015 as the target of the build (and not only ES5). If you are targeting only modern browsers, you can now choose to output ES2015 code as the result of your build. Just change the target of your tsconfig.json file and you’re set! (fun fact: it slimmed down the bundles generated when I tried it, but I can’t say it will always be the case…).

Auto loading of locale files for internationalization

Angular 5 introduced some breaking changes regarding internationalization: Angular stopped relying on the Intl API (that should be provided by the browser, but is not always, and polyfills can be buggy) and now requires you to load explicitly the locale data you need. For example the DatePipe needs to know the day names in french if you want to localize your app in this language. To do so, you need to have somewhere in your app:

import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';

registerLocaleData(localeFr);

The problem is that if you build your application in 5 different languages, you need to do this for each language, and you don’t want to include every locale in every build 🤔.

This is the cool feature introduced by the CLI 1.5: you don’t have to do this yourself! The CLI will automatically add these lines of code, with the correct locale data, when you build your app (based on the locale you specified when you build):

ng build --aot --locale=fr

When you are building or serving the app in JiT mode, the CLI will do the same trick:

ng serve --locale=fr

But for your app to work without AoT, you’ll have to set the LOCALE_ID manually (whereas the CLI does it for you automatically in AoT mode). As the AoT mode will become the default soon (scheduled for CLI 2.0), this is not really bothering.

Resource integrity

The CLI now adds integrity and crossorigin attributes to scripts and stylesheets, that modern browsers use to check if the resource fetched has not been corrupted (by a “man in the middle” type of attack). You don’t have to do anything, and your application is safer!

TypeScript version mismatch

Angular CLI warns you if you are using a version of TypeScript which is not the recommended one with your Angular version (as it can lead to unnecessary headaches). You can now deactivate the warning for your project (if you are sure about what you are doing of course 😅) with ng set warnings.typescriptMismatch=false (it was previously only global).

appRoot configurable

The appRoot is now configurable in a CLI app, the default being app as it is right now. The main use of this feature is for people who want to have several apps in the same src directory, each with their own name.

Schematics template

The new schematics tool used by the CLI under the hood to generate … schematics (blueprints) of projects, is very generic and allows to create your own schematics. But how do you do that? To help with this question, the CLI team released a collection called @schematics/schematics containing a schematic for a schematic (so like a meta-schematic. That’s a lot of schematic, I know). This sample demonstrates a few common features and is a good starting point if you want to try to build your own project templates.

yarn global add @angular-devkit/schematics @schematics/schematics
schematics @schematics/schematics:schematic --name my-custom-schematics

Nx schematics

A new unofficial schematic has been released by nwrl.io. As I was saying in my last blog post, it didn’t took long for the community to start producing these! It’s called Nx and focuses on creating CLI projects containing several applications and components libraries in the same repository. If your company needs to have several applications using the same set of common components and services, you should check it out for inspiration: nrwl/nx. The schematic also uses ngrx and can generate examples with unit tests included.

Check out our ebook, online training (Pro Pack) and training if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Angular 5.0.0 is here!

Angular logo

We made a little video to give you an overview of the new features. If you want to dive deeper into what has changed, keep on reading after watching it ;).

Angular compiler is now much faster and more powerful!

As you may know, Angular has two ways to work:

  • one where the templates are compiled at runtime (Just in time, JiT)
  • one where the templates are compiled at build time (Ahead of time, AoT)

The second way is far better, as the work is done on the developer’s machine at build time, and not for each user at runtime, making the application start faster. It also allows compiling all the templates of the application and catch errors early. But this compiler was a bit slow before Angular 5.0, and as a result, most of us were using the JiT mode in development and the AoT mode only for production (that’s what Angular CLI does by default).

The main reason for this slowness was that every template change was triggering a full compilation of the application! That’s no longer the case: leveraging the new “pipeline transformer” ability of the TypeScript compiler (introduced in TS 2.3, as I was talking about in my previous article), the Angular compiler, ngc, is now able to only compile what is necessary with the introduction of a new watch mode:

ngc --watch

A new flag --diagnostics has also been introduced to print how much time the compiler spent on a compilation in watch mode.

We can expect the Angular CLI to use this new watch mode and it will probably become the default mode very soon!

The compiler can also check more thoroughly your templates, with the new option fullTemplateTypeCheck. It can for example catch that a pipe is not used with the proper type:

<!-- lowercase expects a string -->
<div>{{ 12.3 | lowercase }}</div>

This example will compile with ngc but not if fullTemplateTypeCheck is activated:

Argument of type '12.3' is not assignable to parameter of type 'string'

It can also analyze the local variables referencing a directive in your templates. For example, let’s say you created a variable to reference a ngModel, and want to access the hasError() method, but made a typo:

<input [(ngModel)]="user.password" required #loginCtrl="ngModel">
<!-- typo in `hasError()` method -->
<div *ngIf="loginCtrl.hasEror('required')">Password required</div>

This will also compile with ngc, except if fullTemplateTypeCheck is activated:

Property 'hasEror' does not exist on type 'NgModel'. Did you mean 'hasError'?

That’s super cool! Right now the default value of fullTemplateTypeCheck is false, but we can expect to see it become true in a future release. (Side note: this feature is currently a bit flaky, and I ran into issues testing it. You might want to wait 5.0.x to try it!).

The compiler is now also smarter to understand factories, and there’s thus no need to use this weird trick anymore:

export function webSocketFactory() {
  return WebSocket;
}

@NgModule({
  providers: [
    { provide: WEBSOCKET, useFactory: webSocketFactory },
  ]
})
export class AppModule {

You can now directly write:

@NgModule({
  providers: [
    { provide: WEBSOCKET, useFactory: () => WebSocket },
  ]
})
export class AppModule {

Forms

Forms have a tiny but really useful addition to their API: the ability to decide when the validity and value of a field or form is updated. This is something we already had in AngularJS 1.x, but not yet in Angular.

To do so, the FormControl allows to use an options object as the second parameter, to define the synchronous and asynchronous validators, and also the updateOn option. Its value can be:

  • change, it’s the default: the value and validity are updated on every change;
  • blur, the value and validity are then updated only when the field lose the focus;
  • submit, the value and validity are then updated only when the parent form is submitted.

So you can now do something like this:

this.passwordCtrl = new FormControl('', {
  validators: Validators.required,
  updateOn: 'blur'
});

It’s also possible to define this option on the FormGroup level, to have all the fields of the group behaving the same:

this.userForm = new FormGroup({
  username: '',
  password: ''
}, { updateOn: 'blur' });

This is of course also possible in template-driven form, with the ngModelOptions input of the NgModel directive:

<input [(ngModel)]="user.login" [ngModelOptions]="{ updateOn: 'blur' }">

or the new ngFormOptions input of the NgForm directive to apply on all fields:

<form [ngFormOptions]="{ updateOn: 'submit' }">

You can learn more about the plans for forms in this design docs.

Http

The old @angular/http module is now officially deprecated and replaced by @angular/common/http, the new HttpClient introduced in 4.3. You can probably expect that @angular/http will be removed in Angular 6.0.

HttpClient has been slightly improved with Angular 5.0, as we are now able to directly use object literals as headers or parameters, whereas we had to use the classes HttpHeaders and HttpParams.

So this kind of code:

const headers = new HttpHeaders().set('Authorization', 'secret');
const params = new HttpParams().set('page', '1');
return this.http.get('/api/users', { headers, params });

can now be simplified into:

const headers = { 'Authorization': 'secret' };
const params = { 'page': '1' };
return this.http.get('/api/users', { headers, params });

Animations

Two new transition aliases are introduced: :increment and :decrement. Let’s say you want to animate a carousel with 5 elements, with a nice animation based on the index of the element displayed. You had to declare a transition like: transition('0 => 1, 1 => 2, 2 => 3, 3 => 4', ...). With Angular 5, you can now use transition(':increment')!

Router

The router gains two new events to track the activation of individual routes:

  • ChildActivationStart
  • ChildActivationEnd

These events are introduced to give a more fine-grained control than using the global NavigationStart/NavigationEnd events, if you for example want to display a spinner while some children components are loading.

More newsworthy, it’s now possible to reload a page when the router receives a request to navigate to the same URL. Until now it was ignoring such a request, making it impossible to build a “refresh” button.

It’s now configurable at the router level, using onSameUrlNavigation, which can receive either reload or ignore (currently the default).

providers: [
  // ...
  RouterModule.forRoot(routes, {
    onSameUrlNavigation: 'reload'
  })
]

i18n

The messages extracted from your application now include the interpolations used in the template.

Before:

<source>
  Welcome to Ponyracer
  <x id="INTERPOLATION"/>
  <x id="INTERPOLATION_1"/>!
</source>

Now:

<source>
  Welcome to Ponyracer
  <x id="INTERPOLATION" equiv-text="{{ user.firstName }}"/>
  <x id="INTERPOLATION_1" equiv-text="{{ user.lastName }}"/>!
</source>

This can be really helpful for the translators, as they now have a hint about the interpolations.

A notable change in i18n is that the i18n comments are now deprecated. In Angular 4, you could use:

<!--i18n: @@home.justText -->
  I don't output an element, just text
<!--/i18n-->

Starting with Angular 5, you are encouraged to use an already possible alternative with ng-container:

<ng-container i18n="@@home.justText">
  I don't output an element, just text
</ng-container>

Pipes, i18n and breaking changes

More importantly, the pipes that were helping with the internationalization (number, percent, currency, date) have been completely overhauled. They don’t rely on the Intl API anymore. This internationalization API was supposed to be provided by the browser, but that was not always the case, so we had to use a polyfill, and inconsistencies between browsers (and polyfills) led to numerous bugs.

If you don’t do anything when you upgrade, you’ll use the new pipes by default. The good news is that there should be less bugs and you can remove the Intl polyfill you likely included. The bad news is that they don’t all have the same parameters and behavior as previously, and that can break your application.

Using a different locale than the default one (en-US) now requires to load additional locale data:

import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';

registerLocaleData(localeFr);

All the i18n pipes now take a locale as their last parameter, allowing to dynamically override it:

@Component({
  selector: 'ns-locale',
  template: `
    <p>The locale is {{ locale }}</p>
    <!-- will display 'en-US' -->

    <p>{{ 1234.56 | number:'1.0-3':'fr-FR' }}</p>
    <!-- will display '1 234,56' -->        
  `
})
class DefaultLocaleComponentOverridden {
  constructor(@Inject(LOCALE_ID) public locale: string) { }
}

The currency pipe now takes a string as it second parameter, allowing to chose between 'symbol' (default), 'symbol-narrow' or 'code'. For example, with canadian dollars:

<p>{{ 10.6 | currency:'CAD' }}</p>
<!-- will display 'CA$10.60' -->

<p>{{ 10.6 | currency:'CAD':'symbol-narrow' }}</p>
<!-- will display '$10.60' -->

<p>{{ 10.6 | currency:'CAD':'code':'.3' }}</p>
<!-- will display 'CAD10.600' -->

The date pipe has several breaking changes. I won’t list them, it’s easier to check out the commit message.

All things are not lost if you want to keep the “old” pipes for now, as they have been kept in a new module DeprecatedI18NPipesModule, that you can import if you want to still use them:

@NgModule({
  imports: [CommonModule, DeprecatedI18NPipesModule],
  // ...
})
export class AppModule {

Service Workers

Angular has a package called @angular/service-worker, which has been in beta for quite some time and in a different repository. It received a little bit of love with Angular 5, as it graduated to the main repository, so we can expect it to be brought to the same quality standards as the other packages, and to be out of beta soon!

If you don’t know about service workers, you can picture them as small proxies in your browser. If you activate them in an app, it allows to cache static assets, and to not fetch them on every reload, improving performances. You can even go offline, and your app can still respond!

@angular/service-worker is a small package, but filled with cool features. Did you know that if you add it to your Angular CLI application, and turn a flag on ("serviceWorker": true in .angular-cli.json), the CLI will automatically generate all the necessary stuff to cache your static assets by default? And it will only download what has changed when you deploy a new version, allowing blazingly fast application start!

But it can even go further, allowing to cache external resources (like fonts, icons from a CDN…), route redirection and even dynamic content caching (like calls to your API), with different strategies possible (always fetch for fresh data, or always serve from cache for speed…). The package also offers a module called ServiceWorkerModule that you can use in your application to react to push events and notifications!

Other breaking changes

A few things that were deprecated in Angular 4.0 have now been definitely removed.

There is a last breaking change that should not really impact you. I feel morally obligated to show it to you, but it’s totally not interesting.

If you are declaring extra providers in the platformXXXX() or bootstrapModule() methods, you now need to use the (new) StaticProvider, which is really similar to a Provider, but forces you to explicitly declare the dependencies. It does not impact the providers you declare in your modules and components, don’t worry.

So if you have something like this:

platformBrowserDynamic([
  MyCustomProviderA,
  MyCustomProviderB // depends on MyCustomProviderA
]).bootstrapModule(AppModule);

It must now be in 5.0:

platformBrowserDynamic([
  { provide: MyCustomProviderA, deps: [] },
  { provide: MyCustomProviderB, deps: [MyCustomProviderA] }
]).bootstrapModule(AppModule);

I honestly couldn’t come up with a decent real use-case, as it is quite rare to give extra providers to these methods, and this only impact the two cases in the example and not useValue, useFactory, useExisting… So I don’t think many apps will be impacted :)

On the other hand, this change allows Angular to not depend on the Reflect API, and that gives us (slightly) smaller bundles \o/.

Another change is the removal of the ES5 API to write Angular applications without decorators. This API was also depending on Reflect and is now gone.

All our materials (ebook, online training (Pro Pack) and training) are up-to-date with these changes if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Nous vous avions promis, dans notre article faisant le bilan des 5 ans de Ninja Squad de vous fournir le bilan comptable de ce dernier exercice quand il serait disponible. Et comme nous sommes transparents, super cools, et fiables (et humbles), nous tenons promesse.

Donc voici, pour les passionnés de chiffres, les curieux, ou les futurs entrepreneurs angoissés, notre bilan officiel 2016-2017 :

(le gendre idéal apparaissant sur la page de garde n’est ni un ninja, ni notre comptable… 🤷‍)


Cyril Lacôte


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Angular 4.4.1 is here (4.4.0 glitched out and was never released)!

Angular logo

This is a fairly small release, with some bugfixes but not a lot of features. Angular 5.0, scheduled for next month, will bring more awesomeness but we’ll have to wait a little.

Let’s see what 4.4 has in stock for us!

Performance with preserveWhitespaces

A few things changed internally to boost performance, and a new compiler flag appeared that allows to remove extra whitespaces. This can look minor, but it can improve the generated code size, and also speed the components creation. But it can also break your layout if you rely on several consecutive spaces in your templates :) That’s why the default for the preserveWhitespaces flag is true for now, and might become false one day. But right now, you have to activate it manually.

You can configure it globally:

platformBrowserDynamic().bootstrapModule(AppModule, {
  preserveWhitespaces: false
});

or per component:

@Component({
  selector: 'pr-home',
  templateUrl: './home.component.html',
  preserveWhitespaces: false
})
export class HomeComponent implements OnInit, OnDestroy {

If you really want a whitespace to be kept, you can use a special entity called &ngsp;. It looks like &nbsp; with a typo, but it is not: it is a special character that the Angular compiler will transform in a whitespace. Note that it will only keep one whitespace, even if add several consecutive ones, like &ngsp;&ngsp;. If you really want to preserve the whitespaces in a fragment of a template, you can use ngPreserveWhitespaces:

<div ngPreserveWhitespaces>hello     there</div>

Note that the gains were fairly small on our applications, but a gain is a gain…

Multiple exportAs names

It’s not really important, but it’s the second and last feature of this release: you can now specify several names in the exportAs attribute of a directive. This is mostly introduced for allowing to change the name of existing directives, while still keeping the old one for backward compatibility.

For example:

@Directive({
  selector: '[ns-ninja]',
  exportAs: 'ninja, superNinja'
})
export class NinjaDirective {

can be used as:

<div ns-ninja #foo="ninja">
<!-- or -->
<div ns-ninja #foo="superNinja">

Summary

That’s all for this release: the next important one will be 5.0!

The Angular CLI also had interesting changes lately. Check out our blog posts if you missed them:

All our materials (ebook, online training (Pro Pack) and training) are up-to-date with these changes if you want to learn more!


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular
Cover of ebook Become a ninja with Angular

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular

27/02-01/03 à Lyon
19-21/03 à Paris

Angular avancé

22-23/03 à Paris


Suivez-nous


Posts plus anciens