React at Scale with Nx

Rate this content
Bookmark

The larger a codebase grows, the more difficult it becomes to maintain. All the informal processes of a small team need to be systematized and supported with tooling as the team grows. Come learn how Nx allows developers to focus their attention more on application code and less on tooling.


We’ll build up a monorepo from scratch, creating a client app and server app that share an API type library. We’ll learn how Nx uses executors and generators to make the developer experience more consistent across projects. We’ll then make our own executors and generators for processes that are unique to our organization. We’ll also explore the growing ecosystem of plugins that allow for the smooth integration of frameworks and libraries.

This workshop has been presented at React Summit 2022, check out the latest edition of this React Conference.

FAQ

React at Scale with NX is a workshop designed to introduce and explore the use of NX in managing React applications at scale. It includes a combination of lectures and hands-on labs to help participants learn how to utilize NX for efficient project management and development.

A monorepo is a repository, usually a Git repository, where you have multiple applications in the same repository. The benefit of coding in this way includes atomic changes, more easily shared code, and a single set of dependencies.

The benefits of using a monorepo include atomic changes where you can immediately see the effects of a change across all applications, easier code sharing across projects, and maintaining a single set of dependencies which simplifies updates and reduces compatibility issues.

NX supports monorepo management by providing tools and features like atomic changes, controlled code sharing, and consistent coding practices. It offers capabilities such as faster command execution, an accurate architecture diagram, and distributed caching through NX Cloud.

NX Cloud is a service that offers distributed caching for NX. It allows organizations to share build and test results across their team, speeding up the development process by reusing the cache generated by others. NX Cloud has a large free tier, making it accessible for most applications.

NX improves build and test speeds using features like affected commands that only operate on changed code, and caching mechanisms which store the results of previous operations. This means subsequent builds or tests that are identical to previous ones can be skipped or pulled from the cache, dramatically reducing time.

Yes, NX can be integrated into existing repositories with minimal disruption. It can be added to work alongside existing tools and configurations, allowing teams to gradually adopt NX features and workflows without the need for a complete overhaul of their project structure.

Isaac Mann
Isaac Mann
Zack DeRose
Zack DeRose
160 min
01 Jul, 2022

Comments

Sign in or register to post your comment.
Video Summary and Transcription
Welcome to React at Scale with NX. NX provides benefits such as faster command execution, controlled code sharing, consistent coding practices, and an accurate architecture diagram. The workshop covers various topics including workspace setup, library creation, code splitting, API integration, and testing with Storybook and Cypress. NX offers functionality such as caching, Nx console, and Nx cloud, and provides a dependency graph for visualizing project dependencies. Troubleshooting tips and workspace generator creation are also discussed.
Available in Español: React a gran escala con Nx

1. Introduction to React at Scale with NX

Short description:

Welcome to React at Scale with NX. In this workshop, we'll introduce you to NX and the benefits of using a monorepo. A monorepo is a repository that contains multiple applications, allowing for atomic changes, easily shared code, and a single set of dependencies. Atomic changes enable you to make a change and see its effects across the entire app immediately. Sharing code becomes easier as you can export and import functions within the monorepo. Having a single set of dependencies ensures that all applications stay up to date and reduces the lag in the development process.

All right, everyone. Welcome to React at Scale with NX. Yeah, let's go. And so my name is Isaac Mann. I am an architect at Narwhal. I've been here for three and a half years. And, Zach, you want to introduce yourself?

Sure, as I find the mute button. I'm Zach Derose. I've been with Narwhal going on four years now. I am a senior engineer and engineering manager, like Isaac, and, yeah, looking forward to sharing this NX knowledge with you all. So, yeah. Yeah. So, yeah, Zach and I joined like two weeks apart. So you can see how like Zach's the optimistic one. So he's almost four years. And I'm saying, well, more than three years. So glass half full, glass half empty. Yeah, I guess so. I'm sorry I didn't hear your spiel because I'm like writing in the chat. But, yeah. That's funny.

