Home .NET Création d’une application SPA .NET Core/Angular [1/9]

Création d’une application SPA .NET Core/Angular [1/9]

  Nolan VIEIRA Développeur .NET/Angular 25 min 4 novembre 2019

Création d’une application SPA .NET Core/Angular

Cette suite d’articles a pour objectif de vous expliquer les avantages techniques avec l’utilisation d’une SPA en .NET Core et Angular. Nous allons voir comment fonctionne cette stack technique et construire un projet avec ce choix technologique. Dans les prochains chapitres, nous allons voir pour ajouter de la sécurité et une authentification. Cette suite d’articles est à destination des développeurs qui ont une notion et une compréhension du langage C#.

Explication du Single Page Application

Une Single Page Application est un terme utilisé pour décrire le comportement d’exécution d’une application. une application en JavaScript est chargée et lancée depuis la page web principale d’une application écrite en langage qu’on utilise exclusivement en backend. On distingue souvent une application réactive et qui est écrite en JavaScript de par sa facilité de navigation sans pour autant avoir un chargement dans la page.

Les avantages sont nombreux, c’est pourquoi nous retrouvons de plus en plus souvent le SPA dans les projets.
Avec une Web API ou un projet en MVC, nous pouvons faire une SPA sur des applications écrites en PHP, .NET, Java ou tout autre langage pour le Backend. Le principe est simple : nous utilisons la page principale du projet backend pour charger et lancer l’application JavaScript comme Angular, React ou VueJS.

Cette technique est encore utilisable aujourd’hui, mais elle est maintenant différente. Pour les plus anciens, le fait de lancer une application AngularJS depuis la vue Index du HomeController est maintenant révolu ! Les nouvelles templates de projet Angular (Attention, je ne parle pas de AngularJS) fournies avec Visual Studio en .NET Core sont différents et beaucoup plus moderne.

En effet, le csproj du projet principal (donné avec le template officiel de Microsoft pour faire une SPA .NET Core/Angular) est légèrement différent. Nous retrouvons une partie qui vérifie la présence de NodeJS sur la machine et installe les dépendances d’Angular lors du lancement de l’application .NET Core:

<Project Sdk="Microsoft.NET.Sdk.Web">


  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>

    <!-- Set this to true if you enable server-side prerendering -->
    <BuildServerSideRenderer>false</BuildServerSideRenderer>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DocumentationFile>.\Demo.xml</DocumentationFile>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Api.Analyzers" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
    <PackageReference Include="NSwag.AspNetCore" Version="12.0.9" />
  </ItemGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Content Remove="$(SpaRoot)**" />
    <None Remove="$(SpaRoot)**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

</Project>

Nous pouvons aussi remarquer des sécurités, comme la vérification de la présence de NPM sur la machine ou bien l’exclusion du dossier « Node_Module » et de « dist » (qui se trouvent dans le dossier « ClientApp », le dossier avec votre code Angular) du projet une fois la solution compilée, car elle devient naturellement inutile une fois que l’application Angular est générée.

Pour lancer l’application Angular, la template Angular proposé par .NET Core dispose d’un npm start dans le Startup.cs :

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    app.UseSpa(spa =>
    {
        // To learn more about options for serving an Angular SPA from ASP.NET Core,
        // see https://go.microsoft.com/fwlink/?linkid=864501

        spa.Options.SourcePath = "ClientApp";

        if (env.IsDevelopment())
        {
            spa.UseAngularCliServer(npmScript: "start");
        }
    });
}

Cette combinaison de technologie est une valeur sûre aujourd’hui. Elle existe depuis longtemps et nous retrouvons des templates officiels de Microsoft qui proposent de faire une SPA Angular depuis de nombreuses années. La raison est simple : le web d’aujourd’hui demande une flexibilité et de plus en plus d’interaction dynamique entre le site et l’utilisateur. Faire de l’Ajax dans tous les sens et faire du JavaScript pour chaque action demande énormément de code. Un autre point important, la maintenabilité d’un code Javascript est rarement une chose facile avec l’évolution d’un projet, surtout dans nos projets MVC.

