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   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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular CLI 1.4.0 is out with some nice new features!

If you want to upgrade to 1.4.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.4.0 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/1.2.1…1.4.0. You have no excuse for staying behind anymore!

Let’s see what new features we have!

Schematics

The Google team has created schematics, a Yeoman-like generator. Angular CLI will now use this new tool to generate the application skeleton and the components, services, pipes… All the blueprints are now bundled in schematics/@angular and have been removed from the CLI itself.

Really interesting as it opens the possibility to have other blueprints than the official ones! This is a feature that other frameworks also have (like Vue CLI or Ember CLI).

We can expect to see new “schematics” for Angular CLI really soon, for example some oriented for server-side rendering apps, or mobile apps, or progressive apps, or native apps, etc.

The CLI now has an option to specify the blueprint you want to use when you generate a project:

ng new --collection my-custom-schematics project-name

You can of course define your own schematics, but we did not give it a try yet.

Serve path

A new option for ng serve is available to specify a path where you want the application to be served in dev:

ng serve --serve-path hello

will serve the application at http://localhost:4200/hello. This is a simple way to configure it, even if you could do the same with the --base-href and --deploy-url flags.

Missing translation strategy

If you are using the i18n support of Angular, you can specify directly from the CLI the strategy you want to adopt when a translation is missing:

ng build --aot --locale fr --i18n-file src/i18n/messages.fr.xlf --missing-translation error

The --missing-translation error flag is available for the serve and build commands, and accepts the values error, warning or ignore.

Scripts sourcemaps and minifications

The scripts that were added via the scripts array in .angular-cli.json were not minified and had no sourcemaps. This is now resolved.

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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular a presque un an, et est bientôt en version 5.0 !

Le premier commit date de 3 ans, et nous avons commencé à l’utiliser dès le tout début. Nous avons enseigné les fondamentaux d’Angular à des centaines de développeurs en personne, notre ebook à des milliers de lecteurs, et notre formation en ligne (Pack Pro) a touché quelques centaines de développeurs supplémentaires tout autour du monde !

Tout au long de ce chemin, nous avons appris pas mal de choses sur Angular, son fonctionnement, son éco-système et comment construire de meilleures applications.

C’est pour cela que nous sommes très contents d’annoncer notre nouvelle formation sur 2 jours : Angular avancé: de Ninja à Héros !

Cette formation va au-delà des fondamentaux et se destine à des développeurs qui cherchent des sujets plus avancés et des bonnes pratiques.

Pour vous donner un aperçu, la formation couvre :

  • l’injection de dépendances : injecteur hiérarchique, pourquoi @Injectable, singleton vs plusieurs instances, comment partager des données dans votre application, les différents types de providers et leur utilité, @Optional, @Self, forwardRef ;
  • les observables : les opérateurs avancés et leur utilité, bonnes pratiques, comment les tester ;
  • les composants et directives avancés : méthodes du cycle de vie, ng-content, @HostBinging, @HostListener, ViewChild, ContentChild ;
  • les tests : tester les composants, comment tirer profit de l’injection de dépendances, tests asynchrones ;
  • le router : découper votre application en modules, lazy-loading, les pièges à éviter avec l’injection de dépendances, comment utiliser les guards et resolvers ;
  • le fonctionnement d’Angular : comment le framework fonctionne sous le capot, la détection de changement, les zones, la compilation JiT and AoT ;
  • les performances : les stratégies de détection de changement, tracking des éléments, le pipe async et ses pièges, comment échapper à la détection de changement d’Angular ;
  • l’internationalisation : qu’est-ce que l’i18n, comment construire une application multi-langues, bonnes pratiques ;
  • les formulaires : formulaires imbriqués, formulaires dynamiques, construire vos propres composants de formulaire avec ControlValueAccessor ;
  • et plein d’astuces sur la mise en production, comment faire de l’intégration continue, etc.

Cette formation s’appuie également sur notre Pack Pro que vous pouvez acheter avec notre ebook. Nous ferons quelques-uns des exercices les plus avancés ensemble pour que vous puissiez mettre en pratique ces nouveaux concepts !

Ho, et, comme toujours, la formation est 30% moins chère si vous êtes un développeur indépendant, un contributeur open-source, un organisateur de conférence ou si vous cherchez actuellement un emploi. Pour plus de détails, regardez notre site !


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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular is nearly one year old, and soon in version 5.0!

