Upgrading tips for Angular 10 projects


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:

  1. Download the file from https://gist.github.com/mahmoudajawad/351b7e90460b5d78942046049a6f7598 to your project root (the same level in which package.json is at).
  2. Using your preferred console app, after setting your working directory to your project path, run: node update_package.tns-ng10.js.
  3. 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 your package.json file is already updated. b. To confirm, open package.json and confirm whether @nativescript/angular package version is set to ~10.0.0. c. If so, you probably have your package.json already updated by earlier run of the script. d. If not, delete package.json.bak. e. If issue is still persistent, let me know so I can work with you on it.
  4. Check the updated package.json file and make sure it looks fine.
  5. Delete webpack.config.js.
    • If you have made any changes to webpack.config.js you would need to keep them in mind to re-implement them afterwards as NativeScript packages would attempt to create updated webpack.config.js file when it is not present.
  6. Run npm run clean && npm run PLATFORM where PLATFORM is the platform you are attempting to deploy the app for.
    • Note that running tns run PLATFORM would result in non-working app due to required --no-hmr argument to be passed. using npm run PLATFORM shall give you a shorthand access to the action needed.
    • Running project in preview mode 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
  7. 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:

  1. Updated package.json packages versions as per this comment.
  2. Remove platforms version from nativescript section, but keep id property.
  3. Delete webpack.config.js.
  4. Run npm run clean && npm run PLATFORM where PLATFORM is the platform you are attempting to deploy the app for.
  5. 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, and webpack.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, and webpack.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-outlet with a GridLayout and 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.

Comments


Comments are disabled in preview mode.
NativeScript is licensed under the Apache 2.0 license
© 2020 All Rights Reserved.