Pour résumer, avant les SPA :

  • La maintenabilité du code est désastreuse.
  • Les développeurs C#/Java n’ont pas une bonne pratique dans l’écriture du code JavaScript.
  • Un manque de flexibilité évident dans la manipulation et l’ajout de fonctionnalités : un temps de développement long dans l’ajout de fonctionnalités en JavaScript (qui n’existe pas avec l’utilisation de VueJS, React ou Angular car ce n’est pas hasardeux. Il y a une façon logique et propre de le faire).
  • Des interactions limitées et qui deviennent intenables :
    • La modification du DOM est vraiment compliquée à forte utilisation de JQuery/JavaScript, nous arrivons rapidement à 300 lignes de code JavaScript sur une simple vue HTML.
    • Nous pouvons trouver des cas d’empilement d’actions avec l’utilisation d’événements dans JavaScript, ce qui provoque des interactions non désirées et que nous ne pouvons pas deviner sans expérience.
    • Le manque de bonnes pratiques et de normes pour cadrer le projet entre les développeurs.

Les enjeux actuels nous imposent de faire des applications réactives, maintenables et avec un temps de développement court, ce que les langages backend ne permettent pas. C’est pourquoi le Javascript domine toujours autant les statistiques d’utilisation dans les sites. La maintenabilité est bien meilleure, rapide, simple et surtout permet un code bien structuré avec l’utilisation d’une solution comme Angular, React ou VueJS !

Le .NET

Avant d’avancer plus en détail sur le choix technologique de Angular, nous allons revoir rapidement l’avantage de rester chez Microsoft avec l’univers de .NET.

L’avantage du .NET Core est qu’il dispose d’une forte expertise depuis plusieurs années avec la technologie .NET framework, qui est maintenant dirigée sur le .NET core. Microsoft, avec la version .NET Core 2.1 (LTS), propose une technologie mature et robuste qui fonctionne sur Mac OS, Linux et Windows.

Cette suite d’articles repose sur la version 2.2 de .NET Core, mais je prévois une révision majeure de ce guide après la sortie de .NET Core 3.1 (LTS) et Angular 9 avec le moteur de rendu Ivy, ce qui promet d’être vraiment intéressant.

La version 3.0 est disponible depuis septembre 2019 avec le support de C# 8. La version 3.1 LTS est sortie fin novembre 2019.

Concernant le futur du .NET, Microsoft a vraiment bien réussi son objectif. Le Cross-platform et l’open-source sont des choix vraiment rassurants pour un développeur, ce qui permet d’avoir une grande communauté d’utilisateurs. Petit point important, le choix de Google avec l’utilisation principale de Kotlin (JetBrains) dans Android est un véritable tournant pour les développeurs Java, ce qui peut maintenant favoriser le choix de partir chez Microsoft pour les développeurs Java qui souhaitent changer de technologie. L’avenir nous dira si Microsoft gagnera des utilisateurs ou non pour les applications web, car le langage Java semble perdre des avantages et ses développeurs.

De mon point de vue, le .NET est un choix judicieux, d’autant plus que le .NET 5 (la version après .NET Core 3.1) arrivera fin 2020 avec un lot fort intéressant de fonctionnalités.

Pourquoi TypeScript ?

Vous savez déjà sans aucun doute que le .NET utilise un langage de programmation qui demande une compilation : le C#. L’avantage premier d’un langage compilé, c’est qu’il permet de vérifier que votre code n’a pas d’incohérence de type, car c’est un langage fortement typé !

Beaucoup de développeurs apprécient l’utilisation de langage fortement typé. Ce n’est pas anodin que le langage PHP commence à avancer dans cette direction. Pour TypeScript, nous pouvons faire un raccourci et dire que les avantages sont les mêmes. Cependant, nous ne parlons plus de compilation pour le cas de TypeScript, mais de transpilation. Nous avons des optimisations globales dans notre code et la possibilité de choisir la version de EcmaScript pour les rétrocompatibilités. Je vous invite a regarder la documentation officiel sur les possibilités offertes.

Cet avantage n’existe pas en JavaScript pur, mais est présent dans le TypeScript. Aujourd’hui, nous pouvons assurément dire qu’il est dangereux de ne pas avoir de compilation/transpilation et un fort typage sur une application. Ce serait une régression inconcevable pour un choix technique.

Le TypeScript est un langage de Microsoft qui permet de typer, compiler et minifier du code pour le transformer en JavaScript. Les similitudes syntaxiques entre le C# et le TypeScript sont nombreuses, mais nous pouvons surtout saluer la forte implémentation dans les IDE ce qui offre une simplicité déconcertante dans l’écriture du code.

C’est pourquoi dans un choix technologique qui demande une utilisation en backend d’une application écrite en .NET Core, il est parfaitement logique de choisir une technologie basée sur TypeScript. Elle est cohérente pour un développeur .NET et offre un confort, un projet sécurisé et fiable dans le temps.