The first commit is now 3 years old, and we’ve been using it since the very beginning. We have taught the fundamentals of Angular to hundreds of developers in person, our ebook has thousands of readers, and our online training (Pro Pack) reached a few hundred more developers all over the world!

Along the way we have learnt quite a bit about Angular, its internals, its ecosystem and how to build better applications.

That’s why we are really happy to announce our new 2 days training: Advanced Angular: from Ninja to Hero!

This training goes beyond the fundamentals and is built for developers who are looking for more advanced topics and best practices.

To give you an overview, the training deep dives in:

  • dependency injection: hierarchical injector, why @Injectable, singleton vs several instances, how to share data in your application, the different types of providers and their use, @Optional, @Self, forwardRef;
  • observables: advanced operators and use-cases, best practices, how to test them;
  • advanced components and directives: lifecycle hooks, ng-content, @HostBinging, @HostListener, ViewChild, ContentChild;
  • testing: component tests, how to leverage dependency injection, asynchronous tests;
  • router: how to split your application in modules, lazy-loading, the traps to avoid with dependency injection, how to use guards and resolvers;
  • Angular internals: how does it work under the hood, change detection, zones, JiT and AoT compilation;
  • performance: change detection strategies, element tracking, the async pipe and its traps, how to escape Angular’s change detection;
  • internationalization: what’s i18n, how to build a multi-language application, best practices;
  • forms: nested forms, dynamic forms, build your own form component with ControlValueAccessor;
  • and a lot of tips on how to be ready for production, how to set up a continuous integration, etc.

This training also relies on our online training, the Pro Pack that you can buy with our ebook. We’ll go over some of the more advanced exercises of the “Pro Pack” so you can get your hands dirty with all these new concepts!

Oh, and, as always, the training is 30% cheaper if you are an independent developer, an open source committer, a conference organizer or if you are currently looking for a job. If you want to have more details, check out our website!


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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular CLI 1.3.0 is out with some nice new features!

It now officially supports ES2017 and TypeScript 2.4 and is ready for Angular 5 (which should be out shortly).

You can check out what files you need to update using angular-cli-diff, for example if you are currently using 1.2.1: angular-cli-diff/compare/1.2.1…1.3.0

Let’s see what new features we have!

Bundle sizes

The Angular team is putting a ton of work to generate the smallest bundles possible. Angular CLI uses Webpack 3 and now leverages its scope hoisting feature which resulted in some nice gains, but there is still room for improvements.

The Angular team is working on a better tree-shaking with a new project @angular/devkit, that the CLI now uses. It’s a bit experimental, so it’s behind a new flag called --build-optimizer. It does some manipulations on your compiled code, like folding the static properties inside the class, scrubbing the Angular specific decorators and metadata (that are unneeded when you have compiled in AoT mode), adding a /*@__PURE__*/ comment on classes, etc. All these actions aim for the same goal: helping Webpack and Uglify to do a better tree-shaking and a better dead code elimination.

And all that gives us smaller bundles \o/ I tested it on a medium-size application:

Size without --build-optimizer: 871K (211K gzip)

With --build-optimizer: 778K (192K gzip)

That’s a small but nice win. But for others it resulted in massive gains! So it can be interested for you, especially if you are using Angular Material (check the comments of this issue).

You can read more about how this feature works here. Be warned that it is experimental though, and can break your app, so be careful…

Named chunks

While we are talking about building the application, a new flag, called --named-chunks, will generate nicely named chunks. Until now, if you had lazy-loaded modules in your application, the bundles looked like that:

main.bundle.js
0.chunk.js
1.chunk.js

With this new flag, the CLI names it with the names of the Angular modules:

main.bundle.js
users.module.chunk.js
admin.module.chunk.js

This is the default in development mode so you don’t even have to add the flag to your command, but it’s not the default in production mode.

Server side rendering

The SSR is getting better and better, and the CLI now has a piece of documentation to guide you, check it out: universal rendering. It’s honestly still very early days, and won’t work with most apps (no lazy-loading support for example).

Proxy configuration

It’s possible to define a proxy configuration since some time now, and it’s quite useful as you can for example forward all the requests to an API to a local server running on your machine (really useful when you are developing the backend too).

{
  "/api": {
    "target": "http://localhost:9000",
    "secure": false
  }
}

But you had to manually give it to the serve command every time, like ng serve --proxy-config proxy.conf.json, which was a bit painful.

