Use of Angular
Use of Angular
ASP.NET Core apps using Angular and the Angular CLI to implement a rich, client-
side user interface (UI).
Create a new project from a command prompt using the command dotnet new angular in
an empty directory. For example, the following commands create the app in a my-new-
app directory and switch to that directory:
Copy
dotnet new angular -o my-new-app
cd my-new-app
Run the app from either Visual Studio or the .NET Core CLI:
Visual Studio
.NET Core CLI
Ensure you have an environment variable called ASPNETCORE_Environment with a value
of Development. On Windows (in non-PowerShell prompts), run SET
ASPNETCORE_Environment=Development. On Linux or macOS, run export
ASPNETCORE_Environment=Development.
Run dotnet build to verify the app builds correctly. On the first run, the build
process restores npm dependencies, which can take several minutes. Subsequent
builds are much faster.
Run dotnet run to start the app. A message similar to the following is logged:
console
Copy
Now listening on: http://localhost:<port>
Navigate to this URL in a browser.
Warning
The app starts up an instance of the Angular CLI server in the background. A
message similar to the following is logged: NG Live Development Server is listening
on localhost:<otherport>, open a browser to http://localhost:<otherport>/. Ignore
this message�it's not the URL for the combined ASP.NET Core and Angular CLI app.
The project template creates an ASP.NET Core app and an Angular app. The ASP.NET
Core app is intended to be used for data access, authorization, and other server-
side concerns. The Angular app, residing in the ClientApp subdirectory, is intended
to be used for all UI concerns.
Run ng commands
In a command prompt, switch to the ClientApp subdirectory:
console
Copy
cd ClientApp
If you have the ng tool installed globally, you can run any of its commands. For
example, you can run ng lint, ng test, or any of the other Angular CLI commands.
There's no need to run ng serve though, because your ASP.NET Core app deals with
serving both server-side and client-side parts of your app. Internally, it uses ng
serve in development.
If you don't have the ng tool installed, run npm run ng instead. For example, you
can run npm run ng lint or npm run ng test.
console
Copy
cd ClientApp
npm install --save <package_name>
Publish and deploy
In development, the app runs in a mode optimized for developer convenience. For
example, JavaScript bundles include source maps (so that when debugging, you can
see your original TypeScript code). The app watches for TypeScript, HTML, and CSS
file changes on disk and automatically recompiles and reloads when it sees those
files change.
In production, serve a version of your app that's optimized for performance. This
is configured to happen automatically. When you publish, the build configuration
emits a minified, ahead-of-time (AoT) compiled build of your client-side code.
Unlike the development build, the production build doesn't require Node.js to be
installed on the server (unless you have enabled server-side rendering (SSR)).
You can use standard ASP.NET Core hosting and deployment methods.
There's a drawback to this default setup. Each time you modify your C# code and
your ASP.NET Core app needs to restart, the Angular CLI server restarts. Around 10
seconds is required to start back up. If you're making frequent C# code edits and
don't want to wait for Angular CLI to restart, run the Angular CLI server
externally, independently of the ASP.NET Core process. To do so:
In a command prompt, switch to the ClientApp subdirectory, and launch the Angular
CLI development server:
console
Copy
cd ClientApp
npm start
Important
Use npm start to launch the Angular CLI development server, not ng serve, so that
the configuration in package.json is respected. To pass additional parameters to
the Angular CLI server, add them to the relevant scripts line in your package.json
file.
Modify your ASP.NET Core app to use the external Angular CLI instance instead of
launching one of its own. In your Startup class, replace the
spa.UseAngularCliServer invocation with the following:
C#
Copy
spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
When you start your ASP.NET Core app, it won't launch an Angular CLI server. The
instance you started manually is used instead. This enables it to start and restart
faster. It's no longer waiting for Angular CLI to rebuild your client app each
time.
C#
Copy
options.SupplyData = (context, data) =>
{
// Creates a new value called isHttpsRequest that's passed to TypeScript code
data["isHttpsRequest"] = context.Request.IsHttps;
};
The SupplyData callback lets you pass arbitrary, per-request, JSON-serializable
data (for example, strings, booleans, or numbers). Your main.server.ts code
receives this as params.data. For example, the preceding code sample passes a
boolean value as params.data.isHttpsRequest into the createServerRenderer callback.
You can pass this to other parts of your app in any way supported by Angular. For
example, see how main.server.ts passes the BASE_URL value to any component whose
constructor is declared to receive it.
Drawbacks of SSR
Not all apps benefit from SSR. The primary benefit is perceived performance.
Visitors reaching your app over a slow network connection or on slow mobile devices
see the initial UI quickly, even if it takes a while to fetch or parse the
JavaScript bundles. However, many SPAs are mainly used over fast, internal company
networks on fast computers where the app appears almost instantly.
At the same time, there are significant drawbacks to enabling SSR. It adds
complexity to your development process. Your code must run in two different
environments: client-side and server-side (in a Node.js environment invoked from
ASP.NET Core). Here are some things to bear in mind:
SSR requires a Node.js installation on your production servers. This is
automatically the case for some deployment scenarios, such as Azure App Services,
but not for others, such as Azure Service Fabric.
JavaScript
Copy
if (typeof window !== 'undefined') {
// Call browser-specific APIs here
}