April 30, 2021
  • Engineering
  • Tutorials
  • Angular
  • Monorepos
  • NX

Ionic Angular monorepos with NX

Devin Shoemaker

This is part two of a new series on monorepos. By the end of the series, you’ll have the tools you need to adopt monorepo setups in your organization.

Between sharing code, managing dependencies across projects, and more, monorepos can require a lot of investment to get right. Thankfully, there are many different tools out there that can streamline the process and get developers on the right path. There’s Lerna, Yarn workspaces, npm workspaces (with npm v7), and the one we’ll look at today, Nx.

Let’s look at setting up an Nx workspace and looking at a few packages that can help Ionic Angular developers manage complex app setups and ship their apps faster.

What is Nx?

Nx is described as “extensible dev tools for monorepos” and is created by Nrwl, a company founded by former Angular team members. The tooling has first-class support for Angular, React, Next.js, and more all within a single workspace. This includes generating both applications and libraries for all of these frameworks. The magic comes from the Nx CLI. The experience is very similar to the Angular CLI, but with support for far more technologies than just Angular.

Most monorepo tools are designed to retrofit existing applications, but Nx has a different approach to offer the best monorepo experience possible. While it’s possible to port an existing application or monorepo to an Nx workspace, it’s best to let the Nx CLI generate the base workspace and application due to how the tooling architects multiple projects in the same repo.

Single Source of Truth

Nx strongly enforces the “single package philosophy”. This is when all projects in a monorepo workspace share the same version of all dependencies. When dependencies are mismatched across projects, you can run into errors and inconsistencies. Tools like Lerna and Yarn workspaces help with this, but it can still be confusing to developers because each project typically has its own package.json. Nx encourages users to add all dependencies to the workspace root package.json to easily keep track of dependency versions and upgrades. While this may seem like a departure from what you are used to, the Nx plugin architecture makes this easier to manage.

Extensible architecture

While frameworks help provide a structure for building applications, Nx realized that there is no “one size fits all” solution, especially with monorepos. To address this, Nx has its own plugin architecture to automate the configuration and tailor your experience to the tools you use. Nx plugins allow you to focus on getting to the code, not dealing with configuration. The default plugins help you generate Angular and React applications/libraries in a single workspace, but there are also plugins for Storybook, Cypress, ESLint, and more.

Common Use Cases

Okay, so Nx sounds great, but you might be asking, “How does this benefit me and my Ionic apps?” Some common situations where Nx can help are:

If your organization develops multiple Ionic applications, then you may be implementing very similar components across these apps. Whether it’s the authentication interface or a similar layout for settings pages, you can benefit from sharing these components across applications. Nx makes it easy to develop shared libraries for React and Angular, and enables you to avoid copying and pasting code. This also unifies your user experiences.

If your applications do not share many UI components, they still benefit from sharing types, interfaces, and other functions. Sharing code can not only improve the developer experience, it can also improve the reliability of applications and avoid bugs.

Nx also supports extending configs for TypeScript, ESLint, Webpack, and more. By creating base configuration files that all applications and libraries extend from, you can enforce agreed-upon best practices across your entire organization. This combined with the advanced CLI tooling and plugins makes building applications at scale more maintainable and consistent.

Nxtend Plugins

Building upon the plugin architecture that Nx provides, Nxtend is a series of plugins that mostly focus on enabling Ionic and Capacitor development in an Nx workspace. These plugins include @nxtend/ionic-react, @nxtend/ionic-angular, @nxtend/capacitor, and more. The main functionality that these plugins provide is the generation of Ionic applications in an Nx workspace that fits the standards of other Nx applications.

While the official documentation is the best place to learn how to use the Nxtend plugins, you can begin developing with them with Nx right away. First, you need to start with an Nx workspace. To generate a new workspace from your terminal or command line, execute:

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

The Nx CLI allows you to generate a new workspace with a React or Angular app pre-configured, but since we are going to add the Nxtend plugins manually, we want to generate our workspace with the --preset=empty option.

Generating Applications

For this example, we will generate an Ionic Angular application that uses Capacitor. (Generating an Ionic Angular application is very similar, and more information on that can be found on the official documentation.)

First, install the Nxtend Ionic Angular dependency to your workspace:

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

From here, initialize the plugin:

nx generate @nxtend/ionic-angular:init

Finally, generate a new application:

nx generate @nxtend/ionic-angular:app my-app

The CLI will prompt you for the Ionic starter template you would like to use, and once the command is complete, you can begin serving your Ionic app:

nx serve my-app

Using Capacitor

Nxtend Ionic applications are generated with Capacitor support by default. However, before we can use Capacitor, we must build our application:

nx build my-app

Next, we can add a Capacitor platform like iOS:

nx run my-app:add:ios

And finally, we can open that app in Xcode:

nx run my-app:open:ios

Capacitor can also be added to any existing web application in an Nx workspace. Learn more about this on the official documentation.

Shared Libraries

The Nxtend Ionic Angular plugins are compatible with Nx Angular libraries, meaning that once a library is generated, you can begin creating components in that library and export them from the index.ts to use them in your applications.

To generate a new Angular library, execute:

nx generate @nrwl/angular:library my-lib

Next, we can generate a component in the new library:

nx generate @nrwl/angular:component MyComponent --project my-lib

Before we can use Ionic components in the new library, we must import the IonicModule and export the new component in libs/my-lib/src/lib/my-lib.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MyComponentComponent } from './my-component/my-component.component';
import { IonicModule } from '@ionic/angular';

@NgModule({
  imports: [CommonModule, IonicModule],
  declarations: [MyComponentComponent],
  exports: [MyComponentComponent],
})
export class MyLibModule {}

Now, we can update the component we generated with Ionic:

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title> Blank </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">Blank</ion-title>
    </ion-toolbar>
  </ion-header>

  <div id="container">
    <h1>Welcome to my-app!</h1>
    <strong>Ready to create an app?</strong>
    <p>
      Start with Ionic
      <a
        target="_blank"
        rel="noopener noreferrer"
        href="https://ionicframework.com/docs/components"
        >UI Components</a
      >
    </p>
  </div>
</ion-content>

And finally, import the module in your app:

import { MyLibModule } from '@my-org/my-lib';

And that’s it! Using this strategy, you can share components, interfaces, utils, and more.

Wrapping Up

Nx is an excellent tool for workspaces, and the plugin architecture opens the door for applications and libraries to feel at home in a monorepo. Developing Ionic apps in an Nx workspace can offer many benefits, and the Nxtend suite of plugins is designed to make that a smooth process. Between generating apps, libs, managing dependencies, as well as the ability to share code across projects, Nx benefits projects both large and small.


Devin Shoemaker