Pourquoi Angular ?

Angular est un framework, comme .NET Core. L’avantage est d’avoir une application fonctionnelle, rapide d’installation et de configuration et extrêmement bien documentée. Elle est fournie avec un ensemble d’outils standards comme : un module d’animations, de routing, de formulaire, un debug simple avec des Test Unitaire et e2e.

En quelques mots :

  • L’avantage est de ne pas avoir de dépendances sur d’autres projets Javascript qui risquent de ne plus être suivis ou sécurisés.
  • Par exemple, je pense que les applications écrites en JQuery ont souvent des tonnes de dépendances avec d’autres modules (Gestion des dates, des tableaux etc.)
  • Structure et stack : les projets Angular sont homogènes et on tombe rarement sur des cas particuliers.
  • L’approche MVC : Angular a un avantage pour une personne qui travaille sur le .NET, la syntaxe est énormément proche de celle du C# grâce à TypeScript. Le système de component est d’une telle flexibilité et simplicité qu’il est dur de repartir sur du Razor une fois qu’on l’a utilisé.
  • Sucre syntaxique : la syntaxe est simple et logique, vous passez rarement du temps sur la documentation d’Angular. Cependant, certains modules d’Angular Material (optionnels) peuvent être compliqués sans expérience sur Angular. Mais les exemples sont bien expliqués sur la documentation, donc je ne considère pas cela comme un frein technique. Bien au contraire, la documentation est vraiment simple, fonctionnelle et toujours à jour contrairement à d’autres technologies dans le web.
  • Nouvelle version majeure tous les 6 mois: les évolutions dans le framework sont nombreuses les mises à niveau sont simples et documentées.
    • Chaque version est maintenue pendant 18 mois et reste compatible avec les fonctionnalités de la version précédente (mais qui peuvent devenir dépréciées).

      Concernant les versions majeures, le .NET évolue aussi dans un système similaire, mais avec une mise à jour majeure et LTS tous les 3 ans maintenant. La bonne pratique est donc de toujours être sur des LTS et de faire des mises à niveau de version quand c’est possible, car un saut de deux versions LTS est brusque et dangereux !

    • Elles sont publiées lors des deux conférences internationales : en mai avec la NgConf et en novembre avec Angular Connect
  • Les évolutions ne cassent pas le code. La syntaxe est identique.
    • S’il y a un changement, Angular nous retourne les modifications à faire. Les méthodes dépréciées dans votre code sont directement affichées avec le CLI ng lint. – Documentation Angular

    Nous pouvons trouver des évolutions de syntaxe sur TypeScript, mais elles seront aussi retournées dans le terminal lors de la compilation si besoin !

  • Projet créé par Google, par une communauté de particuliers et de sociétés.
  • Ivy dans Angular 9 : C’est un nouveau moteur d’Angular qui optimise le code:
    Sans Ivy Avec Ivy Gain en %
    36 ko 2,7 ko 93% de compression du projet
    4 sec 2,2 sec 49% plus rapide pour le lancement

    Tests réalisés par telerik sur le moteur d’Ivy en version de test et non définitif sur Angular 8

    Cette optimisation n’est possible qu’avec un code compilé, ce qui donne un énorme avantage à Angular contre React et VueJS. Il y aura toujours des astuces d’optimisation grâce à de la transpilation.

  • La configuration simplifiée : nous avons des options qui permettent de demander que l’application soit minifiée en un seul fichier ou en plusieurs pour le lazy loading.
  • NativeScript: la possibilité de faire des applications natives avec Angular (ou VueJS), ce qui donne une vraie crédibilité de faire de l’Angular face à React Native.

Création du projet

Nous avons besoin de Visual Studio 2019 (Visual Studio 2017 est également compatible) pour la création du projet SPA en Angular depuis Windows. Il est aussi possible de le faire via le CLI dotnet si vous utilisez Visual Studio Code:

Ne pas oublier de regarder si vous avez bien la dernière version stable du SDK de .NET Core 2.2 pour suivre ce guide.

dotnet new angular -o Le-nom-de-votre-application

Nous avons aussi besoin de NodeJS pour l’utilisation de NPM, qui est un gestionnaire de package pour les projets JavaScript. Je vous recommande la LTS.

Lors de l’installation, il y a une option pour installer automatiquement un environnement de travail. Nous allons en avoir besoin, je vous recommande de cocher la case suivante :

