Create a sub dir in your mvc app, like "Angular5".
Create your angular app here in the subfolder "Angular5" using the ng commands.
In the .angular-ci.json file edit the out dir to something like "outDir":"../MyDistFiles"
This will put your distributed files outside the "Angular5" source files dir.
DO NOT USE your main folder for your mvc app as the output "../" or the angular cli will delete all of your mvc app files without an undo feature so be sure to use a subdir.
Option 1:
In your source files change the Index.html to
<base href="/MyDistFiles/">
This works ok if your app will be in a hybrid mobile app if the user can't select refresh on your page but if in a browser the user will get a 404 if they hit refresh.
Option 2:
Create a blank MVC controller with a simple blank Index view. Call is something like MyAngularController.cs
You can use conditional compilation to use a --prod build versus debug.
The prod build is 1/10 the size as the debug build, so it is worth using.
In the web project build properties, Select the release configuration.
Add a conditional compilation symbol Named PROD.
public ActionResult Index()
{
#if PROD
ViewBag.IsProd = true;
#endif
#if !PROD
ViewBag.IsProd = false;
#endif
return View();
}
In your RouteConfig.cs add this to the top (not at the bottom) in
RegisterRoutes.
routes.MapRoute(
"Catch All",
"MyDistFiles/{*url}",
new { controller = "MyAngular", action = "Index", id = UrlParameter.Optional });
In the index.cshtml of MyAngularController use this.
@{
Layout = null;
}
@if (ViewBag.IsProd)
{
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ClientApp</title>
<base href="~/MyDistFiles/">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="styles.bundle.css?@ConfigSettings.AppVersion" rel="stylesheet" />
</head>
<body>
<app-root></app-root>
<script type="text/javascript" src="inline.bundle.js?@ConfigSettings.AppVersion"></script>
<script type="text/javascript" src="polyfills.bundle.js?@ConfigSettings.AppVersion"></script>
<script type="text/javascript" src="main.bundle.js?@ConfigSettings.AppVersion"></script>
</body>
</html>
}
@if (!ViewBag.IsProd)
{
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ClientApp</title>
<base href="~/MyDistFiles/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script type="text/javascript" src="inline.bundle.js"></script>
<script type="text/javascript" src="polyfills.bundle.js"></script>
<script type="text/javascript" src="styles.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
</html>
}
Now you can navigate to the http://localhost:port/MyDistFiles and use the angular app navigation, select f5 and everything reloads as it should.
When you do a prod build with angular cli it will by default add a hash to the file names making them always different for cache control. You can omit this hash action by using
ng build --prod -oh
You will notice in prod version of the cshtml I append an app version id to the javascript and css files. I do this to prevent cache of old versions in browsers.
In the application properties/Assembly information/Assembly Version you can use a build number like 1.0.*.. This will create a new build number every time you rebuild.
The method in the ConfigSettings.cs class is
public static string AppVersion
{
get
{
if (string.IsNullOrEmpty(appVersion))
{
appVersion = System.Reflection.Assembly.GetExecutingAssembly()
.GetName()
.Version
.ToString();
}
return appVersion;
}
}
I like the feature of using ng serve because you can easily see your changes in seconds as you work on your angular app rather than waiting each time for a full rebuild. Unfortunately if you are not using a CORS app but maybe forms auth then you won't be able to access your web api methods from another port number. The work around for this is to open a command prompt CD to your Angular5 Dir.
Run the command ng build --watch. The --watch will do the same as ng serve except for automatically refreshing the browser but it is a lot faster and more productive to select save on your files and then f5 on the browser as a few seconds later it rebuilds that fast.
You can set up a post build command in Application/Properties/Build Events so you don't forget to build your angular if you do a prod release
cd "$(SolutionDir)MyMVCApp\Angular5"
if $(ConfigurationName) == Release (
ng build --prod -oh
) ELSE (
ng build
)