DEV Community

Cover image for Angular with Nx in 2023? Seriously, You Should!
Daniel Glejzner for This is Angular

Posted on • Updated on

Angular with Nx in 2023? Seriously, You Should!

By MidJourney AI

Honestly, it’s hard for me see why you wouldn’t want to use Nx for your Angular application. And no, you don’t need a monorepo. Let me break it down for you.

A lot of people find it tough to set up a folder structure and app architecture that’s easy to use, can grow over time, and can be managed by a big team. This is tough for polyrepos and even tougher for monorepos. But whether you’re working with a polyrepo or a monorepo, Nx can help you out.

Briefly — What is Nx?

Nx is a powerful open-source build system that provides tools and techniques for enhancing developer productivity, optimizing CI performance, and maintaining code quality. — Nx docs.

I pulled this straight from the official documents. To me, Nx is like a trusty foundation stone for any Angular app architecture. I’ve built a ton of apps using Nx — and let me tell you, it’s like having a helpful buddy along the way.

Nx nudges you into:

  • Structuring your codebase into well-defined modules for better manageability

  • Ensuring a consistent setup through the systematic use of code generation

  • Avoiding the potential pitfalls of messy dependencies that could compromise the maintainability of your code

  • Helping you automatically visualize your structure through dependency graph and much much more.

While Nx lays the groundwork for success, it doesn’t promise a win. It’s still up to you to stick with the best practices, pick a method that’s proven in battle (like DDD or FDD), and define *module boundaries, and so on.

Once you’ve got everything set up just right, adding new features and growing your app is a piece of cake. But let’s start with a first step.

By MidJourney AI

The Big Decision

Software projects can be big, small, simple, complex, and have different team setups. So, deciding how to set up your project really depends on a few things like how big your team is, how many apps you’re building, the size of your codebase, and how much code you’re sharing between projects.

Choosing between a polyrepo and a monorepo is a big decision and it’s something your team should sit down and chat about with your lead or architect. It’ll be even better if that person knows their way around Angular applications, team setups, workflows, and all those high-level bits and pieces.

By MidJourney AI

Nx Specific Approach

Now let’s compare Nx monorepo approach vs Nx non-monorepo approach with example of Angular app.

With Nx — In both cases you have to create your features as libraries. Don’t get discouraged by this step. Having things as libs allow Nx to do it’s magic and for you it’s almost the same as simple directories.

Our application will have two libraries, Tasks for task-related functionalities, and Users for user-related functionalities.

By MidJourney AI

Nx Monorepo Setup

Monorepo Approach

Monorepo approach is basically putting all closely related projects into one big box — a single repository.

Sounds scary, isn’t it? That’s why a lot of people immediately disregard Nx — because they think its for monorepo only. It’s not. But I will explain that later — for now let’s focus on monorepo.

Key Steps and Differences:

  1. Creating the workspace: An Nx workspace is created with npx create-nx-workspace@latest — preset=angular-monorepo

  2. Creating the application: We generate an Angular application inside the workspace using npx nx generate @nrwl/angular:app task-manager.

  3. Generating libraries: npx nx g @nx/angular:library tasks, npx nx g @nx/angular:library users

  4. Dependency management: In a monorepo, all apps and libraries share the same node_modules, simplifying dependency management.

  5. Building the application: The command npx nx build task-manager builds the application. Due to Nx's advanced computation caching, build times can be significantly reduced in a monorepo setup. It’s only going to build the part of app that you made changes for.

    task-management/
    ├── apps/
    │   ├── task-manager/
    │   │   ├── src/
    │   │   │   ├── app/
    │   │   │   ├── main.ts
    │   │   │   ├── index.html
    │   │   │   ├── ...
    │   │   ├── angular.json
    │   │   ├── ...
    │   ├── task-manager-e2e/
    │   │   ├── ...
    ├── libs/
    │   ├── tasks/
    │   │   ├── src/
    │   │   │   ├── lib/
    │   │   │   ├── index.ts
    │   │   │   ├── ...
    │   │   ├── ...
    │   ├── users/
    │   │   ├── src/
    │   │   │   ├── lib/
    │   │   │   ├── index.ts
    │   │   │   ├── ...
    │   │   ├── ...
    ├── node_modules/
    ├── package.json
    ├── nx.json
    ├── project.json
    ├── ...
Enter fullscreen mode Exit fullscreen mode

Here, all applications are stored under the apps/ directory, while libraries are stored under the libs/ directory. They share the same node_modules/ directory, which houses dependencies for the entire workspace.

Pros:

  • Code Sharing: Monorepo allows seamless code sharing across different applications and libraries. This can significantly reduce code duplication in projects with multiple apps sharing common functionality. It’s all there in one repository which makes your IDE aware of literally everything. No more NPM packages to worry about.

  • Atomic Changes: Changes across multiple projects can be committed all at once (it’s just a “git branch”), making it easier to track. Nx is smart enough to only build/test what has been affected by your change. So for example only 2 out of 20 apps & 5 out of 100 libs.

  • Unified Build & Test Setup: With all projects in the same place, you can build, test, and release them all together. Setting up and keeping integration tests running smoothly is easier when all projects are under the same roof.

  • Simplified Dependency Management: All your projects share the same dependencies. In theory there is a way to have multiple different versions — however Nx team strictly encourages single-version policy. So, there’s only one package.json file you need to worry about. It also enforces keeping everything in sync. You have to do more work across all of the apps to make sure everything is working fine after updates — which in the end is good for the project.

  • Code Consistency: It’s simpler to make sure everyone is playing by the same rules when all your projects are in one place. You can designate ownership of certain apps/parts to teams/people in your organization. You enable easy way to onboard new developers — they can utilize code generators and you make sure the structure is always as expected.

  • Streamlined Onboarding: It’s easier for new developers to get started when everything’s located in one place.