Yeah, so we are going to give you an intro to NX today going through a workshop that normally we have this workshop set up for a two day workshop. We're going to be going through a one day of it, the first day. And normally it takes about six hours, but we're going to just try to get through it however much we can in three hours. So basically what that means is we'll be cutting down the space that we'll give you to do things on your own. So I'll be running through things, the lab, and giving you some space for questions. But we're not going to be pausing for 10 minutes at each lab to have you do everything on your own. But the repo is linked in the chat. So if you feel like I'm going too fast, it's there and you can go through it at whatever pace you want when you do it later. A few notes just to, I guess procedural notes. So we want to make sure that this a friendly environment that everyone feels welcome and included. So that includes any life choices that people make and any technical choices that people make. So no shaming people for what they choose to do with their life and no shaming people for what technologies they use at work. So that's right. And we will not shame people for using IE, even though it is being phased out, I think, this week, tomorrow? I don't know. It's a big celebration happening. Yeah, today. All right. OK, anything else and I'm missing, Zach, before we dive in?

Nope, just a reminder, though, to anyone new, I've been saying this a lot, but I'll be in chat. So let's use the Zoom chat if you have any questions as we go. I'll answer things as I can. And if it's appropriate, we'll interrupt Isaac to go over some stuff as he's screen-sharing. So yeah, cool. All right. I'm going to share my screen, and share my full screen here. And we're going to be going through some slides. All right, so this is React at scale with NX Monorepos. And one thing that we should start out with is kind of defining what a monorepo is, and why you'd actually want to use a monorepo. So a monorepo is a repository, usually a Git repository, where you have multiple applications in the same repository. And so the benefit of coding in that way is that you get atomic changes, you get more easily shared code, and you can get a single set of dependencies. So let me back up a little bit. There are two kind of flavors of monorepo that you can get into. There's the Google style monorepo, for lack of a better word, where there's lots of tooling and lots of things to help you share code better. And then there's kind of like the learner style or very light touch, less tooling. And we'll get into that a little bit later with the, I think we call it code co-location sometimes. But NX can help with both. But during this workshop, we're going to be talking about the Google style, which has a single set of dependencies, one package JSON at the root. Whereas the learner style is you've got lots of package JSONS with different dependencies for each application in your repo. So we're going to be focused on that Google style for this workshop. But at the end, we could do a demo of what NX would look like in that in the more learner style of monitor repo. We've got these three things that a monitor repo gives you, atomic changes, shared code, and a single set of dependencies. Now let's go into what each of these things mean. So atomic changes are, say you have an app and a library and your repo. Actually, in this case, we have in two separate repos. So you have the app in a UI library. If you have it in two separate repos, then say you make a change to your library and it breaks some behavior in your application. So the library author makes a change, publishes it. The app developer at some point later updates to the latest version of the library. And they realize, hey, this is broken. We can't use this next version of the library. So they tell the library dev, OK, they file a bug. You need to fix this. And then later on, the library dev comes back and they say, OK, I got to fix that. They make the change. They publish a new version. And then later, the app dev updates to the next version of the library and say, OK, it's finally fixed. So that's the long cycle time if you have them in two separate repos. If they were to be in one repo, then the library dev, when they make the change, they could run the tests for the whole application, the whole repo, and say, oh, wait, this change that I'm about to make, it breaks this other app so I'm going to fix it right now. So you got a cycle time of 45 minutes instead of a week. So that's the benefit of an atomic change. You make one change, and you can see the effects of it immediately across the whole app even before you make a commit. The other second thing is, it's easier to share code. So say you've got a function called username is valid, and this logic is used in lots of different apps, if you have a monorepo, sharing that code is as easy as exporting a function and then importing it somewhere else. And anytime you change that logic, it immediately takes effect across your whole repository. Whereas if you have separate repos, you got to version things and republish them, and you got that whole cycle time, that lag in your development process, just like I said with atomic commits. A third benefit is having a single set of dependencies. So often if you have multiple applications, there's always going to be some applications that you're developing on all the time that are going to be on the latest versions of things. And there are going to be some applications that you just touch occasionally and they always get left behind. And so updating them and moving them forward is a pain because they inevitably, they get six versions behind and you have to remember all the things, all the problems you had to solve for the last year when you were updating things, you have to go back and relive them all over and over again as you're updating this old application. Whereas if you keep everything on the same version, then you just make that change once and you just do it across your whole application.

2. Benefits of NX

Short description:

NX helps with faster command execution, controlled code sharing, consistent coding practices, and an accurate architecture diagram. It eliminates problems with code co-location and provides benefits such as faster command execution, controlled code sharing, consistent coding practices, and an accurate architecture diagram. NX allows for faster command execution, controlled code sharing, consistent coding practices, and an accurate architecture diagram. It addresses the drawbacks of code co-location and provides benefits like faster command execution, controlled code sharing, consistent coding practices, and an accurate architecture diagram.

You say, okay, every time I see this code pattern, I do this fix on it and you do it one time and you're done with it. Whereas instead of having to do it now and then two months from now and then six months from now for all the different applications you're looking at. The other thing that single set of dependencies helps with is if you're doing like a, what is it called? Micro fund-in kind of approach, you have to have things on the same version otherwise you'll get weird bugs with like a React 16 library trying to be injected into a React 17 application and things are confused about what a singleton of a certain instance is or whatever. So having a single set of dependencies just eliminates that whole class of problems.

All right, so Code Co-location is what you would do if you were just to dump multiple applications in the same repo without any tooling around it. You just drop it in and you say, it'll be better, we'll be able to share our code and it'll be nice. But here are the problems with that. The time it takes to run tests will grow exponentially. You have trouble having code boundaries and keeping things contained and not have spaghetti code. And then you'll have inconsistent tooling when you're trying to manage your code base. So running unnecessary tests.

So let's say you have a homepage that depends on a UI library. If you were to change the homepage then you only need to run the test for the homepage. You don't need to run the test for the UI library because there's no way a change to the homepage could break the UI library cause that's just the way the dependency goes. But if you don't have the tooling that understands that you won't know which tests you have to run. So you end up, just running the tests for everything anytime you make any change. And that makes the time your CI takes grow exponentially with the number of things you add in because every app you add just adds more tests that you have to run no matter where that change is made. Even if you're making changes to one app that has no dependency on the other you have to run the test for everything just to make sure that you didn't break something by accident.

And obviously this is a very small example. You could tell just by looking at it if you need to run tests for something or not. But your dependency graph is gonna look more, something like this, this is even a really small repository. Any moderately sized company you'll have hundreds of nodes in this graph once you get working on things. So at that point you can't just know as a person just by understanding the code to know what tests really need to run, you need to have some tooling that will do that for you. So you need to know that when you change the CartPage library, you need to know that the tooling can tell you that you need to test the Cart app and then the Cart End-to-End app because those are the things above it that depend on it. All right. You want to have code boundaries. So let's say you have something in your library that you only want to use internally to that library or you know that it's going to change and you don't want other people in other parts of the code base to be using this. So you could do things like, I know React does this sometimes, they have unstable or they prefix the names of things with warning messages to people to say, hey, don't actually use this, it's your own fault if you use this, this is going to change, it's going to break your code. And just to get people to not depend on things that aren't meant for public consumption. Whereas, so, you know, that's a problem with having code that's shared that way. Whereas if you have tooling that blocks you from making these deep imports, you can stop this problem before it even happens.

All right, the other thing is inconsistent tooling. So if you have lots of applications in your repo, you get the ballooning NPM scripts. And the format of those NPM scripts is based on the whim of the developer at the moment that they wrote it. Because they're always gonna have some random flag that nobody knows or expects. And you just don't even know how to do different things. So one application could be build. One application could be dev. One application could be a launch. And they all do the same thing, but if you're switching from one application to another, you have no way of knowing how to get going on it. There's no consistency in those scripts.

All right, so NX can help you to get the benefits of the Monorepo style of coding without the drawbacks of code co-location. So it helps by giving you faster command execution, controlled code sharing, consistent coding practices, and an accurate architecture diagram. So things that help with faster command execution, if you use Executors, which are basically like NPM scripts, but in a more structured NPM scripts basically. So there's tooling around them that helps you get like auto-completion and get some like graphical. So there's NX console that lets you like visually fill out all the options that are available. So the second thing is NX affected, helps you run the tests on things that are actually affected by a PR. So you can run tests or builds or any command only on the code that's affected by your change. So that speeds up your CI and your local development and you get local and distributed caching. So if you run a command a second time on the same code without changing the code, it's gonna be almost instant. It's gonna pull from the cache instead of running the command again. And then you can use distributed caching, which allows you to share that cache across your whole organization. So that's NX Cloud and it's a paid product. Although there's a large free tier for NX Cloud. So most applications it's just free. It's so when it get to a giant companies you have to pay some.