You can now specify a proxyConfig in your .angular-cli.json file, and ng serve will pick it up automatically.

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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular 4.3.0 is here!

Angular logo

This is a fairly big release, with a new HttpClientModule, a complete rewrite of the HttpModule 💅! This should be the last minor release before Angular 5, when we can expect some other exciting stuff!

HttpClientModule

The biggest feature of this release is without a doubt the new HttpClientModule. This module is a complete rewrite of the current HttpModule that had some defaults, like the obligation to extract the JSON from the response for every request, no mechanism to handle requests and responses in a generic fashion, and a quite awful testing API.

The new HttpClientModule is a really cool alternative: it solves all these issues, and we migrated our applications fairly easily. And it was mostly code deletions 💖.

We made a little video to show you the difference, and a complete article to help you to migrate your applications.

It showcases the brand new HttpClient service, how to write unit tests, and how to use the new interceptors!

Check out the article we wrote that explains in deep how to use this new module!

Router

A few events have been added to the router, if you need to know when a resolver or a guard is run:

  • ResolveStart, ResolveEnd
  • GuardsCheckStart, GuardsCheckEnd

Forms

The two new validators min and max released with 4.2 have been temporarily rolled back as they were breaking changes :(. They’ll return in a major release, probably 5.0.0.

Style

You may know that the /deep/ “shadow-piercing” combinator can be used to force a style down to child components. This selector had an alias >>> and now has another one called ::ng-deep.

Be warned though: the /deep/ combinator has been deprecated from the Shadow DOM spec and is being removed from all major browsers. So the support will probably also be dropped by Angular in the future. Until then, it is recommended to use ::ng-deep, and to only use it with emulated view encapsulation.

Compiler

This is not really a new feature, but I think it is interesting to understand how things work under the hood.

TypeScript 2.3 recently introduced the concept of transformers in the compiler API. That means some teams can write custom transformations/plugins that are applied to the code compiled by tsc. This is not really something that we common mortals will write, but Angular has its own compiler called ngc that wraps tsc.

Until now, the process for ngc was to compile your templates to generate TypeScript files, and then call tsc to compile your TypeScript code and the TypeScript files generated to JavaScript. If that sounds strange, you can check out our ebook where we explain all this.

With the introduction of transformers, tsc works slightly differently: it starts by parsing the files, does the type-checking, applies any plugin you want, and then generates JavaScript.

Based on this, ngc is now becoming a plugin called in the TypeScript compilation pipeline, rather than a wrapper of the TypeScript compiler.

As Angular developers, we can expect to have very precise type-checking in our templates, referring to the exact line of the problem in HTML source file!

Summary

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

In the meantime, 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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular 4.3 introduced a new module, HttpClientModule, which is a complete rewrite of the existing HttpModule.

This article will show you how to easily migrate to this new module, and why you should (spoiler: because it’s way better 🦄).

Here is a short video we made to show you what’s new with this HttpClientModule.

The rest of the article focuses on what you have to do to migrate your apps. It assumes an app generated with Angular CLI, but if that’s not your case, you’ll still be able to follow, minus some file names that might differ for you.

Migrate your application

The first step is to remove the @angular/http package from your package.json file. Indeed the new HttpClientModule is in the @angular/common/http package, and @angular/common should already be in your package.json file.

Save your file, and run NPM or Yarn to update the node_modules. You should start to see compilation errors in your application, as all the imports from @angular/http are now breaking. That’s good, because it tells you all the files you’ll have to migrate.

The first obvious one is your app.module.ts file, which contains your main NgModule. Replace HttpModule with HttpClientModule in your module’s imports field, and update the TypeScript import from:

import { HttpModule } from '@angular/http';

to:

import { HttpClientModule } from '@angular/common/http';

The second step is to replace every instance of the service Http with the new service HttpClient. This is will usually be the case in your services. This is where using the new HttpClient will shine: you don’t have to manually extract the JSON anymore \o/!

So a service which was looking like that:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { UserModel } from './user.model';

@Injectable()
export class UserService {

  constructor(private http: Http) {}

  list(): Observable<UserModel> {
    return this.http.get('/api/users')
      .map(response => response.json())
  }
}

can be rewritten as:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { UserModel } from './user.model';

@Injectable()
export class UserService {

  constructor(private http: HttpClient) {}

  list(): Observable<UserModel> {
    return this.http.get('/api/users');
  }
}

Feels good to remove this code, doesn’t it?

Migrate your tests

Now let’s move on to the unit tests.

Testing services with HTTP requests was really verbose with HttpModule… You probably had something like:

describe('UserService', () => {

  beforeEach(() => TestBed.configureTestingModule({
    imports: [HttpModule],
    providers: [
      MockBackend,
      BaseRequestOptions,
      {
        provide: Http,
        useFactory: (backend, defaultOptions) => new Http(backend, defaultOptions),
        deps: [MockBackend, BaseRequestOptions]
      },
      UserService
    ]
  }));

  it('should list the users', async(() => {
    const userService = TestBed.get(UserService);
    const mockBackend = TestBed.get(MockBackend);
    // fake response
    const expectedUsers = [{ name: 'Cédric' }];
    const response = new Response(new ResponseOptions({ body: expectedUsers }));
    // return the response if we have a connection to the MockBackend
    mockBackend.connections.subscribe((connection: MockConnection) => {
      expect(connection.request.url).toBe('/api/users');
      expect(connection.request.method).toBe(RequestMethod.Get);
      connection.mockRespond(response);
    });

    userService.list().subscribe((users: Array<UserModel>) => {
      expect(users).toEqual(expectedUsers);
    });
  }));
});

You can now use the new testing API, which is much, much nicer:

describe('UserService', () => {

  beforeEach(() => TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    providers: [UserService]
  }));

  it('should list the users', () => {
    const userService = TestBed.get(UserService);
    const http = TestBed.get(HttpTestingController);
    // fake response
    const expectedUsers = [{ name: 'Cédric' }];

    let actualUsers = [];
    userService.list().subscribe((users: Array<UserModel>) => {
      actualUsers = users;
    });

    http.expectOne('/api/users').flush(expectedUsers);

    expect(actualUsers).toEqual(expectedUsers);
  });
});

