Last month, Angular 5 was released with some code breaking changes. You can refer to this post for the list of changes. I was playing with Angular 5 and as part of this learning process; I thought of upgrading one of my previously created Angular 4 app to Angular 5. You can read my post about creating an Angular 4 application with Visual Studio 2017. This post talks about how to upgrade Angular 4 app to Angular 5 with Visual Studio 2017. The steps given in this post are applicable for Angular 4 apps created using Visual Studio 2017, but some of these steps will also apply to Angular 4 apps created using other ways.
Upgrade Angular 4 app to Angular 5
Configuring Angular with the Visual Studio was never straightforward until a few Angular ready templates introduced in Visual Studio. Similarly, the whole upgrade process also gives the same experience. It is not straightforward and time-consuming as Angular 5 has some code breaking changes. Let’s see this step-by-step process.
- First, close all instances of Visual Studio 2017 as in my case the Angular package upgrade didn’t work when the VS was running. NPM could not upgrade the packages. So I suggest you to close VS instances.
- Open PowerShell (Make sure to run it as Administrator). You can also use Node.js command prompt. I first tried with Node.js command prompt, but the packages were not updated in VS 2017. Then, I tried with PowerShell and things worked.
- Browse to the location of the project and run
dir
command. You should seepackage.json
file present in the output listing. - Update the Angular packages using the following commands.
- npm install -g npm-check-updates
- and ncu -u
If you get any error while running these commands, update your node and npm version. You can follow the instructions given in this post to upgrade node and npm.
You should see all the Angular packages are upgraded to Angular 5.
- Open your Angular 4 project in Visual Studio 2017 and go to Dependencies-> npm to check the Angular version. The packages should point to Angular 5.
If the packages are still pointing to Angular 4, then delete the package-lock.json and follow the above-given steps again.
- As you know, Webpack is used as module bundler by Visual Studio. Webpack uses AotPlugin to compile the Angular 4 apps, now Webpack no longer uses Aotplugin for Angular 5. It now uses AngularCompilerPlugin. You can read more about this here.
So open
webpack.config.js
and replace all occurrences of AotPlugin with AngularCompilerPlugin. - Open ClientApp/boot.server.ts file and replace the following line of code (line no.22).
const zone = moduleRef.injector.get(NgZone);
with,
const zone: NgZone = moduleRef.injector.get(NgZone);
- Switch from Http Service to HttpClient Service. In Angular version 4.3
HttpClient
was shipped in@angular/common
as a smaller, easier, and more powerful way to make web requests in Angular. The newHttpClient
has gotten some great praise from developers, soHttpClient
is recommended by the Angular team for all applications, and@angular/http
library is deprecated. To update to HttpClient, you’ll need to make the following changes:- Replace HttpModule with HttpClientModule from
@angular/common/http
in each of the modules. - Inject the HttpClient service.
- Remove any
map(res => res.json())
calls.
The fetch data component uses
HttpModule
. It is located at “ClientApp/app/components/fetchdata”. Open the file and replace it withHttpClientModule
. The following changes need to be done in the fetchdatacomponent.ts file,
Replace All Http Declarations with HttpClient,import { Http } from '@angular/http';
with,
import { HttpClient } from '@angular/common/http';
HttpClient provides high-level abstractions for application programming. With Http, the fetch data service code is like:
constructor(http: Http, @Inject('BASE_URL') baseUrl: string) { http.get(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => { this.forecasts = result.json() as WeatherForecast[]; }, error => console.error(error)); }
Inject
HttpClient
in constructor and app code will be like:constructor(httpClient: HttpClient, @Inject('BASE_URL') baseUrl: string) { httpClient.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => { this.forecasts = result; }, error => console.error(error)); }
If you want to learn all of Angular, I want to personally recommend ng-book as the single-best resource out there. You can get a copy here.
In the earlier post creating an Angular 4 application with Visual Studio 2017, I extended the fetch data component service to add a summary filter. So based on the same example, the updated code for fetchdatacomponent.ts will be like:
import { Component, Inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'fetchdata', templateUrl: './fetchdata.component.html' }) export class FetchDataComponent { public forecasts: WeatherForecast[]; public cacheForecasts: WeatherForecast[]; public summaries: any[]; constructor(httpClient: HttpClient, @Inject('BASE_URL') baseUrl: string) { httpClient.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => { this.forecasts = result; this.cacheForecasts = this.forecasts; }, error => console.error(error)); httpClient.get<any[]>(baseUrl + 'api/SampleData/GetSummaries').subscribe(result => { this.summaries = result; }, error => console.error(error)); } filterForeCasts(filterVal: any) { if (filterVal == "0") this.forecasts = this.cacheForecasts; else this.forecasts = this.cacheForecasts.filter((item) => item.summary == filterVal); } } interface WeatherForecast { dateFormatted: string; temperatureC: number; temperatureF: number; summary: string; } interface Summary { name: string; }
- Replace HttpModule with HttpClientModule from
- Replace
HttpModule
withHttpClientModule
in app.module.shared.ts file. - Finally, change the following line of code in file Views/Home/Index.cshtml
<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>
To,
<app>Loading...</app>
That’s it. We are done with all the changes required to upgrade the Angular 4 app to Angular 5. We can now run the app to see Angular 5 app in action. You may see the following exception in the browser.
“NodeInvocationException: No provider for PlatformRef!”
To fix this issue, update the webpack to the latest version. Execute the following command in PowerShell to update webpack,
npm install --save-dev @ngtools/webpack@latest
Build the app and run again. You should see app running in the browser. You can verify the Angular version by visiting counter component.
You can find the source code here at Github.
Reference post:
- Angular 5 and .NET Core 2 with Visual Studio 2017
- How to Upgrade from Angular 2 to Angular 5 Apps
- Upgrade to Angular 5 and HttpClient
- Upgrade from Angular 4 to 5: “NodeInvocationException: No provider for PlatformRef!”
Summary
To conclude, this post takes you through a detailed guide for upgrading Angular 4 app created using Visual Studio 2017 to Angular 5. The main changes are with respect to upgrading Angular packages, changing Angular compiler plugin used by webpack and switching from Http to HttpClient module. The whole process is quite time-consuming and not documented anywhere. It would be ideal to have an automatic upgrade and an option to choose the Angular version while creating the project in Visual Studio to avoid burning the midnight oil.
Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.
10000X Thanks friend
thank you very much. you post helped me a lot, i found it late but its better then nothing 🙂 at least solved my problem
Awesome explanation. I am able to migrate my web application.
Thank you…
Hi, I’m following the first few steps (close VS, open powershell as admin, run `npm install -g npm-check-updates` followed by `ncu -u`, open Visual Studio, check dependencies, if no, then delete package-lock.json and try again), but this doesn’t work.
When I run `npm install -g npm-check-updates` I get a warning that says, “npm WARN npm@3.10.10 had bundled packages that do not match the required version(s). They have been replaced with non-bundled versions. +npm-check-updates@2.14.1″. Then when I run `ncu-u`it will initially say all my packages have been updated to the latest. I’ll open VS2017 and it still shows my packages as being 4.2.5. If I close it and repeat the commands, I get the same warning, and then `ncu -u` always reports “aspnet-webpack ^2.0.1 -> ^2.0.3”.
I have no package-lock.json in the directory where the solution lives. Any ideas? I’ve followed multiple guides and none of them work for me.
Before applying commands delete package.lock.json (or if exists npm-shrinkwrap.json)
Here are the steps to update the VS 2017 dependencies:
– Delete the npm-shrinkwrap.json file. (You cannot see it in VS 2017 until you “show all files”).
– Upgrade Angular to version 5.x in your package.json with the steps mentioned above in that post.
– Add manually the “popper.js”: “^1.12.5” in your package.json (this package is required later in the steps to upgrade angular)
– Run npm install (that will install popper)
– Run VS 2017 solution. (that will update the Dependencies/npm packages in VS 2017)
After these steps, a package-lock.json file will be created. Be sure to delete that file if you have any issue later during package update.
Steve,
I have followed the steps above (for the mentioned VS+Angular template setup) but it only updates 2 packages for me… I DEFINITELY don’t have the package-lock.json anywhere within the project dir but found the npm-shrinkwrap.json.
I have tried using Node.js command prompt and Powershell (both run as admin) with all instances of VS closed.
Everything seems to run smooth and no errors are reported; the package.json is now showing the latest package versions but the packages under npm folder still restore to the original 4.2*
I’ve removed the contents of the node_modules folder in the proj dir and tried restoring several times… still no joy…
Could you guys advise?
Hi,
When I run the app (debug) the js files are minified and bundled in one file and I see this console message:
The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.
How do I set the mode to development so I get unminified files in debug mode?
(I’m running IIS express because the site needs Windows authorization)
thx!
the complete console output:
./node_modules/@angular/core/esm5/core.js
6558:15-36 Critical dependency: the request of a dependency is an expression
@ ./node_modules/@angular/core/esm5/core.js
@ ./ClientApp/boot.browser.ts
@ multi event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.browser.ts
./node_modules/@angular/core/esm5/core.js
6578:15-102 Critical dependency: the request of a dependency is an expression
@ ./node_modules/@angular/core/esm5/core.js
@ ./ClientApp/boot.browser.ts
@ multi event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.browser.ts
./node_modules/@angular/core/esm5/core.js
System.import() is deprecated and will be removed soon. Use import() instead.
For more info visit https://webpack.js.org/guides/code-splitting/
@ ./ClientApp/boot.browser.ts 6558:15-36 4:0-47
@ multi event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.browser.ts
./node_modules/@angular/core/esm5/core.js
System.import() is deprecated and will be removed soon. Use import() instead.
For more info visit https://webpack.js.org/guides/code-splitting/
@ ./ClientApp/boot.browser.ts 6578:15-102 4:0-47
@ multi event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.browser.ts
configuration
The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
main-client.js (1.11 MiB)
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
main-client (1.11 MiB)
main-client.js
webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
Robert,
You can change the environment setting in two ways.
1. Right click on Project -> select properties -> navigate to debug tab and set ASPNETCORE_Environment variable value to “Development”.
2. Go to command prompt and navigate to your project directory and execute the following command.
“SET ASPNETCORE_Environment=Development”
I already have this setting in the debug tab:
ASPNETCORE_Environment variable value to “Development”
and this is the launchSettings.json:
{
“iisSettings”: {
“windowsAuthentication”: true,
“anonymousAuthentication”: false,
“iisExpress”: {
“applicationUrl”: “http://localhost:9180/”,
“sslPort”: 0
}
},
“profiles”: {
“IIS Express”: {
“commandName”: “IISExpress”,
“launchBrowser”: true,
“environmentVariables”: {
“ASPNETCORE_ENVIRONMENT”: “Development”
}
},
“WebApp”: {
“commandName”: “Project”,
“launchBrowser”: true,
“environmentVariables”: {
“ASPNETCORE_ENVIRONMENT”: “Development”
},
“applicationUrl”: “http://localhost:9181/”
}
}
}
Okay. It seems that it’s the webpack mode, not the ASP.NET Core mode. Can you please check the script section in your package.json file. What value is set for the build entry?
This link will help you to set up development mode for webpack
https://www.valentinog.com/blog/webpack-4-tutorial/
I already looked at that article and added this:
“scripts”: {
“dev”: “webpack –mode development”,
“build”: “webpack –mode production”,
“test”: “karma start ClientApp/test/karma.conf.js”
}
but no effect. this is the complete package.json:
{
“name”: “WebApp”,
“private”: true,
“version”: “0.0.0”,
“scripts”: {
“dev”: “webpack –mode development”,
“build”: “webpack –mode production”,
“test”: “karma start ClientApp/test/karma.conf.js”
},
“devDependencies”: {
“@angular/animations”: “5.2.7”,
“@angular/cli”: “^1.7.2”,
“@angular/common”: “5.2.7”,
“@angular/compiler”: “5.2.7”,
“@angular/compiler-cli”: “5.2.7”,
“@angular/core”: “5.2.7”,
“@angular/forms”: “5.2.7”,
“@angular/http”: “5.2.7”,
“@angular/platform-browser”: “5.2.7”,
“@angular/platform-browser-dynamic”: “5.2.7”,
“@angular/platform-server”: “5.2.7”,
“@angular/router”: “5.2.7”,
“@ngtools/webpack”: “^1.10.1”,
“@types/chai”: “4.1.2”,
“@types/jasmine”: “2.8.6”,
“@types/webpack-env”: “1.13.5”,
“angular2-router-loader”: “0.3.5”,
“angular2-template-loader”: “0.6.2”,
“aspnet-prerendering”: “^3.0.1”,
“aspnet-webpack”: “^2.0.3”,
“awesome-typescript-loader”: “3.5.0”,
“bootstrap”: “4.0.0”,
“chai”: “4.1.2”,
“css”: “2.2.1”,
“css-loader”: “0.28.10”,
“es6-shim”: “0.35.3”,
“event-source-polyfill”: “0.0.12”,
“expose-loader”: “0.7.4”,
“extract-text-webpack-plugin”: “3.0.2”,
“file-loader”: “1.1.11”,
“html-loader”: “0.5.5”,
“isomorphic-fetch”: “2.2.1”,
“jasmine-core”: “3.1.0”,
“jquery”: “3.3.1”,
“json-loader”: “0.5.7”,
“karma”: “2.0.0”,
“karma-chai”: “0.1.0”,
“karma-chrome-launcher”: “2.2.0”,
“karma-cli”: “1.0.1”,
“karma-jasmine”: “1.1.1”,
“karma-webpack”: “2.0.13”,
“preboot”: “6.0.0-beta.3”,
“raw-loader”: “0.5.1”,
“reflect-metadata”: “0.1.12”,
“rxjs”: “5.5.6”,
“style-loader”: “0.20.2”,
“to-string-loader”: “1.1.5”,
“typescript”: “2.7.2”,
“url-loader”: “0.6.2”,
“webpack”: “4.0.1”,
“webpack-cli”: “^2.0.10”,
“webpack-hot-middleware”: “2.21.1”,
“webpack-merge”: “4.1.2”,
“zone.js”: “0.8.20”
},
“dependencies”: {
“popper.js”: “^1.12.9”
}
}
Doesn’t work for me.
node_modules@ngtoolswebpacksrcplugin.js:79
SyntaxError: Unexpected token {
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:373:25)
at Object.Module._extensions..js (module.js:404:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at Object. (C:SourceSparkleSistersSparkleSistersnode_modules@ngtoolswebpacksrcindex.js:22:10)
at Module._compile (module.js:397:26)
at Object.Module._extensions..js (module.js:404:10)
Process terminated with code 1.
Thanks for the post.
Since I made these changes, I lost the ability to set breakpoints in the Typescript code. Every breakpoint now shows an open red circle and says “The breakpoint will not currently be hit. No code has been loaded for this code location”. I had done your last step of upgrading to the latest webpack (even though I didn’t have that exception).
I backed up and did the upgrade again. I checked whether I still had breakpoints after each step. They still worked after I did “npm install -g npm-check-updates” and “ncu -u”.
But after I made the changes to webpack.config.js and boot.server.ts, I got the error on the breakpoint that was set.
John,
Frankly, I am not sure what could be the reason for this. After some googling found this link having solution for the issue.
Give it a try and let me know if that works.
Thanks for the suggestion. For now I got around the problem by not switching from Aotplugin to AngularCompilerPlugin. The link you included gets the error “No symbols have been loaded for this document.” I’m getting “No code has been loaded for this code location”. The first suggested solution in that link involved finding which symbols are missing. The second one involved removing a conflict in duplicate file names with mixed case. I had that problem once before and resolved it.
But switching to AngularCompilerPlugin from AotPlugin will not run the Angular 5 app as Angular 5 is using Aot not Angular compiler.
Breakpoints work if you set
“webpack”: “2.6.1”
in package.json.
You may need to run “npm update” after that.
Maybe someone could look into it why newer webpack doesn’t work.
This breaks webpack hot swap. I get following error when I run app:
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred. (Unexpected token import
C:\projects\VIN.Members\VIN.WebApp\webpack.config.js:4
import { AngularCompilerPlugin } from ‘@ngtools/webpack’
^^^^^^
Other more effective option to force VS to update all NPM dependencies to latest version would be by selecting all dependencies inside of NPM virtual folder then right click and Update packages.
Regards!
This doesn’t work.
It seems that Core 2.0 builds with an npm-shrinkwrap.json file. This seems to perform the same duties as the package-lock. Interestingly, when I deleted the npm-shrinkwrap and ran npm install after updating the package.json a package-lock.json was built to replace the mpm-shrinkwrap.
Thank you for this very helpful article.
I already had most of this figured out and the debug build works but now the release/prod build fails at webpack:
“node node_modules/webpack/bin/webpack.js –env.prod”:
ERROR in ./ClientApp/boot.browser.ts
Module not found(0,0): Error : Can’t resolve ‘./app/app.module.browser.ngfactory’ in ‘\ClientApp’
@ ./ClientApp/boot.browser.ts 8:0-74
There are a lot of similar errors online but their solution didn’t work for me.
@Garnx – I am hitting the same error. The line that it’s failing on in boot.browser.ts is “import { platformBrowserDynamic } from ‘@angular/platform-browser-dynamic’;”. I assume your line “8:0-74” is the same import statement.
Were you able to find a solution or further information?
I am not finding the package-lock.json file. The package.json file points to Angular 5.2.1 but when I open the dependencies folder the node packages are still pointing to 4.2.5. Any help would be appreciated.
The package-lock.json file will be visible only when you click show all files option in solution explorer. It is hidden by default. I also faced the similar problem but deleting the lock file helped me to fix this issue.
HI Well Done !!!
You have explained it clearly to the point. I have an issue when follow the steps
npm install –save-dev @ngtools/webpack@latest
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {“os”:”darwin”,”arch”:”any”} (current: {“os”:”win32″,”arch”:”x64″})
any Idea?
Chanuri,
Thanks for the appreciation. I am glad it helped you..
Well I am also getting the same warning. You can ignore this warning. As you are using Windows os and fs-events is required on macOS. So that’s ok.
Good Job!
Looks like you and I have been playing with the same tools i.e. .Net Core and Angular in 2017.
Well, I recently solved this problem, and I had to use Node v9 and latest NPM to upgrade to Angular5, because somehow Node v5 or v7 were not updating the Angular’s packages to v5. Well, thanks again. Great Post indeed!