Upgrading tips for Angular 10 projects
Continuing the series on Angular 10 support, a great community contributor Mahmoud offers some additional helpful tips and guidance
NativeScript team has done it again and delivered the latest Angular 10 support for NativeScript. The new release of @nativescript/schematics package marks another great milestone in the journey for unifying codebases across web and mobile, as well as improving the developer experience while building NativeScript with Angular. If you are new to @nativescript/schematics you need to have a look at the package source repository on Github to learn more about it. If you want to give it a shot now, you can do the following:
npm i -g @angular/cli // You could be needing to prefix sudo on GNU/Linux and other Unix-like OSes.
npm i -g nativescript // You could be needing to prefix sudo on GNU/Linux and other Unix-like OSes.
npm i -g @nativescript/schematics // You could be needing to prefix sudo on GNU/Linux and other Unix-like OSes.
ng new workspace
cd workspace
ng add @nativescript/schematics --skipAutoGeneratedComponent
// start apps:
npm run ios
npm run android
ng serve
Based on https://github.com/NativeScript/nativescript-schematics/pull/286#issuecomment-666116443
Upgrading your Project to Angular 10
Updating your project now actually prepares you for the upcoming NativeScript 7 release as it relies on the current running @nativescript/core rc's which use es2017 target builds for compliance with Angular 10 since es5 support was officially dropped by default. This is a wonderful and welcome change upcoming in NativeScript 7 and will allow nice optimizations with the v8 engine, advanced tree shaking and aligning your NativeScript code with modern JS ecosystems.
If you already use NativeScript with Angular and want to stay up-to-date with the project releases, here's your guide to upgrade your project to Angular 10:
WARNING: Make sure to have your project changes committed and pushed to your remote repository. The process involves some changes that would be beneficial to have a changeset diff on against your current project
1. Update package.json
package.json is the ultimate reference for what your project contains and depends on. For that, it currently enlists previous versions of your project dependencies. Nathan Walker, a TSC member, has explained and put in place the form in which package.json needs to look like. Based on his comment I created a sample node script that takes your current package.json and using Spread syntax it updates the packages that needs to be updated without removing your other project dependencies. The script additionally removes the platform version definitions from nativescript section of your package.json, as upgrading the platforms versions alongside @nativescript/angular packages is an advised step. To use the script:
- Download the file from https://gist.github.com/mahmoudajawad/351b7e90460b5d78942046049a6f7598 to your project root (the same level in which
package.jsonis at). - Using your preferred console app, after setting your working directory to your project path, run:
node update_package.tns-ng10.js. - The script would run and hopefully it would end with
🎉 Updated package.json!. a. If not, and the message you received is"package.json.bak" was found..., it is possible you already attempted to run script before and that yourpackage.jsonfile is already updated. b. To confirm, openpackage.jsonand confirm whether@nativescript/angularpackage version is set to~10.0.0. c. If so, you probably have yourpackage.jsonalready updated by earlier run of the script. d. If not, deletepackage.json.bak. e. If issue is still persistent, let me know so I can work with you on it. - Check the updated
package.jsonfile and make sure it looks fine. - Delete
webpack.config.js.- If you have made any changes to
webpack.config.jsyou would need to keep them in mind to re-implement them afterwards as NativeScript packages would attempt to create updatedwebpack.config.jsfile when it is not present.
- If you have made any changes to
- Run
npm run clean && npm run PLATFORMwhere PLATFORM is the platform you are attempting to deploy the app for.- Note that running
tns run PLATFORMwould result in non-working app due to required--no-hmrargument to be passed. usingnpm run PLATFORMshall give you a shorthand access to the action needed. - Running project in
previewmode using NativeScript Preview apps on Android and iOS is not possible as of this moment as an update for Preview apps is required and is undergoing: https://github.com/NativeScript/nativescript-schematics/pull/286#issuecomment-667577731
- Note that running
- If your app doesn't work, there's very high chance some imports are broken, which you will fix next.
If you prefer to do things yourself. Here's what you need to do:
- Updated
package.jsonpackages versions as per this comment. - Remove platforms version from
nativescriptsection, but keepidproperty. - Delete
webpack.config.js. - Run
npm run clean && npm run PLATFORMwhere PLATFORM is the platform you are attempting to deploy the app for. - If your app doesn't work, there's very high chance some imports are broken, which you will fix next.
2. Fixing imports
NativeScript with Angular 10 brings more standardized experience on using the framework. One aspect is importing the tools and classes provided by the framework. This will help improve your project's future upgrade resilience to framework changes since the core team can make improvements under the hood to organization of the framework classes without affecting tons of deep import paths which can be wildly varied from one project to the next. This means some old import styles in your project need to be updated. To do so use your IDE or editor to search for the following terms and replace them, as:
tns-core-modules
WARNING: Your search results would include results from
package.json,package-lock.json,package.json.bak, andwebpack.config.js. You should not attempt to modify these files.
This package contains all the core tools and classes of NativeScript. You would need to search for any import statement importing from tns-core-modules and replace it with @nativescript/core. If you have an import statement, importing from a nested module, such as:
import { screen } from 'tns-core-modules/platform';
you would need to replace the import as top-level to become:
import { screen } from '@nativescript/core'; // and not @nativescript/core/platform
// Still will give error, read next...
The change from tns-core-modules to @nativescript/core has also had some classes names changed, such as screen earlier which becomes Screen. You can figure this out by hitting your IDE or editor auto-complete combination (Usually, Ctrl+Space, Cmd+Space) to list all classes available in @nativescript/core package and find the possible new class name.
Some other imports are invalid totally now such as:
import * as applicationSettings from 'tns-core-modules/application-settings';
which need to be imported as:
import { ApplicationSettings } from '@nativescript/core';
You will be done with this step when you don't have any results when searching for the terms tns-core-modules or @nativescript/core/ in your codebase.
Top-level import is suggested in this comment and it was essential for my projects to be upgraded to Angular 10. Having deep imports seem to break my projects, and simply changing to top-level importing based on the comment suggestion resolved my upgrade issues.
nativescript-angular
WARNING: Your search results would include results from
package.json,package-lock.json,package.json.bak, andwebpack.config.js. You should not attempt to modify these files.
Similarly, you would need to replace all imports to nativescript-angular to @nativescript/angular. Same top-level rule apply here, so if after fixing your imports you end up with search results for @nativescript/angular/ you would need to drop those deep import statements and rebase them for top-level imports. A common one is the import statement in app-routing.module.tns.ts which gets created by @nativescript/schematics as:
import { NativeScriptRouterModule } from 'nativescript-angular/router';
which, if you just change to:
import { NativeScriptRouterModule } from '@nativescript/angular/router';
it would still break the app, but you need to completely drop the deep import as:
import { NativeScriptRouterModule } from '@nativescript/angular';
Some classes are not available after the upgrade such as DEVICE which used to be imported for injecting in your Angular classes. You now need to simply use Device from @nativescript/core without injecting it.
You will be done with this step when you don't have any results when searching for the terms nativescript-angular or @nativescript/angular/ in your codebase.
Additional Tips
As mentioned earlier, to run your NativeScript with Angular 10 app you can either use:
npm run PLATFORM
tns run PLATFORM --no-hmr
as compiling the app would fail if --no-hmr argument is not present when using tns.
If you ever used this nice hack to add re-routing to HMR you would need to undo it as it will break your app. you simply need to comment the line import './livesync-navigation.tns'; in your main.tns.ts file.
Lastly, if you get the following error:
com.tns.NativeScriptException: Calling js method onCreate failed
Followed with following error on Android and iOS respectively:
java.lang.IllegalArgumentException: Cannot add a null child view to a ViewGroup
Root should be either UIViewController or UIView
then, you probably are facing an interesting issue I faced, which is having app.component.tns.html look like:
<page-router-outlet></page-router-outlet>
And, wrapping page-router-outlet with any layout component such as GridLayout or StackLayout fixed the issue. So, your app.component.tns.html should become similar to:
<GridLayout>
<page-router-outlet></page-router-outlet>
</GridLayout>
CORE TEAM NOTE: It's advantageous to wrap
page-router-outletwith aGridLayoutand there will be more details shared on some advantages to this layout in the future which is why it's now the default and required.
State of Unit Testing
Unit Testing is broken since release of NativeScript with Angular 9. However, NativeScript team seems to have an idea about it and I'm hoping the issues surrounding this gets resolved soon. For now, you have to live without testing (which, I know you were hoping for all along xD).
Upgrade in Action
If you want to see upgrading in action, have a look at my repository which I used as one of the tests to confirm the sequence of events to upgrade NativeScript with Angular projects. Before the upgrade, the project was based on Angular 8, and now it's running on Angular 10 without any issues. Find the exact changes here: https://github.com/mahmoudajawad/nativescript-pokedex/commit/2e9723dd093244761cd524cb068a0563d5813e22.