That should remove a lot of errors you have or all of them.

Maybe you were also adding headers or params to your requests. The new HttpClient allows it too:

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

const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
this.http.get('/api/users', { headers });

In the example above, I set the JWT token needed in the Authorization header. This is something you probably repeat a lot of times in your services, as every request needs it.

The new module introduces a very interesting feature: interceptors. These interceptors are called for every request and response, and allow to easily handle tasks like adding a header to every request, or handling errors in a generic way for example.

First create your interceptor:

@Injectable()
export class GithubAPIInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }

}

Then add your custom logic, for example to add an OAUTH token to every Github API request, but not to the other requests:

@Injectable()
export class GithubAPIInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    // if it is a Github API request
    if (req.url.includes('api.github.com')) {
      // we need to add an OAUTH token as a header to access the Github API
      const clone = req.clone({ setHeaders: { 'Authorization': `token ${OAUTH_TOKEN}` } });
      return next.handle(clone);
    }
    // if it's not a Github API request, we just handle it to the next handler
    return next.handle(req);
  }

}

If you want to learn more about this API and Angular in general, you can check out our ebook, online training (Pro Pack) and training!


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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Né un 4 juillet

La société Ninja Squad a été immatriculée le 4 juillet 2012. Nous célébrons donc notre mi-décennie : 5 glorieuses années d’existence. 🎩🙆🕺

Extrait KBis Ninja Squad

Pour ceux qui ne nous connaîtraient pas, rappelons les principes qui régissent Ninja Squad. On est 4 fondateurs dont 3 salariés développeurs à plein temps. Tous égaux, tous actionnaires, sans lien de subordination (pas de managers, pas de commerciaux). Les salaires sont aussi égaux, quelque soit l’activité ou l’expérience de chaque ninja. On ne compte pas les vacances, et on essaie d’encourager les projets de chacun, qu’ils soient professionnels, dans l’open-source, ou plus personnels (voyage, famille, etc.).

En 5 ans, nous n’avons pas dérogé à un autre principe fondateur : on ne facture que 4 jours par semaine, et nous réservons les vendredis au reste : side projects, administratif, ou… procrastination.

Bref, on s’est juste donné les moyens de faire notre métier/passion dans des conditions correctes, en bonne entente avec nos clients, et en se faisant plaisir.