Monorepo isn’t perfect either. Here are a few things to watch out for:

Cons:

  • Scalability: As your codebase expands, the time it takes to build and test might also grow. That said, Nx does a solid job in tackling this with its computation caching and affected commands. However — large codebases can still lead to slower IDE performance and longer test, build, and CI times.

  • Increased Complexity: A monorepo can get complex, especially with large codebases and teams. You need to be very strict and have the rules set right to keep order easily.

  • Merge Conflicts: With multiple teams working on different applications in the same repository, the potential for merge conflicts increases.

  • Read Access Control: In the world of Monorepo, everyone typically gets read access to everything. There is no easy way to restrict read access to specific projects. This might not be the best fit if you need more control over who gets to touch what.

  • Code Reviews: With potentially larger scopes of changes, code reviews might feel overwhelming. You can potentially solve this issue assigning the “codeowners” to certain parts.

By MidJourney AI

Nx Non-monorepo Setup

Polyrepo Approach

Let’s talk about the Polyrepo Approach. Here, each project gets its own personal space — its own separate repository. If you’re a big organization, you might have to juggle between 10–20 separate repositories.

Key Steps and Differences:

  1. Creating the workspace: When creating an Nx workspace for a standalone setup, we use npx create-nx-workspace@latest, select Standalone Application, and name the application task-manager.

  2. Generating libraries: npx nx g @nx/angular:library tasks, npx nx g @nx/angular:library users

  3. Building the application: The command npx nx build task-manager builds the application. The computation caching in Nx also works in a standalone setup but has less impact since there's only one app.

    task-manager/
    ├── src/
    │   ├── app/
    │   ├── main.ts
    │   ├── index.html
    │   ├── ...
    ├── libs/
    │   ├── tasks/
    │   │   ├── src/
    │   │   │   ├── lib/
    │   │   │   ├── index.ts
    │   │   │   ├── ...
    │   │   ├── ...
    │   ├── users/
    │   │   ├── src/
    │   │   │   ├── lib/
    │   │   │   ├── index.ts
    │   │   │   ├── ...
    │   │   ├── ...
    ├── node_modules/
    ├── project.json
    ├── nx.json
    ├── package.json
    ├── ...
Enter fullscreen mode Exit fullscreen mode

Here, the structure is simpler. The application and its source files are at the root of the project. Libraries are still present in a libs/ directory — but you can name that directory however you like. You can also have multiple libs directories.

With non-monorepo appraoch you still get all of that out of the box:

  • Ready to go Angular application at the root of the Nx workspace (src/app)
  • Cypress based e2e test (e2e/)
  • Prettier preconfigured
  • ESLint preconfigured
  • Jest preconfigured

Pros:

  • Simplified Project Structure: Standalone setup has a simpler project structure, making it easier for smaller teams or for those just starting with Nx. One repository equals one project, making it easier to understand and find your way around the codebase.

  • Isolation: Standalone setup keeps applications isolated from each other. It’s beneficial when the apps don’t have much in common or when strict isolation between them is required. Each repository is its own island, encouraging you to write code that stands alone, which can lead to higher quality code.

  • Specific Configurations: Standalone applications can have their own specific configurations, providing flexibility when different apps have differing requirements.

  • Controlled Read Access: You get to decide who gets in and who doesn’t. This means you can limit read access to certain apps or parts of your codebase, making Polyrepos a good choice if different teams or people need different levels of read access.

  • Manageable Code Reviews: Code reviews are less of a headache, as changes are usually tucked away in specific repositories.

But, polyrepos are not perfect. There can be some bumps along the way.

Cons:

  • Code Duplication: Sharing code between projects can turn into a copy-paste festival if you’re not careful. Or you can end up maintaining 10 NPM packages across your apps and struggle with keeping everything up to date with latest versions. Standalone setups do not facilitate code sharing as efficiently as monorepos, making them less suitable for projects with multiple apps that share significant functionality.

  • Multiple Build Configurations: If you have multiple standalone applications, each may require a separate build configuration.

  • Dependency Management: This can get a bit tricky. Each project has its own package.json file, and you might end up with different versions of third-party dependencies across projects.

  • Coordinating Changes: Making changes that affect several projects at once can be overwhelming. A single feature or bug fix could need changes in a few different repositories.

  • Tricky Integration Tests: Setting up and keeping integration tests running smoothly across different repositories can be more of a hassle compared to a monorepo setup.

Go with Nx

Choosing between a monorepo and a non-monorepo (polyrepo) setup really comes down to what your project needs. If you’ve got a big project with a lot of shared stuff, a monorepo could be a good fit. But if your project is smaller or needs to keep things separate, have better control of read access restrictions, then a standalone setup might be the way to go.

Both have their pros and cons — but as mentioned before. Doesn’t matter which one you pick. Nx has something in store for you for both options.

I cannot see any reason not to start Angular project without Nx as companion. For monorepo or polyrepo approach.


I hope you liked my article!

If you did you might also like what I am doing on Twitter. I am hosting live Twitter Spaces about Angular with GDEs & industry experts! You can participate live, ask your questions or watch replays in a form of short clips :)

If you are interested drop me a follow on Twitter @DanielGlejzner — would mean a lot :). Thank You!

Top comments (1)

Collapse
 
fyodorio profile image
Fyodor

The cons are real, so real 🥲 wouldn’t recommend nx without a serious need for the tools. Think about the future, at least if you don’t like pain.