Ionic Monorepos with NX

Today I am writing about Ionic and how to use it with NX. As I explained in previous posts Ionic enables you to write Angular code that can be used as the base for Android/iOS applications. So it enables you to write code that can be shared across all plattforms, which is a great opportunity. Together we will create a Nx monorepo which contains an Ionic application and can be extended very easily. You can find the code in my Github repo.

Why do we need Monorepos for creating this type of application? For many applications you not only need a frontend but also some backend functionality. In some businesses you might also have severall applications created in a project, something like a mobile app, a administrative application and so on. Most of the time you share functionality across both applications. To face that challange there are different approaches, one are node libraries which are shared across both applications. Another one would be to use Microfrontends and bundleling those frontends to two different applications. The third option is to create monorepos. All three approaches have pros and cons, however, if you have one or two frontend applications and maybe a Javascript backend application monorepos might be a good option for you. In general a monorepo is a project, that contains different projects and some shared functionality. NX is the framework that is used most the time in Angular projects. NX also creates configs for TypeScript, EsLint, Webpack and so on. So it provides a base to create extendable and maintainable applications that are consistent.

Basic setup

To start you need to have a running Node enviroment with an installed npx version. You can install npx by using npm i npx

Nx has in general some plugins that are summarized by Nxtend. Those are built to create specific type of applications in a NX enviroment. For instance, there is the @nxtend/ionic-angular plugin or a plugin for creating Nest backend applications.

To start of our application we need to create an empty nx workspace. That is done using the following command:

npx create-nx-workspace my-org --preset=empty

After typing in that command you might get asked if you want to use nx cloud. For this post I did not use that type of configuration. After the command is completed you will see an empty workspace that was created for you. This workspace does not contain of any application yet. If you have a short look into the created project you will see that the structure is a little bit different from normal Angular applications. Of course, you have a package.json but also there is no src directory. There is however an apps folder as well as a libs folder. The apps folder will later contain our applications and the libs folder can be used to create shared libraries. Also you might notice the jest.config files, that is because Nx is using Jest as the default test runner for unit tests.

Generating applications

I will create an Ionic application that uses Capacitor here. First of all we need to install the Nxtend Ionic Angular dependency and initialize it:

npm install --save-dev @nxtend/ionic-angular

In order to be able to use nx as a npm command I extend the package.json with the following script:

....
"scripts": {
  ....
  "nx": "nx"
},
....


npm run nx generate @nxtend/ionic-angular:init

After executing these two commands you can generate the new application:

npm run nx generate @nxtend/ionic-angular:app demo-app

Great! Now we have created our Ionic application in our Nx workspace. If you have a look into the code you will see that there is now a new folder in the apps which contains the demo-app. Also nx has created an E2E testing project for us that contains everything to get started with E2E testing with Cypress, great, isn’t it?

Now let’s have a look into the created application. Type in the following command to start a debug version of the app:

npm run nx serve my-app

It is possible that you see the following error after typing in that command:

Property 'name' has no initializer and is not definitely assigned in the constructor.

This is because of the default tsconfig which forces you to initialize all variables. To get rid of that error you need to go to the tsconfig.base.json and add that line to the compiler options:

"strictPropertyInitialization": false

After running the nx serve command again the compilation should work and you can checkout your awesome application.

Creating the Android app

Next, we want to create the Android app out of the code that we have so far. For doing that we need to build the app and than add the android plattform. For building the app you can call nx build demo-app. Also it is a good idea to extend the package.json with a script that is doing that in the future for us:

"scripts": {
  ...
  "build:demo": "nx build demo-app",
  ...
},

To add the android project you need to run the following command:

npm run nx run demo-app:add:android

This will create an android folder within the demo-app. This is used to create the APK. If you want to create iOS apps you can run the command

npm run nx run demo-app:add:ios

To open the app you need to call npm run nx run demo-app:open:android. Here I also suggest to add that script to package.json:

"name": "ionic-workspace",
"version": "0.0.0",
"license": "MIT",
"scripts": {
  ...
  "open:demo:android": "nx run demo-app:open:android",
  ...
},

If the code is changed you need to copy the new code to the android app. That is done using the command npm run nx run demo-app:copy:android. I also add that script to the package.json:

"scripts": {
  ...
  "copy:demo:android": "nx run demo-app:copy:android",
  ...
},

Creating shared libs

In the introduction I already explained that nx provides a possibility to create shared libraries that may contain shared functionality or model classes shared in different projects. To create the lib you simply need to type in the following command: npm run nx generate @nrwl/angular:library shared-lib

This command will setup everything so that you can simply use that lib. As already explained, libraries are created in the libs folder. After you create some class you will see the true magic of Nx, there is no need to recompile the library or add some package to a npm repository. You can simply import the created class if it is added to the index.ts of the lib:

import { ExampleSharedClass} from '@ionic-workspace/shared-lib';

Conclusion

As you see from that blog post, it is really simple to use Nx for Ionic Angular applications. Nx will bring you a scalable application with very useful preconfigured parts. That is why I would suggest using Nx for your next project if it fits to your requirements.

What do you think about using Ionic with Nx? Have you used Nx in the past? Was it useful to you?

One thought on “Ionic Monorepos with NX”

  1. Thank you for the explanation on how to use NX with ionic, it seems that this has changed in the past year as it was more complicated in the past. I was wondering how your general setup is and what you do at the beginning of the project to find out what technologies you use? Maybe you can do a post on that topic in the future.

Leave a Reply

Your email address will not be published. Required fields are marked *