Et les résultats sont au beau fixe. Nous avons le luxe de choisir nos missions, et d’en refuser bien plus qu’on en accepte (on les refile alors aux copains d’autres NoSSII, ou indépendants). Si nous n’avons pas encore notre dernier bilan annuel (qui vient de se clôturer au 30 juin pour nous), il s’annonce encore meilleur que le précédent, comme chaque année. Nous le publierons ici quand il sera disponible.

En attendant, notre CFO amateur Cédric nous indique les chiffres suivants : 365k€ de chiffre d’affaires, dont :

  • 130k€ de prestations de développement ;
  • 190k€ de formation et conseils, essentiellement sur Angular ;
  • et 60k€ de ventes d’ebooks.

Nous nous distribuerons alors cette année encore une confortable prime annuelle, en plus de nos 2500€ de salaire net. Car comme chaque année, nous nous partageons les bénéfices en fin d’exercice (un peu moins de 20k€ nets chacun à l’issue du précédent). Du moins, tant que nous ne convaincrons pas JB de nous acheter des Tesla de fonction.

Et que faisons-nous au quotidien, ces derniers temps ?

  • Cédric Exbrayat, quand il ne donne pas une formation Angular ou assure un audit à l’autre bout de l’Europe (et il est déjà booké jusqu’à la fin de l’année), ne fait plus de prestations longues de développement, car il se consacre à la maintenance de son ebook Angular et de son ensemble d’exercices, ce qui est très consommateur de temps ;
  • Jean-Baptiste Nizet, quand il n’assure pas une formation Angular en remplacement de Cédric déjà pris ailleurs, fait du développement chez un client lyonnais historique où nous nous sentons bien ;
  • Agnès Crépet, quand elle n’est pas à son travail dans une grande école d’ingénieur stéphanoise, réalise quelques missions de conseil pour Ninja Squad ;
  • et Cyril Lacote (moi), quand ses enfants lui laissent un peu de temps, fait aussi du développement chez ce même client historique lyonnais.

Quelques idées reçues et réflexions

Les éxonérations fiscales

On entend souvent dire : “les trois premières années sont les plus dures”.
Ou son contraire : “les premières années sont faciles, avec les exonérations fiscales, c’est après que ça fait mal”.

Ninja Squad a, dès sa première année, payé des impôts, taxes, et prélèvements sociaux, sans exonération d’aucune sorte. Et on en est plutôt fiers. Ce furent ainsi 92k€ sur le bilan précédent (probablement plus cette année), soit 28% de notre chiffre d’affaires de 323k€. Nous voilà donc plus recommandables et moins evil que des grosses sociétés comme Google, Apple ou Amazon.

On peut donc créer une société pérenne sans aucun financement extérieur, ni emprunt, ni aide privée ou publique, ni apport (au-delà du capital social dont le montant peut être négligeable ; pour nous, il est de 10101€).

Il est l’or, mon trésor

Il faut se constituer une bonne trésorerie, un bon matelas d’avance, parce que tout le monde vous payera en retard.

C’est comme un sport national, mais sans le frisson de la compétition. C’est devenu normal, tout le monde paie en retard, personne ne s’en étonne.
Et ce sont souvent les mêmes entreprises qui respecteront scrupuleusement les contraintes pour toucher illégitimement leur Crédit Impôt Recherche chaque année qui feront tout/rien pour ne pas vous payer à temps.

Les clients en retard de paiement

Mais ces entreprises ne sont même pas les pires. Les pires sont les OPCAs, ces organismes de formation privés qui reçoivent chaque année nos taxes professionnelles, comme le FAFIEC, l’AgefosPME, ou l’AFDAS, et qui fonctionnent encore comme au siècle dernier.
Ils ne se contentent pas de vous payer systématiquement avec plusieurs mois de retard, après vous avoir demandé une tonne de documents : ils vous obligent en plus à passer par du courrier papier, et vous demandent parfois de refaire le travail plusieurs fois parce que leur scanner est en panne (true story, voir tweets ci-dessous) 😅.

Votre produit est votre sous-produit

Avec Ninja Squad, on rêvait (et on rêve encore) de sortir un produit et d’en vivre.

On a sorti un outil open-source qui a son petit succès chez les développeurs Java : DbSetup. Mais comme c’est de l’open-source, il n’est pas question d’en vivre.

On a sorti une plateforme de quiz, Quizzie, qui avait un business model en béton : gratuit pour un quiz public, payant pour un quiz privé. Ca a marché… moyennement : on n’a vendu que deux quiz, un premier au tout début, et un second très récemment 🎉. Soit une croissance organique d’à peu-près… 0% 😅.

