Add new Angular CLI-based template #1288
Description
The Angular template shipped with .NET Core 2.0 originated well before @angular/cli
came on to the scene. Even when @angular/cli
was first shipped, it was unclear whether it would become the de facto standard way to build real-world Angular apps. But now it seems the Angular community largely sees the CLI as the preferred approach, and it has stabilised and matured into something you actually can use in real-world development scenarios.
So, even though the ASP.NET Core Angular template has pretty much all the same features as @angular/cli
such as HMR, AoT on publish, Karma tests, etc. (and in fact even some features that the CLI lacks, such as out-of-the-box server-side prerendering), it would be advantageous if our template achieved that stuff using @angular/cli
rather than having its own implementation. The key benefit is that developers will have an even more typical project setup, so basically all online tutorials, StackOverflow posts, etc., will apply without any modification.
Approach
The idea is for an updated dotnet new angular
template to use a new SpaServices
feature called Angular CLI middleware instead of the existing Webpack middleware. So it will still be a single ASP.NET Core project with the Angular part in a subdirectory called ClientApp
, but now when the browser makes requests for content under /dist
, we will pass through the request to an instance of @angular/cli
's ng serve
process. As such, the output and behaviour will be identical to what you'd get if you ran ng serve
directly, and all the same config and features apply. If you wanted, you could even take your ClientApp
directory out of your project and run it manually with ng serve
, since it's literally just a standard @angular/cli
project. Likewise you can ng eject
it if you don't want to use the Angular CLI for some reason (and then use Webpack middleware like before if you want).
Of course, because you then have a standard Angular CLI project, you can use all other CLI features such as ng generate
, ng lint
, etc., without anything being different just because you're also using ASP.NET.
We would also integrate with Angular CLI when you publish your app. That is, a single dotnet publish
command (or the Visual Studio equivalent option) would not only publish the .NET part but would also automate the process of using ng build -prod
, putting the output in the right places to be served in production. Likewise, server-side prerendering would also be achieved by a call into Angular CLI.
Note: This would not be a breaking change. The SpaServices
package will continue to work exactly the same with existing applications created using the .NET Core 2.0.0 template - this scenario remains fully supported.
Tasks
- Add
BuildServerSideRenderer
flag in csproj - Add new API for supplying custom data to prerenderer
- Support "proxy only" mode for AngularCliMiddleware, so you can have an
ng serve
process running separately and not restarted on each C# code change. Ideally, decouple the proxying from the Angular CLI-specific bits so it can be reused with other SPA frameworks. - Consider whether it's practical to proxy the HMR endpoint. If not, this will be difficult to use from inside a Docker container (or at least requires extra configuration). Update: it does now proxy, so should work fine in Docker.
- Try to get CLI's progress display reflected in the console.
- Ensure that any errors occurring in angular-cli-middleware.js are passed back upstream. This also includes the CLI writing to stderr.
- Stop hard-coding CLI options in angular-cli-middleware.js. Either have a .NET API for configuring them, or better, call a
script
inpackage.json
(in which case, make the task name appear explicitly in the C# source so people can discover what it does). - Make sure the
npm
child processes aren't left behind on exit, including when usingdotnet watch
, including on Mac/Linux - Get SSR working with publish by default. Waiting on Easy "ng build" improvements to make "platform":"server" work well on Windows & Visual Studio angular/angular-cli#7903
- Consider whether it's desirable to have
package.json
andnode_modules
at project root (is this necessary for VS to do auto-restore?). If so, need to support findingnode_modules
in ancestor directories usingrequire-from-string
-type approach (Resolve node modules in parent directories #154), since Angular app will be in subdirectory. Update: Not doing this - it's impractical. Angular CLI is hardcoded to assumenode_modules
is in the project root (e.g., seegetBrowserConfig
inmodels\webpack-configs\browser.js
line 25), so we'd need to have the .NET project root as the Angular CLI project root, which means merging the folder structures (super ugly, and violates the intended separation), or having an extremely nonstandard Angular CLI config to have it fetch all sorts of things from a special subdirectory (violates the idea of it being a standard Angular CLI project). Instead, we'll rely on the.csproj
containing instructions to do the applicablenpm install
in theClientApp
subdir during build when necessary. - Figure out how the APIs would look if someone wanted
index.html
to be a server-rendered cshtml page instead. Update: Not supporting this. Doesn't really make sense. - See if it's possible to detect efficiently whether the
<base href>
matches thePathBase
of the incoming request, and if not, fail with a clear message. Alternatives include rewritingindex.html
dynamically to inject a<base href>
based on the per-requestPathBase
, or just rely on people reading docs to know they have to configure this manually before publishing. - Ensure the right set of files are appearing in VS's Solution Explorer (e.g.,
package.json
should be there) - Add shrinkwrap
- Fix the bootstrap nav button in the Angular templates (and check it works in the others)
- Ship preview
Pre-preview (try it)
You can now try this out. For instructions, please see #1288 (comment)