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