En plus d’avoir trois ninjas dans l’organisation de MiXiT à Lyon, on participe toujours à des conférences, que ce soit en tant qu’orateurs :

ou en tant que simples spectateurs, comme SudWeb récemment, où on a pu échanger sur les modèles d’entreprise alternatifs comme le nôtre.

Dernièrement, on aide un centre de santé communautaire stéphanois, en leur réalisant bénévolement une application de gestion, qui préserve l’anonymat des migrants.

De beaux projets, mais rien qui permette d’en vivre.
Zach Holman disait The Product is the Byproduct : votre produit ne sera pas ce que vous imaginiez au départ, mais probablement le sous-produit que votre activité aura généré.

Il faut croire que pour nous, ce fut l’expertise Angular de Cédric. Son premier ebook sur AngularJS 1.x eut déjà un succès respectable : plus de 14k€ de chiffre d’affaires, et encore 1500€ de ventes l’année dernière, sur la France essentiellement, ce qui ferait déjà rêver la majorité des auteurs de livres techniques qui sortent via un circuit d’édition classique.

Et on a bien eu raison de le payer partiellement pendant son tour du monde pour qu’il relise chaque commit de l’équipe Angular 2, alors que le framework était en gestation, et qu’il commence à rédiger son second ebook. Il s’est pour le moment vendu pour plus de 85k€ au total dans le monde entier (dans 105 pays !), dont 60k€ sur cette seule dernière année. Et le Pack Pro, notre plateforme de formation en ligne, est en pleine explosion alors que les entreprises se mettent sérieusement à Angular 2 4 5, donc on n’exclut pas de tutoyer, Inch’Allah, les records de Discover Meteor (même si on s’est interdit de notre côté de vendre des goodies à prix d’or dans un pack Super Premium).

Dernièrement, des auteurs nous contactent même pour bénéficier de cette plateforme qui permet de coder et valider à son rythme des exercices, pour mettre en pratique la théorie apprise dans leur livre. Qui sait, peut-être que d’autres ebooks/formations en ligne préparés avec amour seront bientôt disponibles…

Nos ebooks n’étaient au départ que la mise en forme de nos supports de formation. On a donc peut-être trouvé, finalement, le sous-produit qui constituera notre produit. 🤞

Bisous

Ce nouvel exercice commencera par un nouveau tour du Monde de Cédric (il veut aller en Antarctique depuis qu’il a invité Marie Manceau et ses manchots à MiXiT), alors on n’est pas à l’abri qu’il revienne avec un nouveau master plan décennal.

En attendant, bisous à tous, merci à ceux qu’on croise aux détours de conférence et qui nous disent tout le bien qu’ils pensent de nous 😘, et à dans 5 ans.

Cet article sera mis à jour prochainement avec notre dernier bilan définitif, pour ceux qui ont une appétence ou une curiosité pour les chiffres.

via GIPHY


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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular 4.2.0 is here!

Angular logo

Templates

As we explained in our blog post about Angular 4.1, it is now possible to use strictNullChecks in your applications.

The ! post-fix operator is now also available in templates:

<h2>{{ possiblyNullRace!.name }}</h2>

The code generated from the AoT compiler will then include the non-null assertion operator too, allowing to do strict null checking in your templates also!

Forms

Two new validators joins the existing required, minLength, maxLength, email and pattern: min and max help you validate that the input is at least or at most the value specified.

<input type="number" [(ngModel)]="user.age" min="0" max="130">

Update (2017-06-17): The min and max validators have been temporarily removed from Angular in version 4.2.3, as they are a breaking change. They’ll return in a major version, maybe 5.0.0.

Animations

Animations received a lot of love in this release!

A new query function has been introduced in the animation DSL, allowing to query elements in the template. It uses querySelectorAll behind the scene, so you can use an element or a class as parameter for example. It also supports pseudo-selectors, and that opens a few interesting possibilities!

For example, we can now easily animate elements in a NgFor:

<div [@races]="races?.length">
  <button class="btn btn-primary mb-2" (click)="toggle()">Toggle</button>
  <div *ngFor="let race of races | slice:0:4">
    <h2>{{race.name}}</h2>
    <p>{{race.startInstant}}</p>
  </div>
</div>

with the following animation:

