An important part of maintenance work is also to follow along with new releases of packages you depend on. That way you get important bug fixes as well as new improvements and features. Similarly also in an Nx workspace. However, performing updates might be cumbersome, especially if breaking changes are involved.
Nx comes with a special mechanism to take away that burden of updating an Nx workspace:
nx migrate. In this lesson, we're going to use the Nx migrate command to update our Nx 10 workspace to v11.
Instructor: [0:00] Here we have our Nx workspace with a couple of applications in here. As you start developing yours by teams, over time you might come to the point where you need to update packages, or even just update Nx itself.
[0:13] I'm talking basically about the versions which we have here in our package.json. Here we have things to setup, like the actual frameworks we're using, such as React, or Angular, or whatever, but also like those @nrwl/packages which are the Nx packages.
[0:30] Obviously, as you stay closer to the latest versions of, for instance, Nx, you might get more benefits, because you get new features, you get new bug fixes. Overall, your developing experience is much better.
[0:42] On the other side, upgrades in general might be potentially problematic. If it's just like updating minor package versions, it's usually not a big deal. But if you're breaking changes, you might have to understand how to fix the config files, maybe just get updated, the config file changed, and you have to figure out how to change your config files, rewrite them. It's quite a time-intensive process.
[1:07] Nx is here to help with that, as well. There is a command called Nx migrate latest. With it you get semi-automatic migration command that will update your package.json versions, but also the underlying code, which means config files or even source code, if needed.
[1:24] Let's see how that works. First, I'm going to open up your console, and I'm running that Nx migrate latest command. What that does is it analyzes all the dependencies in your workspace. Here, for instance, you can see it starts with the nrwl packages, it goes and grabs the latest package, and then writes that new version number into the package.json.
[1:48] At the same time, it also analyzes the migrations that need to be done and will generate the migrations.json file, which has pointers to the various scripts that need to be executed, which then will change underlying code base for you. We'll have a look at that in a second.
[2:04] Once this process completes successfully, you can see that the package.json has been updated, as well as a new migrations.json has been generated. Let's have a look, first of all, into the package.json.
[2:14] The best is if you go to the git diff. You can see then that the actual versions of the Nx packages have been changed from 10-something to 11. Even further down, things like babel-jest have been updated, as well as ESLint, and so on.
[2:32] These versions have just been written into the package.json, but it don't have actually being installed. In fact, the suggested next steps here is to make sure that the package.json contains things that make sense.
[2:40] We actually go and have a look at the babel-jest, and if we don't want to upgrade, we change that here. Once you are sure that these are the changes which we want, we can just have npm install them or yarn install them. I do just yarn, hit Enter. Now, all these packages will be installed.
[3:03] Meanwhile, we can scroll up a bit, and the next step we choose should do after installation is to run the migrations. For that sake, I'm just copying that piece of command. Once the packages are installed, we can also do a git status and see that the yarn.lock has now been updated to the new package version. Now I can run the migrations.
[3:27] The migrations grid lies at the root. It has been generated here. Here, we can see this is just like a structured file which contains a version, a description of the script of what this grid does, and then it points to the actual source code that we can execute.
[3:43] There are a series of them in here, depending on what package I have installed in my workspace, or what version I'm using, whether I'm using React or whether I'm using Angular. It might also contain migrations for Angular itself.
[3:57] Let's run the migrations. I just do yarns, Nx migrate, run migrations, and give it a path to the file. Now you can see how the migrations have been executed.
[4:13] We see now that we have lots more changes. For instance, we see that eslintrc files have been renamed to @.json extensions. We also see further down, there are some just config changes. You can see how, for instance, that has been refactored. These are changes you get for free, but which might improve your performance of the next workspace by a lot.
[4:37] At this point, we are done. We could go and commit all these changes and push them up to our remote repository. There might be one question, however. We have this new migration.json file here. This hasn't really been executed, and so in theory, we could just delete it and we are done.
[4:56] However, this file is here on purpose. Nx wants to make sure that such a migration process also works with lots of teams and on a big scale. If you work with lots of teams on the same mono repository, what might happen is that at the point when you have upgraded the Nx workspace and pushed it up to be merged into master, there might be lots and lots of other MRs already open that also want to be merged.
[5:21] However, they didn't execute the migrations. They, for instance, still have the old eslintrc files and would never get that migration done.
[5:31] What you can do in such a case is you can commit this migration.json with your upgrade in such that this lends them into your main or master branch, or your teams just rebase as they usually do to get a latest version. Then, they can execute that migration command again and would then also upgrade their specific version of the workspace at that specific moment in time.
[5:55] As a result, they will also run the same migrations. They will get the same updated, or even if they have to potentially generate new libraries, those would also be upgraded which in this case we would simply miss.
[6:08] Once they are ready, they can migrate in. The whole process will be much smoother, and it would result in much less merge failures due to migrations or code changes that have happened in between.