L’utilisation de dépendance disponible sur NPM demande souvent d’avoir Python et VCC sur l’ordinateur pour compiler les packages. Cela évite d’avoir des problèmes et d’installer Node GYP.

Vous avez maintenant la possibilité de faire un projet SPA Angular depuis Visual Studio. Cependant, la version de Angular n’est pas à jour ; il y a un décalage et vous devez forcément faire à un moment donné une mise à niveau d’Angular. Je vous recommande donc de suivre le chapitre suivant pour avoir une application à jour et sécurisée.

Mise à niveau de Angular

Nous avons bien entendu une version installée d’Angular dans notre projet, qui se trouve dans /ClientApp. Nous devons faire une mise à niveau de Angular avant de commencer.

Il serait fort dommage de ne pas profiter de la dernière version stable d’Angular pour un nouveau projet. L’objectif est double, et savoir faire cette mise à niveau vous permet d’avoir la main totale sur votre projet. De plus, vous laisser juste avec une version de base n’est pas utile pour une formation, le but est de devenir autonome.

Lors de la création d’un projet sur Angular, nous installons généralement le CLI d’Angular en Global. Ceci nous force à avoir une version unique dans les applications Angular, mais il est conseillé d’utiliser le CLI du Node_module pour faire les commandes ng.

node .\node_modules\@angular\cli\bin\ng Nom_de_la_commande

Sinon, nous pouvons tomber sur le message suivant avec une erreur à la suite du message !

Your global Angular CLI version (7.1.2) is greater than your local
version (7.0.6). The local Angular CLI version is used.

To disable this warning use "ng config -g cli.warnings.versionMismatch false".

La solution pour cette erreur est de rétrograder la version globale ou de mettre à niveau la version locale de votre projet. Le plus simple reste d’utiliser la version présente dans le node_nodule de votre projet.

Dans un premier temps, nous allons récupérer les dépendances sur NPM (Gestionnaire de package de NodeJs) avec la commande suivante dans le dossier /ClientApp:

npm i

Nous allons donc faire la migration de Angular 5 vers la dernière version stable d’Angular. Pour cela, nous avons besoin de la dernière version d’Angular CLI

Visual Studio 2017/2019 propose avec le .NET Core 2.2 une template avec une version 6. La procédure est identique !

npm install @angular/cli

Nous pouvons ajouter aussi Angular CLI en Global avec l’option -g, mais il est obligatoire que la version en Local (dans le node_modules) soit mise à jour !

Une fois que @angular/cli est mise à jour, nous avons besoin de lancer la migration d’angular:

ng update @angular/cli ng update @angular/core

Si il y a une erreur avec le ng update @angular/core, nous pouvons le forcer avec :

npm install @angular/animations@latest @angular/common@latest @angular/compiler@latest @angular/core@latest @angular/forms@latest @angular/http@latest @angular/platform-browser@latest @angular/platform-browser-dynamic@latest @angular/platform-server@latest @angular/router@latest --save

npm install @angular-devkit/build-angular@latest @angular/compiler-cli@latest @angular/cli@latest @angular/language-service@latest --save-dev

 

Vous devez ensuite refaire les commandes précédentes du ng update !

Le fichier de configuration angular-cli.json va être automatiquement modifié et devenir angular.json (si votre version d’Angular était en version 5)

Voici un retour des modifications de Angular:

$ node .\node_modules\@angular\cli\bin\ng update @angular/cli
Updating karma configuration
Updating configuration
Removing old config file (.angular-cli.json)
Writing config file (angular.json)
Some configuration options have been changed, please make sure to update any npm scripts which you may have modified.
DELETE .angular-cli.json
CREATE angular.json (3704 bytes)
UPDATE karma.conf.js (993 bytes)
UPDATE src/tsconfig.spec.json (322 bytes)
UPDATE package.json (1650 bytes)
UPDATE tsconfig.json (407 bytes)
UPDATE tslint.json (3140 bytes)
UPDATE src/polyfills.ts (3164 bytes)

...

Mise à niveau de RxJS

Cette partie est uniquement pour les applications Angular 5. Si vous avez déjà une application Angular > à 6, vous pouvez passer au point suivant.

Nous parlerons de RxJS dans un prochain chapitre. Pour faire simple, c’est un outil qui permet d’utiliser des observables.

Nous pouvons trouver une procédure pour la mise à niveau d’un projet Angular de la version 5 vers la 6, car il y a énormément de changement dans l’utilisation de RXJS. Il n’est pas utile de lancer le script de migration pour les versions supérieures à Angular 6.