trigger('races', [
  transition('* => *', [
    query(':leave', [
      animate(1000, style({ opacity: 0 }))
    ], { optional: true }),
    query(':enter', [
      style({ opacity: 0 }),
      animate(1000, style({ opacity: 1 }))
    ], { optional: true })
  ])
])

Now, every time an element will leave (removed from the races array), it will slowly fade out. And when an element enters, it will slowly fade in.

Query animation

Another function introduced is stagger. it allows to build a staggering animation, where the elements will animate one after the other.

trigger('races', [
  transition('* => *', [
    query(':leave', [
      stagger(500, [
        animate(1000, style({ opacity: 0 }))
      ])
    ], { optional: true }),
    query(':enter', [
      style({ opacity: 0 }),
      animate(1000, style({ opacity: 1 }))
    ], { optional: true })
  ])
])

Stagger animation

animation has also been added to build reusable animations. The syntax allows to have dynamic parameters with default values. When you then need to use a reusable animation, you can call useAnimation, and override the default parameters if you want to.

In our small example, we can for example define a changeOpacity animation:

const changeOpacity = animation(
  [animate(1000, style({ opacity: '{{opacity}}' }))],
  { params: { opacity: 0 } }
);

This animation will slowly transition to the defined opacity (by default 0). Then we can use this animation:

trigger('races', [
  transition('* => *', [
    query(':leave', [
      stagger(500, [
        useAnimation(changeOpacity)
      ])
    ], { optional: true }),
    query(':enter', [
      style({ opacity: 0 }),
      useAnimation(changeOpacity, { params: { opacity: 1 } })
    ], { optional: true })
  ])
])

You can give various options to the useAnimation, like the delay you want to apply or the duration.

Note that when an element is animating, Angular will add a ng-animating class on the element. You can customize your CSS to use it, or you can use the pseudo-selector :animating in a query to style these elements.

It’s now also possible to trigger “child” animations, with the animateChild function. It can be handy to animate the router transitions for example.

Last but not least, we can now inject AnimationBuilder in our components, to programmatically build animations, and trigger them on demand from the code.

Tests

TestBed.overrideProvider()

The team is also working on the internals to bring interesting features, like the possibility to test in AoT mode. This materializes in this release with a new method on TestBed called overrideProvider, that allows to override a provider, no matter where it was defined (whereas you currently have to know the module/component that declared the provider you want to override).

This is a small step to have the same features between tests in JiT mode and in AoT mode. And this is really interesting for developers, as currently you can only test in JiT mode, which can lead to discrepancies. Indeed you can have an app that runs perfectly, and no error in your unit tests, and then try to build the app with the AoT compiler, and see a bunch of errors. In a near future, we will be able to test in AoT mode too, so you’ll be sure that your app runs fine in both modes.

If you want to learn more on this topic, take a look at the official design doc.

The AoT compiler will also become incremental soon, allowing to use it during development. Even if it is possible to use it right now when you’re coding, it’s too slow for most applications, as every change triggers a full rebuild of the application.

flush()

Another utility function called flush has been added. You may know that Angular comes with a built-in support for asynchronous tests.

For example, let’s say you have a component which displays a welcome message after a few seconds:

@Component({
  selector: 'pr-welcome',
  template: '<p>{{ greetings }}</p>'
})
export class WelcomeComponent implements OnInit {

  greetings: string;

  ngOnInit() {
    setTimeout(() => this.greetings = 'Hello there!', 3000);
  }

}

After 3 seconds, the greetings field will be initialized and the template will be updated.

Now how do you test this?

The first time you encounter something like this, you may be tempted to write a naive test, like waiting for 3 seconds before testing the content of the template:

it('should have a greeting message', () => {
  const fixture = TestBed.createComponent(WelcomeComponent);
  const element = fixture.nativeElement;
  fixture.detectChanges();

  setTimeout(() => {
    fixture.detectChanges();
    const message = element.querySelector('p').textContent;
    expect(message).toBe('Hello there!');
  }, 3000);
});

This will succeed… for the wrong reasons! It will indeed always succeed, as Jasmine will simply exit the test without running the assertions inside the setTimeout.

Angular offers the async function to wrap your test and force Jasmine to wait for the asynchronous functions in your test to finish:

it('should have a greeting message', async(() => {
  const fixture = TestBed.createComponent(WelcomeComponent);
  const element = fixture.nativeElement;
  fixture.detectChanges();

  setTimeout(() => {
    fixture.detectChanges();
    const message = element.querySelector('p').textContent;
    expect(message).toBe('Hello there!');
  }, 3000);
}));