You get controlled code sharing with NX. You can have a defined API for your library and say, hey, if anyone's gonna use this library, these are the things you're allowed to use. If you try to reach into something I didn't explicitly export in this defining the API then it's gonna throw an error and you're not gonna, your code won't compile. You can set up tags to say which libraries and applications are allowed to depend on each other and say, these belong to this team and this whole set of projects belong to this team and they can't interact with each other. They can only depend on shared things. You can easily publish libraries to NPM and you can use something like the Code Owners file in GitHub, which requires an approval from a certain set of people for changes to a particular project, particular section in your repo.

NX also allows you to have consistent coding practices. There's linting, lint rules that help you determine which things depend on which other things and enforcing those defined APIs and libraries. Generators are basically scripts that allow you to create or modify code. There's special kind of generators called migration generators that update your code when you update versions. If you go from React 16 to 17, there's a migration generator that updates your config files to make sure that your code stays up to date along when you're updating your framework as well. So, NARL has a set of plugins that support different frameworks and tools, so, Angular, React, Express, Nest, Next, Cypress, Storybook, things like that. And then, there are also, so those plugins do things like set up your configuration for those tools, and they have the migration scripts to help you stay up to date as the version numbers bump up. And then community plugins, so things that NARL does not have out-of-the-box support for. There's a community where people write their own plugins for things like Vue and other things, and you can use those community plugins to help enforce those consistent coding practices.

All right, another thing that NX gives you is an accurate architecture diagram. So if you run NX graph on a repo that has NX installed, you can see what the actual code structure is of your repository, not what you wish it was or not what it was six months ago, which is usually what our architecture diagram is. It's what the code actually is right now and how the different parts of your code actually depend on each other. And so this is really used and this is a picture of an old version of the NX graph. We'll get into the common more up-to-date one, which it's a lot nicer. You can zoom in more and you can hover over it and see how different things are depending on each other. It's really useful. This is one of the, I don't know. One of my favorite features of NX is this dependency graph.

Okay, so this is how NX structures your repository by default. So if you go the lightweight NX setup, you can have it structured however you feel like. This is just the default. If you go all in with NX and you say, hey, NX, structure my repository for me, then this is what NX will do. But if you want to do the lighter weight version, then you can just add NX to your existing repo and not change your structure at all. But so we'll go through this one with the all in for NX setup. And then maybe at the end, I can show you how to use NX in a repo that's structured differently. All right, so NX has a, by default has an apps folder and a libs folder. So apps are anything that's like the, has an entry point basically, it can be deployed somewhere.

QnA