Voici la ligne de commande:

npm install -g rxjs-tslint typescript rxjs-5-to-6-migrate -p src/tsconfig.app.json

Plus d’informations sur les mises à niveau dans la documentation officielle !

Mise à niveau de Angular

Pour les mises à jour non majeures d’Angular, la commande est identique via la commande ng update. Cette commande permet de lister les mises à jour possibles.

Il y a trois erreurs possibles avec cette commande.

Par exemple un package mal reconnu :

$ node .\node_modules\@angular\cli\bin\ng update
We analyzed your package.json, there are some packages to update:

Name Version Command to update

@nguniversal/aspnetcore-engine 5.0.0-beta.5 -> 7.0.2 ng update @nguniversal/aspnetcore-engine

There might be additional packages that are outdated.
Run "ng update --all" to try to update all at the same time.

Il y a un souci avec le package @nguniversal/aspnetcore-engine, vous ne pouvez pas faire la mise à jour avec la ligne de commande donnée, car le vrai nom du package est : @nguniversal/module-map-ngfactory-loader. Pour faire cette mise à jour, nous devons installer à la main la mise à jour via la commande :

npm i @nguniversal/module-map-ngfactory-loader

La deuxième erreur est l’installation d’un package dans le mauvais ordre. Le package @angular/cdk est installé automatiquement avec la commande ng update @angular/material ! Inversement, une erreur d’installation s’affiche.

Les mises à jour recommandées sont généralement:

ng update @angular/cli
ng update @angular/core


// si vous avez Angular Material !
ng update @angular/material

Il est important de savoir qu’un simple projet en JavaScript utilise une multitude de packages (qui utilisent aussi d’autres dépendances …) et qui ne sont pas toujours maintenus et sans vulnérabilité !

Nous parlons ici des packages autre que Angular, karma et Jasmine sont des outils pour les tests en développement

Depuis un moment, NodeJS propose de remplacer les packages qui posent des problèmes de sécurité. Une chose à savoir, les modifications proposées ne touchent pas le fichier package.json, mais juste le package-lock.json !

Il va simplement remplacer les dépendances non sécurisées qui sont utilisées pour l’utilisation des packages installés depuis le package.json.

$ npm audit fix
...

added 40 packages from 68 contributors, removed 19 packages and updated 15 packages in 25.202s fixed 35 of 62 vulnerabilities in 24862 scanned packages
1 package update for 27 vulns involved breaking changes (use `npm audit fix --force` to install breaking changes; or do it by hand)

Nous avons fait une mise à jour des composants de Angular, mais pas de tous les packages du package.json.

Nous avons vu qu’il reste encore des vulnérabilités et cela n’est pas normal. Nous devons encore faire mieux ! Types, codelyzer, karma tools, jasmine, protractor, tslint, Core-js, Zone.js, RxJS ne sont pas sur leurs dernières versions !

Attention avec le TypeScript, Angular 7.1 demande la version 3.1.6 ! Nous devons laisser ng update faire la modification de version de TypeScript et non la forcer !

Attention avec @angular-devkit/build-angular, Angular 7.1 demande la version 0.10.0 ! Nous devons laisser ng update faire la modification et non la forcer !

La commande suivante a été testée sur Angular 7.1, nous devons toujours faire un test avec ng serve avant de push sur le git !

Voici les commandes de mise à jour:

npm install core-js@latest zone.js@latest rxjs@latest rxjs-compat@latest --save

npm install @types/jasmine@latest @types/jasminewd2@latest @types/node@latest codelyzer@latest karma@latest karma-chrome-launcher@latest karma-cli@latest karma-jasmine@latest karma-coverage-istanbul-reporter@latest karma-jasmine-html-reporter@latest jasmine-core@latest jasmine-spec-reporter@latest --save-dev

npm install protractor@latest ts-node@latest node-sass@latest tslint@latest rxjs-tslint@latest --save-optional

Du moment que npm nous dit :

added 22 packages from 46 contributors, removed 8 packages, updated 25 packages, moved 4 packages and audited 40839 packages in 24.811s found 0 vulnerabilities

C’est que nous avons un bon projet de base !

Ne pas oublier de lancer un ng serve pour valider que le projet compile et on est bons pour commit 🙂

Lire les articles similaires

Laisser un commentaire

Social Share Buttons and Icons powered by Ultimatelysocial