This time the test succeeds for the right reasons. But we now have a test that needs 3 seconds to execute…

Angular allows you to do much better by using fakeAsync and tick. fakeAsync is used to wrap your test into a zone where you master the time! And tick can be used to fast-forward the time for as many milliseconds as you want. We can write the same test with these two like this:

it('should have a greeting message', fakeAsync(() => {
  const fixture = TestBed.createComponent(WelcomeComponent);
  const element = fixture.nativeElement;
  fixture.detectChanges();

  tick(3000);
  fixture.detectChanges();
  const message = element.querySelector('p').textContent;
  expect(message).toBe('Hello there!');
}));

The test is now instantaneous and can be read as if everything is synchronous!

You still need to know how long to wait in your test, and that’s where the new flush function can help. You can use flush instead of tick and the test will automatically wait until all macrotask events (like timeout) have been cleared from the event queue:

it('should have a greeting message', fakeAsync(() => {
  const fixture = TestBed.createComponent(WelcomeComponent);
  const element = fixture.nativeElement;
  fixture.detectChanges();

  flush();
  fixture.detectChanges();
  const message = element.querySelector('p').textContent;
  expect(message).toBe('Hello there!');
}));

fixture.whenRenderingDone()

A method called whenRenderingDone has also been added to the ComponentFixture class. It returns a promise and is slightly similar than whenStable but focuses on waiting the animations to be done. As you can imagine, it will be really useful if you need to test components with animations.

Summary

That’s all for this release! The focus was mainly on animations and tests, and the team is also working on reducing the bundle size of our applications, with the help of the Google Closure Compiler. I think we’ll learn more about that very soon!

In the meantime, 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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Angular 4.1.0 is here!

Angular logo

This will be a short blog post, because there are not a lot of new features…

The most part of the work has been done on the official docs, which are now an Angular CLI app, and this migration takes some time. We can then expect to have nice new content when this will be done.

So, what are the new features? Let’s dive in!

i18n

The internationalization module has a few bugfixes, and a notable new feature: the extracted messages file now has the source file for each message. It will be far easier for developers to know where the messages come from!

<trans-unit id="home.title" datatype="html">
  <source>Welcome to Ponyracer</source>
  <target/>
  <context-group purpose="location">
    <context context-type="sourcefile">src/app.component.ts</context>
    <context context-type="linenumber">10</context>
  </context-group>
</trans-unit>

Core

The main new feature of this release is the support of the brand new TypeScript 2.3 version, and the support of strictNullChecks.

This option allows to check if you won’t run into nullability problems in your app. Angular itself now has correct types. For example, when you try to retrieve a FormControl from a FormGroup with get, the returned type is AbstractControl | null.

That’s because the control you are trying to get might not exist, and, if you are not careful, you are introducing a bug in your application by supposing it does exist.

If you don’t have the strictNullChecks option, you can do:

static passwordMatch(control: FormGroup) {
  const password = control.get('password').value;
}

but when you enable it, the compiler will complain, and may save you by warning you that the control may not exist, and that your code should handle this case.

You have to do something like:

static passwordMatch(control: FormGroup) {
  const passwordCtrl = control.get('password');
  const password = passwordCtrl !== null ? passwordCtrl.value : '';
}

Or you can use the ! post-fix expression operator introduced by TypeScript, to basically say to the compiler “Shut up”:

static passwordMatch(control: FormGroup) {
  const password = control.get('password')!.value;
}

It can also be really interesting for your application models. Let’s say you have a UserModel representing your user, with a surname field that can be null. If you declare it correctly, the type should be:

interface UserModel {
  surname: string|null;
}

Then, with the strictNullChecks option activated, the compiler will help you when you use this model. For example:

this.user.surname.toLowerCase();

will throw a warning as the surname field can be null.

When you have complex entities coming from your server, it can really help you to have this kind of warning to avoid subtle and hard to avoid bugs.

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!

Oh, and our Pro Pack has 3 new exercises about the router! A perfect way to learn about protecting routes with guards, nested routes, resolving data before displaying the component, and how to split your app in small chunks that can be lazy-loaded.


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

22-24 aout à Lyon
12-14 sept. à Paris
14-16 nov. à Lyon
12-14 dec. à Paris


Suivez-nous


Posts plus anciens