Watch more workshops on topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Hooks Tips Only the Pros Know
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React, TypeScript, and TDD
React Advanced 2021React Advanced 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
Master JavaScript Patterns
JSNation 2024JSNation 2024
145 min
Master JavaScript Patterns
Top Content
Featured Workshop
Adrian Hajdin
Adrian Hajdin
During this workshop, participants will review the essential JavaScript patterns that every developer should know. Through hands-on exercises, real-world examples, and interactive discussions, attendees will deepen their understanding of best practices for organizing code, solving common challenges, and designing scalable architectures. By the end of the workshop, participants will gain newfound confidence in their ability to write high-quality JavaScript code that stands the test of time.
Points Covered:
1. Introduction to JavaScript Patterns2. Foundational Patterns3. Object Creation Patterns4. Behavioral Patterns5. Architectural Patterns6. Hands-On Exercises and Case Studies
How It Will Help Developers:
- Gain a deep understanding of JavaScript patterns and their applications in real-world scenarios- Learn best practices for organizing code, solving common challenges, and designing scalable architectures- Enhance problem-solving skills and code readability- Improve collaboration and communication within development teams- Accelerate career growth and opportunities for advancement in the software industry
React at Scale with Nx
React Summit 2023React Summit 2023
145 min
React at Scale with Nx
Top Content
Featured WorkshopFree
Isaac Mann
Isaac Mann
We're going to be using Nx and some its plugins to accelerate the development of this app.
Some of the things you'll learn:- Generating a pristine Nx workspace- Generating frontend React apps and backend APIs inside your workspace, with pre-configured proxies- Creating shared libs for re-using code- Generating new routed components with all the routes pre-configured by Nx and ready to go- How to organize code in a monorepo- Easily move libs around your folder structure- Creating Storybook stories and e2e Cypress tests for your components
Table of contents: - Lab 1 - Generate an empty workspace- Lab 2 - Generate a React app- Lab 3 - Executors- Lab 3.1 - Migrations- Lab 4 - Generate a component lib- Lab 5 - Generate a utility lib- Lab 6 - Generate a route lib- Lab 7 - Add an Express API- Lab 8 - Displaying a full game in the routed game-detail component- Lab 9 - Generate a type lib that the API and frontend can share- Lab 10 - Generate Storybook stories for the shared ui component- Lab 11 - E2E test the shared component

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Don't Solve Problems, Eliminate Them
React Advanced 2021React Advanced 2021
39 min
Don't Solve Problems, Eliminate Them
Top Content
Kent C. Dodds discusses the concept of problem elimination rather than just problem-solving. He introduces the idea of a problem tree and the importance of avoiding creating solutions prematurely. Kent uses examples like Tesla's electric engine and Remix framework to illustrate the benefits of problem elimination. He emphasizes the value of trade-offs and taking the easier path, as well as the need to constantly re-evaluate and change approaches to eliminate problems.
Using useEffect Effectively
React Advanced 2022React Advanced 2022
30 min
Using useEffect Effectively
Top Content
Today's Talk explores the use of the useEffect hook in React development, covering topics such as fetching data, handling race conditions and cleanup, and optimizing performance. It also discusses the correct use of useEffect in React 18, the distinction between Activity Effects and Action Effects, and the potential misuse of useEffect. The Talk highlights the benefits of using useQuery or SWR for data fetching, the problems with using useEffect for initializing global singletons, and the use of state machines for handling effects. The speaker also recommends exploring the beta React docs and using tools like the stately.ai editor for visualizing state machines.
Design Systems: Walking the Line Between Flexibility and Consistency
React Advanced 2021React Advanced 2021
47 min
Design Systems: Walking the Line Between Flexibility and Consistency
Top Content
The Talk discusses the balance between flexibility and consistency in design systems. It explores the API design of the ActionList component and the customization options it offers. The use of component-based APIs and composability is emphasized for flexibility and customization. The Talk also touches on the ActionMenu component and the concept of building for people. The Q&A session covers topics such as component inclusion in design systems, API complexity, and the decision between creating a custom design system or using a component library.
React Concurrency, Explained
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
Watch video: React Concurrency, Explained
React 18's concurrent rendering, specifically the useTransition hook, optimizes app performance by allowing non-urgent updates to be processed without freezing the UI. However, there are drawbacks such as longer processing time for non-urgent updates and increased CPU usage. The useTransition hook works similarly to throttling or bouncing, making it useful for addressing performance issues caused by multiple small components. Libraries like React Query may require the use of alternative APIs to handle urgent and non-urgent updates effectively.
Managing React State: 10 Years of Lessons Learned
React Day Berlin 2023React Day Berlin 2023
16 min
Managing React State: 10 Years of Lessons Learned
Top Content
Watch video: Managing React State: 10 Years of Lessons Learned
This Talk focuses on effective React state management and lessons learned over the past 10 years. Key points include separating related state, utilizing UseReducer for protecting state and updating multiple pieces of state simultaneously, avoiding unnecessary state syncing with useEffect, using abstractions like React Query or SWR for fetching data, simplifying state management with custom hooks, and leveraging refs and third-party libraries for managing state. Additional resources and services are also provided for further learning and support.
Levelling up Monorepos with npm Workspaces
DevOps.js Conf 2022DevOps.js Conf 2022
33 min
Levelling up Monorepos with npm Workspaces
Top Content
NPM workspaces help manage multiple nested packages within a single top-level package, improving since the release of NPM CLI 7.0. You can easily add dependencies to workspaces and handle duplications. Running scripts and orchestration in a monorepo is made easier with NPM workspaces. The npm pkg command is useful for setting and retrieving keys and values from package.json files. NPM workspaces offer benefits compared to Lerna and future plans include better workspace linking and adding missing features.