<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Juri Strumpflohner</title>
    <description>The latest articles on Forem by Juri Strumpflohner (@juristr).</description>
    <link>https://forem.com/juristr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F149479%2F2951f479-1bfc-45de-8fdd-46eca0930856.JPG</url>
      <title>Forem: Juri Strumpflohner</title>
      <link>https://forem.com/juristr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/juristr"/>
    <language>en</language>
    <item>
      <title>Versioning and Releasing Packages in a Monorepo</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Fri, 09 Feb 2024 18:49:59 +0000</pubDate>
      <link>https://forem.com/nx/versioning-and-releasing-packages-in-a-monorepo-31pk</link>
      <guid>https://forem.com/nx/versioning-and-releasing-packages-in-a-monorepo-31pk</guid>
      <description>&lt;p&gt;When it comes to publishing NPM packages, there are a bunch of libraries and utilities out there that help with the process. Many of them are tricky when it comes to properly configuring them in a monorepo.&lt;/p&gt;

&lt;p&gt;Nx already has all that knowledge. About project dependencies and relationships and leverages that information already for optimizing your task runs. &lt;/p&gt;

&lt;p&gt;Here's the structure of our current example workspace we're going to refer to in this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkcw9c2nv77nxr17dwll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkcw9c2nv77nxr17dwll.png" alt="Workspace structure" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see &lt;code&gt;@tuskdesign/forms&lt;/code&gt; relies on &lt;code&gt;@tuskdesign/buttons&lt;/code&gt; and as such has to consider that when running versioning and publishing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note, it is worth mentioning that the Nx community has also stepped up in the past and created &lt;a href="https://github.com/jscutlery/semver" rel="noopener noreferrer"&gt;jscutlery/semver&lt;/a&gt;, a package that adds semantic versioning and publishing to your Nx workspace. Make sure to check that out as well&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Prefer a video?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KjZKFGu3_9I"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Adding Nx

&lt;ul&gt;
&lt;li&gt;Installing the JavaScript/TypeScript versioning Package&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Running Nx Release&lt;/li&gt;

&lt;li&gt;Excluding Packages&lt;/li&gt;

&lt;li&gt;Running the Versioning and Changelog Generation&lt;/li&gt;

&lt;li&gt;Versioning using Conventional Commits&lt;/li&gt;

&lt;li&gt;Generating a GitHub Release&lt;/li&gt;

&lt;li&gt;Programmatic Mode&lt;/li&gt;

&lt;li&gt;Wrapping Up&lt;/li&gt;

&lt;li&gt;Learn more&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Adding Nx
&lt;/h2&gt;

&lt;p&gt;You can add Nx to your existing monorepo workspace using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm dlx nx@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(use &lt;code&gt;npx nx@latest init&lt;/code&gt; in a NPM workspace)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This brings up a couple of questions. It'll also ask about installing &lt;a href="https://dev.to/nx/what-if-nx-plugins-were-more-like-vscode-extensions-4oh0"&gt;Project Crystal plugins&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgps8q05mmxgag60jyqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgps8q05mmxgag60jyqv.png" alt="Running nx init on pnpm workspace" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It gives you some additional benefits (you can &lt;a href="https://dev.to/nx/what-if-nx-plugins-were-more-like-vscode-extensions-4oh0"&gt;read more here&lt;/a&gt;), but you don't have to as it is &lt;strong&gt;not required for Nx Release&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the JavaScript/TypeScript versioning Package
&lt;/h3&gt;

&lt;p&gt;Nx Release is made to handle the versioning and publishing of any package. For now, the Nx team provides the JS/TS package publishing approach, which comes with the &lt;code&gt;@nx/js&lt;/code&gt;. You could provide your own implementation, like for Cargo, NuGet etc..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm add @nx/js -w
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(We use the &lt;code&gt;-w&lt;/code&gt; flag to install it at the monorepo root level)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Nx Release
&lt;/h2&gt;

&lt;p&gt;Once you're set-up, you can already go ahead and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm nx release --dry-run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will do the versioning, changelog generation, and publishing steps together. Note the &lt;code&gt;--dry-run&lt;/code&gt;, simply simulating a run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F073b7a91nj3hdc16ohoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F073b7a91nj3hdc16ohoh.png" alt="Nx Release First Run" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll get asked whether you want to release a major, pre-major, minor... release or choose an exact version. &lt;/p&gt;

&lt;p&gt;Once this runs through, you might hit the following error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcveo4g9sxsm427muzbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcveo4g9sxsm427muzbv.png" alt="First run error" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since Nx Release has never been run on this repository, it cannot figure out the historical information, for instance, to generate the changelog starting from previous git tags. Re-run the command with &lt;code&gt;--first-release&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm nx release --dry-run --first-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you inspect the console output, you can see that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it would increment the version in the &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;update the pnpm (or npm) lockfile&lt;/li&gt;
&lt;li&gt;stage the changes with git&lt;/li&gt;
&lt;li&gt;creates a &lt;code&gt;CHANGELOG.md&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;git commits everything&lt;/li&gt;
&lt;li&gt;git tags the commit using the version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dry-run mode also nicely previews all &lt;code&gt;package.json&lt;/code&gt; changes in a git diff style:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuxmiadceh5wmrbtyasn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuxmiadceh5wmrbtyasn.png" alt="Preview release changes" width="800" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note, if you want to get even more insights into what is happening when running the command, you can use the &lt;code&gt;--verbose&lt;/code&gt;, which will also print the actual git commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Excluding Packages
&lt;/h2&gt;

&lt;p&gt;If you look closely at the dry-run logs, you may notice that Nx Release bumped the version on all of our packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@tuskdesign/forms&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tuskdesign/buttons&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tuskdesign/demo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfyn06sfssr1mg7kdtwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfyn06sfssr1mg7kdtwz.png" alt="Exclude packages from releasing" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While we want to have it bumped on the &lt;code&gt;forms&lt;/code&gt; and &lt;code&gt;buttons&lt;/code&gt; packages, the &lt;code&gt;demo&lt;/code&gt; is just for us to test things in the workspace. In this particular workspace, Nx Release doesn't have a way to distinguish what is an app and what is a library/package. Note, if you're in an Nx-generated workspace that uses Nx Plugins, you'd potentially have that classification in the &lt;code&gt;project.json&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;In our particular scenario, let's exclude &lt;code&gt;@tuskdesign/demo&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;nx.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!@tuskdesign/demo"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also explicitly list the packages to be released individually. Or, as shown above, include all (&lt;code&gt;*&lt;/code&gt;) and exclude the private package.&lt;/p&gt;

&lt;p&gt;If you re-run the &lt;code&gt;nx release&lt;/code&gt; command, you'll see that &lt;code&gt;@tuskdesign/demo&lt;/code&gt; will be ignored now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Versioning and Changelog Generation
&lt;/h2&gt;

&lt;p&gt;Once you have configured the excluded packages, feel free to go ahead and run the command without &lt;code&gt;--dry-run&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm nx release --first-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can skip the release part when prompted for now. Check how the workspace got updated, incrementing the &lt;code&gt;package.json&lt;/code&gt; version property and updating the version on the package dependency definition, i.e. the &lt;code&gt;@tuskdesign/buttons&lt;/code&gt; version got updated in the &lt;code&gt;@tuskdesign/forms&lt;/code&gt; package.json.&lt;/p&gt;

&lt;h2&gt;
  
  
  Versioning using Conventional Commits
&lt;/h2&gt;

&lt;p&gt;Instead of manually confirming the next version each time, we can use a versioning strategy: &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt; is a commonly adopted approach for publishing packages.&lt;/p&gt;

&lt;p&gt;To configure conventional commits with Nx Release, go to the &lt;code&gt;nx.json&lt;/code&gt; and adjust it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;nx.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!@tuskdesign/demo"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"conventionalCommits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now run..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm nx release --dry-run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;..you'll notice that it doesn't pick up any changes because it leverages conventional commit, and we haven't changed anything yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2aurlmjjtcqtnynwxfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2aurlmjjtcqtnynwxfj.png" alt="No Changes" width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's go ahead and change something in our &lt;code&gt;@tuskdesign/buttons&lt;/code&gt; package and then commit it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -am 'feat(buttons): add new background shadow'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now re-run the &lt;code&gt;nx release&lt;/code&gt; command (don't forget the &lt;code&gt;--dry-run&lt;/code&gt;). You'll see how it chooses &lt;code&gt;v1.2.0&lt;/code&gt; as our new version (we had &lt;code&gt;v1.1.0&lt;/code&gt; previously), given we added a new feature (denoted by the &lt;code&gt;feat(...)&lt;/code&gt; conventional commit).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9w13fr5drqoyudglxu6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9w13fr5drqoyudglxu6o.png" alt="Releasing 1.2" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also generates a nice &lt;code&gt;CHANGELOG.md&lt;/code&gt; for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## 1.2.0 (2024-02-09)&lt;/span&gt;

&lt;span class="gu"&gt;### 🚀 Features&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**buttons:**&lt;/span&gt; add new background shadow

&lt;span class="gu"&gt;### ❤️  Thank You&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Juri

&lt;span class="gu"&gt;## 1.1.0 (2024-02-09)&lt;/span&gt;

This was a version bump only, there were no code changes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating a GitHub Release
&lt;/h2&gt;

&lt;p&gt;Instead of just generating a &lt;code&gt;CHANGELOG.md&lt;/code&gt; entry in our repository you can also opt-in for creating a Github release (here's the example of the &lt;a href="https://github.com/nrwl/nx/releases" rel="noopener noreferrer"&gt;Nx repository&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;createRelease&lt;/code&gt; property and set it to &lt;code&gt;github&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;nx.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!@tuskdesign/demo"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"conventionalCommits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"changelog"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"workspaceChangelog"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"createRelease"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see the working, you need to make sure to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;push the repo to GitHub &lt;/li&gt;
&lt;li&gt;make some change so you can run the &lt;code&gt;nx release&lt;/code&gt; command again and get a changelog generated&lt;/li&gt;
&lt;li&gt;now also get a GH release created&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note, you can still use &lt;code&gt;--dry-run&lt;/code&gt; and it'd show you the URL where the GitHub release would be created. You can also use the &lt;code&gt;--skip-publish&lt;/code&gt; to skip the NPM publishing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programmatic Mode
&lt;/h2&gt;

&lt;p&gt;As you've seen, you can use &lt;code&gt;nx release&lt;/code&gt; right away with minimal configuration. However, we are very well aware that many real-world scenarios are more complex, you want/need more control over when the version is happening, when the changelog generation kicks in and so on. This is why we also introduced a &lt;strong&gt;programmatic API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This approach gives you full control to embed Nx Release into your current release flow. There's a nice example script &lt;a href="https://nx.dev/features/manage-releases#using-the-programmatic-api-for-nx-release" rel="noopener noreferrer"&gt;on our docs&lt;/a&gt; that can help you get started.&lt;/p&gt;

&lt;p&gt;Create a file - I call it &lt;code&gt;release.ts&lt;/code&gt; - at the root of my workspace. Nx Release obviously doesn't care how the file is called or where you place it. You can also go with plain JS.&lt;/p&gt;

&lt;p&gt;Here's the example script &lt;a href="https://nx.dev/features/manage-releases#using-the-programmatic-api-for-nx-release" rel="noopener noreferrer"&gt;from our docs&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;releaseChangelog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;releasePublish&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;releaseVersion&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nx/release&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;yargs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yargs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;yargs&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// don't use the default meaning of version in yargs&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Explicit version specifier to use, if overriding conventional commits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dryRun&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Whether or not to perform a dry-run of the release process, defaults to true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;boolean&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;verbose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Whether or not to enable verbose logging, defaults to false&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;boolean&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;workspaceVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectsVersionData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;releaseVersion&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;specifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;releaseChangelog&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;versionData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;projectsVersionData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;workspaceVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// The returned number value from releasePublish will be zero if all projects are published successfully, non-zero if not&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publishStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;releasePublish&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publishStatus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can invoke it with &lt;a href="https://github.com/privatenumber/tsx" rel="noopener noreferrer"&gt;tsx&lt;/a&gt; or &lt;a href="https://www.npmjs.com/package/ts-node" rel="noopener noreferrer"&gt;tsnode&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm dlx tsx release.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice by default in the script we have &lt;code&gt;dry-run&lt;/code&gt; enabled as a more cautious approach to not accidentally publish something as we keep editing and trying our programmatic setup.&lt;/p&gt;

&lt;p&gt;From here on you have full control and can pretty much do whatever works best for your workspace setup. Common examples include to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;move files to a common root-level &lt;code&gt;dist/&lt;/code&gt; folder and version and release them from there. This is pretty common to avoid messing with your src files and swapping versions there, allowing you to always depend on the latest local packages for instance.&lt;/li&gt;
&lt;li&gt;setup fully automated releases on CI, including enabling provenance support. &lt;a href="https://nx.dev/recipes/nx-release/publish-in-ci-cd" rel="noopener noreferrer"&gt;Our docs have more details&lt;/a&gt; on how to set that up or check out the linked talk above which goes through those steps&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;With this release of Nx Release it is fully ready to be used. Make sure to check out our docs on &lt;a href="https://nx.dev/features/manage-releases" rel="noopener noreferrer"&gt;Managing Releases&lt;/a&gt; as well as our release-related &lt;a href="https://nx.dev/recipes/nx-release" rel="noopener noreferrer"&gt;recipes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some example repositories already leveraging Nx release&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nrwl/nx/blob/master/scripts/nx-release.ts" rel="noopener noreferrer"&gt;our own Nx Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ReactiveX/rxjs/tree/master/scripts" rel="noopener noreferrer"&gt;RxJS repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/typescript-eslint/typescript-eslint/blob/main/tools/release/release.mts" rel="noopener noreferrer"&gt;typescript-eslint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=lYNa6Ct4RkY" rel="noopener noreferrer"&gt;Watch the live stream&lt;/a&gt; with &lt;a href="https://twitter.com/kentcdodds" rel="noopener noreferrer"&gt;Kent&lt;/a&gt; and &lt;a href="https://twitter.com/MrJamesHenry" rel="noopener noreferrer"&gt;James&lt;/a&gt; as they enable Nx Release on the &lt;a href="https://github.com/epicweb-dev/kcdshop" rel="noopener noreferrer"&gt;EpicWeb workshop app repository&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;X / Twitter&lt;/a&gt; - &lt;a href="https://www.linkedin.com/company/nrwl" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.nx.dev/community" rel="noopener noreferrer"&gt;Nx Community Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devtools</category>
      <category>javascript</category>
      <category>monorepos</category>
      <category>react</category>
    </item>
    <item>
      <title>What if Nx Plugins Were More Like VSCode Extensions</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Mon, 05 Feb 2024 15:32:55 +0000</pubDate>
      <link>https://forem.com/nx/what-if-nx-plugins-were-more-like-vscode-extensions-4oh0</link>
      <guid>https://forem.com/nx/what-if-nx-plugins-were-more-like-vscode-extensions-4oh0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Enhance&lt;/strong&gt;, but don't interfere! That's the ideal! And this is how extensions work in VSCode (or Webstorm). You can use VSCode without any extension and get some basic functionality, or you can add an extension on top to enhance your experience and, ideally, increase your productivity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding Nx to an Existing Monorepo&lt;/li&gt;
&lt;li&gt;Project Crystal&lt;/li&gt;
&lt;li&gt;
Project Crystal Plugins in an Nx Monorepo

&lt;ul&gt;
&lt;li&gt;Inferred Targets&lt;/li&gt;
&lt;li&gt;Visualizing Inferred Targets&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;More Transparency and a Single Source of Truth&lt;/li&gt;

&lt;li&gt;Enhancing existing Monorepos with Nx Plugins&lt;/li&gt;

&lt;li&gt;This is just the Beginning&lt;/li&gt;

&lt;li&gt;Learn more&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Prefer a video? I've got you covered!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wADNsVItnsM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Also, make sure to check out &lt;a href="https://nx.dev/launch-nx" rel="noopener noreferrer"&gt;Launch Nx Conf&lt;/a&gt; on Thursday, Feb 08th, where there are going to be more in-depth talks about Project Crystal as well as other exciting features around Nx and Nx Cloud.&lt;/p&gt;




&lt;p&gt;Take, for instance, the Playwright plugin. You install it, and it'll automatically detect the Playwright config file and enhance your workspace by providing quick run buttons alongside your tests or even a dedicated Test Explorer window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6k4kcu0832u2vg4o7fb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6k4kcu0832u2vg4o7fb9.png" alt="VSCode Playwright Extension" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Nx to an Existing Monorepo
&lt;/h2&gt;

&lt;p&gt;You can add Nx to an existing npm/yarn/pnpm monorepo quite straightforwardly. You run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You'll get an &lt;code&gt;nx&lt;/code&gt; package installed and an &lt;code&gt;nx.json&lt;/code&gt; allowing you to define &lt;a href="https://nx.dev/recipes/running-tasks/defining-task-pipeline" rel="noopener noreferrer"&gt;task dependencies&lt;/a&gt; and caching. With that, you're now able to run commands like &lt;code&gt;nx build &amp;lt;your project&amp;gt;&lt;/code&gt; or &lt;code&gt;nx run-many -t build test&lt;/code&gt; to run all &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; targets in your workspace in parallel. Nx will read and use your existing &lt;code&gt;package.json&lt;/code&gt; scripts. I've written an in-depth &lt;a href="https://dev.to/nx/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-1eem"&gt;blog post about adopting Nx in such a scenario&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the most lightweight setup you can get while still getting some improvements via Nx regarding faster task running and more intelligent parallelization. But, you need to deal with the remaining of the monorepo setup.&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Crystal
&lt;/h2&gt;

&lt;p&gt;Nx always had more to offer, though, which it mainly did through its plugins. They're optional but usually something you'd get set up when creating a new workspace with &lt;code&gt;create-nx-workspace.&lt;/code&gt; Nx Plugins are extremely powerful, helping you not only create and configure new monorepos, but also taking away the burden of integrating various tooling as well as providing features for enforcing consistency and helping with maintainability. These aspects are fundamental in enterprise settings, where Nx Plugins have proven to help teams successfully manage their monorepos.&lt;/p&gt;

&lt;p&gt;However, this is a balancing act. More abstraction and automation means more support but also potentially a learning curve and giving up some low-level control. It also requires a slightly more significant upfront investment when migrating to an Nx plugin-powered monorepo. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;These are things we wanted to solve&lt;/strong&gt;, and &lt;strong&gt;Project Crystal&lt;/strong&gt; is the first step in that direction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ukerqqz8v2g4b1sn6zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ukerqqz8v2g4b1sn6zl.png" alt="Nx Project Crystal" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of the main objectives of Project Crystal are to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make Nx plugins more transparent&lt;/li&gt;
&lt;li&gt;reduce the amount of configuration required&lt;/li&gt;
&lt;li&gt;allow Nx plugins to be drop-in enhancements in existing npm/yarn/pnpm monorepos&lt;/li&gt;
&lt;li&gt;allow for a migration to an Nx plugin-powered monorepo&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Project Crystal Plugins in an Nx Monorepo
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Note, starting with Nx 18, Project Crystal will be active for new workspaces only. You can opt-in to use them though.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you create a new Nx workspace using&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace myorg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;..and you choose an "integrated monorepo" you'll get the usual setup powered by Nx Plugins and all the features and benefits that come with them. Where you'll see Project Crystal in action is when you open a &lt;code&gt;project.json&lt;/code&gt; file, which will most likely look like the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reactapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"../../node_modules/nx/schemas/project-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sourceRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"apps/reactapp/src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"projectType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Inferred Targets
&lt;/h3&gt;

&lt;p&gt;Starting with Nx 18 and Project Crystal, we don't generate any targets anymore, but the corresponding Nx plugin instead &lt;strong&gt;&lt;a href="https://nx.dev/concepts/inferred-tasks" rel="noopener noreferrer"&gt;infers them&lt;/a&gt;&lt;/strong&gt;. If we open the &lt;code&gt;nx.json&lt;/code&gt;, you'll see a new property, &lt;code&gt;plugins&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nx/vite/plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"buildTargetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"previewTargetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"preview"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"testTargetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"serveTargetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"serveStaticTargetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"serve-static"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nx/eslint/plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"targetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lint"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nx/cypress/plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"targetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e2e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"componentTestingTargetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"component-test"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice the &lt;code&gt;options&lt;/code&gt; property defining the names of the potentially inferred targets for each plugin. These targets will be generated dynamically s.t. you can still run &lt;code&gt;nx build reactapp&lt;/code&gt; even though there's no &lt;code&gt;build&lt;/code&gt; target explicitly defined in the &lt;code&gt;project.json&lt;/code&gt; of your &lt;code&gt;apps/reactapp&lt;/code&gt; project.&lt;/p&gt;

&lt;p&gt;This dramatically reduces the redundancy of repeatedly configuring the same tasks (e.g., Jest or Vitest tasks) throughout your various projects. Instead, with this new approach, you get the defaults, and if you need to override them, you can still define them in your &lt;code&gt;project.json&lt;/code&gt; file as you were accustomed to before.&lt;/p&gt;
&lt;h3&gt;
  
  
  Visualizing Inferred Targets
&lt;/h3&gt;

&lt;p&gt;Dynamically inferred targets help with the maintainability aspect and reduce the configuration overhead overall. But how do we know which targets are available for a given project?&lt;/p&gt;

&lt;p&gt;Option 1 is to run the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx show project reactapp --web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This opens your browser with the following view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lscnjkqazwiue8jo55u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lscnjkqazwiue8jo55u.png" alt="Nx inferred targets visualization in the browser" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Option 2 is &lt;a href="https://nx.dev/features/integrate-with-editors" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;, which is an extension for VSCode as well as IntelliJ (Webstorm etc..). It comes with a project detail view, as shown below, as well as "Codelens" features that enhance your configuration files with context-based information and features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkdu1dol5m2xt36jhjx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkdu1dol5m2xt36jhjx2.png" alt="Nx inferred targets in Nx Console" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  More Transparency and a Single Source of Truth
&lt;/h2&gt;

&lt;p&gt;We also wanted the new approach to plugins to be closer to the actual CLI tool of the framework you're using. If you have a React + Vite project, &lt;code&gt;nx build&lt;/code&gt; should be as close as possible to the &lt;code&gt;vite build&lt;/code&gt; while still providing the enhancements around caching configuration.&lt;/p&gt;

&lt;p&gt;And this is what happens. Behind the scenes, the plugin configures caching with inputs and outputs and task dependencies (e.g., &lt;code&gt;^build&lt;/code&gt;) but then mostly pipes through to the Vite CLI (in this particular case), Remix, Next CLI, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5hoof8mbl21my219yqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5hoof8mbl21my219yqh.png" alt="Visualization with nx build vite target expanded showing the details about the caching config" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, the framework-specific config - in the example of Vite, the &lt;code&gt;vite.config.ts&lt;/code&gt; - is the single source of truth from which Nx infers configuration such as caching. If you change your Vite &lt;code&gt;build.outDir&lt;/code&gt;, Nx automatically picks that up and uses that as the caching output directory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enhancing existing Monorepos with Nx Plugins
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, one of the key goals of Project Crystal was to improve the adoption story of Nx Plugins, which implicitly also helps with migrating to Nx plugin-based monorepos. By reducing the config footprint of an Nx plugin and by automatically inferring tasks from existing framework configs, we've moved in a direction where plugins have become much more of a drop-in approach.&lt;/p&gt;

&lt;p&gt;Starting with Nx 18, if you now run &lt;code&gt;nx init&lt;/code&gt; on an existing npm/yarn/pnpm workspace, you'll also get asked about installing plugins based on the setup you have in your monorepo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4dpwaffd98vh9uevh7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4dpwaffd98vh9uevh7g.png" alt="Terminal showing nx init and option to choose plugins" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also obviously start with no plugin at all and incrementally add them as you go and feel comfortable using the new &lt;code&gt;add&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx add @nx/vite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  This is just the Beginning
&lt;/h2&gt;

&lt;p&gt;We just released Project Crystal, so this is just the beginning of it. While we've moved many of our existing Nx plugins to adopt the new approach, there are still some more refinements to be done in the coming weeks. But we are excited about the possibilities Project Crystal enables for Nx and its adoption story going forward, making Nx plugins more approachable, transparent, and lightweight.&lt;/p&gt;


&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;X / Twitter&lt;/a&gt; - &lt;a href="https://www.linkedin.com/company/nrwl" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.nx.dev/community" rel="noopener noreferrer"&gt;Nx Community Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>devtools</category>
      <category>javascript</category>
      <category>monorepos</category>
      <category>react</category>
    </item>
    <item>
      <title>Nx - Highlights of 2023</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Thu, 28 Dec 2023 17:01:08 +0000</pubDate>
      <link>https://forem.com/nx/nx-highlights-of-2023-4a77</link>
      <guid>https://forem.com/nx/nx-highlights-of-2023-4a77</guid>
      <description>&lt;p&gt;&lt;em&gt;Co-authored by &lt;a href="https://twitter.com/victorsavkin" rel="noopener noreferrer"&gt;Victor Savkin&lt;/a&gt; and &lt;a href="https://twitter.com/zackderose" rel="noopener noreferrer"&gt;Zack DeRose&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is that time again: getting flooded by Year of Review blog posts. We did it &lt;a href="https://dev.to/nx/reflecting-on-2022-the-year-in-review-i66"&gt;last year&lt;/a&gt;, and we should do it again! So here we go, and be warned, 2023 was massive!!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Top 10 Nx Highlights of 2023

&lt;ul&gt;
&lt;li&gt;TypeScript for Extensibility - Rust for Speed&lt;/li&gt;
&lt;li&gt;First Class Vite Support&lt;/li&gt;
&lt;li&gt;Nx't Level Publishing&lt;/li&gt;
&lt;li&gt;Improved Node Backend Development: Fastify and Docker&lt;/li&gt;
&lt;li&gt;Nx Console support for IntelliJ&lt;/li&gt;
&lt;li&gt;Playwright for e2e testing&lt;/li&gt;
&lt;li&gt;TypeScript Packaging and Batch Mode&lt;/li&gt;
&lt;li&gt;Nx team maintained Vue plugin&lt;/li&gt;
&lt;li&gt;Extending Nx: Local Generators, Build your Own CLI, Verdaccio Support&lt;/li&gt;
&lt;li&gt;Module Federation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Many OSS repos adopt Nx&lt;/li&gt;

&lt;li&gt;Nx Community&lt;/li&gt;

&lt;li&gt;New Content &amp;amp; Improved Docs&lt;/li&gt;

&lt;li&gt;New Tagline: Smart Monorepos - Fast CI&lt;/li&gt;

&lt;li&gt;Nx Conf&lt;/li&gt;

&lt;li&gt;Looking ahead - 2024&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Top 10 Nx Highlights of 2023
&lt;/h2&gt;

&lt;p&gt;We shipped a ton of features in 2023. You can find all our release blog posts and release-related info here: &lt;a href="https://nx.dev/changelog" rel="noopener noreferrer"&gt;https://nx.dev/changelog&lt;/a&gt; or check out our &lt;a href="https://dev.to/nx"&gt;Dev.to collection&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I picked out 10 highlights for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript for Extensibility - Rust for Speed
&lt;/h3&gt;

&lt;p&gt;At Nx, we’ve heavily embraced Typescript from the beginning and we’ve been very happy with that decision. Nx also stands as the &lt;a href="https://github.com/vsavkin/large-monorepo" rel="noopener noreferrer"&gt;fastest JS monorepo tool&lt;/a&gt; available, demonstrating that adopting TypeScript does not necessarily compromise speed. However, we don't stop here. To push the boundaries further, we started to rewrite the most performance critical and computationally intensive parts of the Nx core in Rust.&lt;/p&gt;

&lt;p&gt;Our initial focus was on &lt;a href="https://dev.to/nx/nx-158-rust-hasher-nx-console-for-intellij-deno-node-and-storybook-27ng#rustifying-the-nx-hasher"&gt;rewriting the task hasher&lt;/a&gt;, previously reliant on Git with a Node fallback. This shift to Rust brings a noticeable performance boost, particularly in large repositories, while maintaining the same user experience.&lt;/p&gt;

&lt;p&gt;Following this, we revamped the TypeScript dependency resolution, observing an almost 5x speed increase with our Rust-based approach over the traditional TSC method.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1726977598218199302-389" src="https://platform.twitter.com/embed/Tweet.html?id=1726977598218199302"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1726977598218199302-389');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1726977598218199302&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Such enhancements are especially crucial for the efficient &lt;a href="https://nx.dev/core-features/explore-graph" rel="noopener noreferrer"&gt;project graph calculation&lt;/a&gt;. As we continue to evolve Nx, Rust will play a key role in optimizing performance-critical components. This strategic use of Rust complements our ongoing commitment to TypeScript, ensuring Nx remains as extensible and powerful as ever.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Class Vite Support
&lt;/h3&gt;

&lt;p&gt;Vite is rapidly transforming the landscape of frontend development! Its refreshing simplicity and innovative approach have made a significant mark in the developer community. What truly stands out is not just Vite's technological aspect but also how its team approaches and grows the community around the tool. Vite stands for speed and community, values that deeply resonate with us here at Nx.&lt;/p&gt;

&lt;p&gt;Our collaboration with our friends in the Vite core team has been incredibly fruitful. Vite is not just compatible but a first-class option with many of Nx's frontend plugins. When you create a new Nx powered React workspace, Vite (and &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;) are your default options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdcvxo2cx46xm3kpppia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdcvxo2cx46xm3kpppia.png" alt="Setting up React app with Nx and Vite" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also built some powerful code generators that not only facilitate a seamless &lt;a href="https://nx.dev/nx-api/vite/generators/configuration#nxviteconfiguration" rel="noopener noreferrer"&gt;transition from Webpack to Vite&lt;/a&gt; but also pave the way for an effortless &lt;a href="https://nx.dev/recipes/react/migration-cra" rel="noopener noreferrer"&gt;migration from a CRA-based setup&lt;/a&gt; to a modern Nx + Vite based workspace. To see this process in action, &lt;a href="https://youtu.be/zvYb7XCLQzU?si=WpiuT18mP2yAmy4q" rel="noopener noreferrer"&gt;check out this short video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://analogjs.org/" rel="noopener noreferrer"&gt;AnalogJS&lt;/a&gt; - the fullstack Angular meta-framework which also heavily builds on top of Vite - is using the &lt;code&gt;@nx/vite&lt;/code&gt; plugin to power its Angular and Nx based workspaces.&lt;/p&gt;

&lt;p&gt;We also spoke at both editions of &lt;a href="https://viteconf.org/" rel="noopener noreferrer"&gt;ViteConf&lt;/a&gt;. If you're curious check out &lt;a href="https://youtu.be/TiU-hdn7_To?si=A5Nkg3rxe3DlODc4" rel="noopener noreferrer"&gt;Juri's talk about High Speed Monorepos&lt;/a&gt; and this year's talk by &lt;a href="https://youtu.be/HfarG4wswK4?si=ZdBiO4zI5ZrpRQ-l" rel="noopener noreferrer"&gt;Katerina on Streamlining your Vite dev flow with Nx&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nx't Level Publishing
&lt;/h3&gt;

&lt;p&gt;Open source libraries and frameworks share a common necessity: the need to develop multiple packages cohesively and efficiently while managing their versioning and publishing to NPM. Nx has emerged as a go-to choice for handling such open source monorepos (as we'll explore further in the next section of this blog post). Until recently, one area Nx did not address directly was versioning and release management. Traditionally, this gap has been filled with tools like &lt;a href="https://github.com/release-it/release-it" rel="noopener noreferrer"&gt;release-it&lt;/a&gt;, &lt;a href="https://github.com/changesets/changesets" rel="noopener noreferrer"&gt;changesets&lt;/a&gt;, or custom Node scripts, similar to our approach in the Nx repository.&lt;/p&gt;

&lt;p&gt;However, many in our community have expressed a desire for a more native, integrated experience for versioning and publishing, akin to what Lerna offers. In response to this feedback, we've introduced &lt;a href="https://nx.dev/core-features/manage-releases" rel="noopener noreferrer"&gt;the "nx release" command&lt;/a&gt;, a solution designed to seamlessly integrate these processes into the Nx workflow.&lt;/p&gt;

&lt;p&gt;James Henry gave a deep dive talk of an early version of it at this year's Nx Conf:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/p5qW5-2nKqI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Since its introduction, the "nx release" feature has significantly evolved, leveraging the power of the Nx project graph to effectively understand inter-package dependencies. This understanding is crucial as it allows for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Versioning packages offering support for both independent and "locked" versioning strategies.&lt;/li&gt;
&lt;li&gt;Releasing packages in the correct sequence, ensuring dependency integrity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond these core functionalities, the feature also includes a robust grouping mechanism, supports semantic versioning, and changelog generation. Additionally, it provides various release targets, such as GitHub and NPM. For those having special requirements, the &lt;a href="https://nx.dev/core-features/manage-releases#using-the-programmatic-api-for-nx-release" rel="noopener noreferrer"&gt;programmatic API&lt;/a&gt; offers maximum flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved Node Backend Development: Fastify and Docker
&lt;/h3&gt;

&lt;p&gt;Colocating frontend and backend code within the same monorepo has become a popular practice. It greatly facilitates cross-functional teams and helps ensure end-to-end type safety. Although you can use &lt;a href="https://www.nx-dotnet.com/" rel="noopener noreferrer"&gt;other backend stacks&lt;/a&gt; with Nx, Node is a popular backend companion for JS based frontends. We had support for &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; and &lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;NestJS&lt;/a&gt; backend for a while.&lt;/p&gt;

&lt;p&gt;This year we added another popular option: &lt;a href="https://fastify.dev/" rel="noopener noreferrer"&gt;Fastify&lt;/a&gt;. Known for its high performance, excellent developer experience, and useful built-in features like logging, Fastify aligns well with Nx's modular software design principles. Its extensible and modular nature complements the Nx philosophy perfectly.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LHLW0b4fr2w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In tandem with Fastify, we've also introduced &lt;a href="https://youtu.be/K4f-fMuAoRY?si=_MHWY2U5IehNrtlu&amp;amp;t=105" rel="noopener noreferrer"&gt;Docker support&lt;/a&gt; for Node deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nx Console support for IntelliJ
&lt;/h3&gt;

&lt;p&gt;Nx Console has evolved from an experimental side project of the Nx team to a core part for enhancing your productivity when working in a monorepo. Being integrated right into your editor it can provide useful information and functionality right where you need it, whether that's running commands, &lt;a href="https://twitter.com/juristr/status/1653032530474565638" rel="noopener noreferrer"&gt;providing contextual autocomplete support&lt;/a&gt; or the ability to explore the project and task graph.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisubsplzjiesl2j6yodj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisubsplzjiesl2j6yodj.png" alt="Nx Graph shown in Nx Console extension" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This year we not only added a lot of new features to Nx Console, but also rewrote its &lt;a href="https://blog.nrwl.io/nx-console-gets-lit-ca339743ff4f" rel="noopener noreferrer"&gt;internals&lt;/a&gt; which paved the way to expand Nx Console to other code editors: &lt;strong&gt;JetBrains IDEs&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Yes, this means you can now use the latest Nx Console directly in your &lt;a href="https://www.jetbrains.com/webstorm/" rel="noopener noreferrer"&gt;Webstorm IDE&lt;/a&gt;. Read the &lt;a href="https://blog.nrwl.io/expanding-nx-console-to-jetbrains-ides-8a5b80fff2d7" rel="noopener noreferrer"&gt;announcement blog post for all the details&lt;/a&gt; or go ahead and install Nx Console if you didn't already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console for VSCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://plugins.jetbrains.com/plugin/21060-nx-console" rel="noopener noreferrer"&gt;Nx Console for IntelliJ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Playwright for e2e testing
&lt;/h3&gt;

&lt;p&gt;2023 saw Nx introduce official support for &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; - a popular testing tool from Microsoft.&lt;/p&gt;

&lt;p&gt;In this video, Zack DeRose explains how you can use Playwright to test both a single web application, as well as stand up a full-stack system - including a backend server and a frontend application - and write and run tests using Playwright:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/k1U3PuBrZFQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The repo for this video can also be found &lt;a href="https://github.com/nrwl/tic-tac-toe-playwright" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Generally, Playwright fits in the Nx ecosystem as a tool that developers can use as a possible alternative to Cypress - a popular e2e testing tool that Nx has supported for a long time now! In addition to publishing an official &lt;a href="https://www.npmjs.com/package/@nx/playwright" rel="noopener noreferrer"&gt;@nx/playwright package&lt;/a&gt;, running the command to create a new workspace will now prompt for Playwright as an option for React, Angular, and Vue stacks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% npx create-nx-workspace@latest

&lt;/span&gt;&lt;span class="gp"&gt; &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;NX   Let&lt;span class="s1"&gt;'s create a new workspace [https://nx.dev/getting-started/intro]
&lt;/span&gt;&lt;span class="go"&gt;
✔ Which stack do you want to use? · react
✔ What framework would you like to use? · none
✔ Integrated monorepo, or standalone project? · integrated
✔ Which bundler would you like to use? · vite
? Test runner to use for end to end (E2E) tests … 
Cypress [ https://www.cypress.io/ ]
Playwright [ https://playwright.dev/ ]
None

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar options will appear when using Nx generators to create new frontend web applications for an existing workspace.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript Packaging and Batch Mode
&lt;/h3&gt;

&lt;p&gt;TypeScript has won. It has become the prevalent way of writing modern JavaScript applications. And we kept improving our support to streamline development and polish some of the rough edges. Like properly defining secondary package entry points. You can define them in the &lt;code&gt;package.json&lt;/code&gt;, but both creating these entries but especially maintaining them can be quite painful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"exports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"./package.json"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./package.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"./foo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/foo.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"./bar"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/bar.js"&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in &lt;a href="https://blog.nrwl.io/nx-16-8-release-e38e3bb503b5#7b41" rel="noopener noreferrer"&gt;v16.8&lt;/a&gt; we added the ability to automatically have these generated for you by defining the &lt;code&gt;additionalEntryPoints&lt;/code&gt; and &lt;code&gt;generateExportsField&lt;/code&gt; when using the &lt;code&gt;@nx/js&lt;/code&gt; plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;packages/my-awesome-lib/project.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-awesome-lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"executor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nx/js:tsc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"packages/my-awesome-lib/src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"additionalEntryPoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"packages/my-awesome-lib/src/foo.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"generateExportsField"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly we improved the ability to package your TS libraries in multiple formats (ESM and CJS). When using the &lt;code&gt;@nx/rollup&lt;/code&gt; plugin, all you need to do is define the &lt;code&gt;format&lt;/code&gt; property in your config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;packages/my-awesome-lib/project.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-awesome-lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"executor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nx/rollup:rollup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"packages/my-awesome-lib/src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"esm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cjs"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"additionalEntryPoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"packages/my-awesome-lib/src/foo.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"generateExportsField"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a video that walks you through:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Vy4d0-SF5cY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;But we wouldn't be talking about Nx if we didn't also look into speeding up TypeScript compilation for large monorepos. We called it "&lt;a href="https://nx.dev/showcase/benchmarks/tsc-batch-mode" rel="noopener noreferrer"&gt;batch mode&lt;/a&gt;". When enabling batch mode, Nx leverages the underlying &lt;a href="https://nx.dev/core-features/explore-graph" rel="noopener noreferrer"&gt;project graph&lt;/a&gt; to generate TypeScript project references behind the scenes for you, to fully leverage TS incremental building. The results are amazing. According to &lt;a href="https://github.com/nrwl/large-ts-monorepo" rel="noopener noreferrer"&gt;our benchmarks&lt;/a&gt;, batch mode has the potential to speed up Typescript compilation by up to 5x for large monorepos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk0e2unykk0aeqmknnmy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk0e2unykk0aeqmknnmy.gif" alt="Nx batch mode speed comparison" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Nx team maintained Vue plugin
&lt;/h3&gt;

&lt;p&gt;After adding Vite as a first-class citizen of Nx workspaces, it was only a matter of time before Nx started offering official support to Vue!&lt;/p&gt;

&lt;p&gt;Vue is currently the second most popular frontend framework (according to npm downloads) behind React and slightly ahead of Angular.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f8wgjsp5s7t3orqge1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f8wgjsp5s7t3orqge1z.png" alt="NPM trends angular, react, vue" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first place your might notice Nx's support for Vue is in the &lt;code&gt;create-nx-workspace&lt;/code&gt; script:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsf8zw4cqj4ttconev7h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsf8zw4cqj4ttconev7h.png" alt="create nx workspace with Vue" width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The option above will create a new Nx workspace with a fresh new Vue application, all set up and ready to develop! To add new Vue projects to an existing Nx workspace, you can also add our &lt;code&gt;@nx/vue&lt;/code&gt; package as a dev dependency to your workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% npm add -D @nx/vue
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you'll then have access to Nx generators so you can create Vue applications, libraries, and more in your workspace!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funo9x7l2nifee6v9wl76.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funo9x7l2nifee6v9wl76.gif" alt="Nx Console showing Vue generators" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checkout out our &lt;a href="https://nx.dev/getting-started/tutorials/vue-standalone-tutorial" rel="noopener noreferrer"&gt;Vue standalone tutorial&lt;/a&gt; for more, as well as our &lt;a href="https://nx.dev/nx-api/vue" rel="noopener noreferrer"&gt;Vue API docs&lt;/a&gt; and stay tuned as Nx prepares to offer more Vue support (including support for &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;, a full-stack framework built around Vue) in the near future! &lt;/p&gt;

&lt;h3&gt;
  
  
  Extending Nx: Local Generators, Build your Own CLI, Verdaccio Support
&lt;/h3&gt;

&lt;p&gt;Extensibility is at the heart of Nx, serving as the cornerstone of its flexibility. It enables the Nx core team to continually expand capabilities through dedicated plugins and simultaneously paves the way for a rich array of &lt;a href="https://nx.dev/plugin-registry" rel="noopener noreferrer"&gt;community plugin contributions&lt;/a&gt;. Furthermore, Nx's adaptable nature is particularly beneficial for large enterprises, as it allows for the creation of custom automation solutions, specifically tailored to meet their unique organizational needs.&lt;/p&gt;

&lt;p&gt;In 2023 we kept improving Nx's extensibility, unifying the Nx plugin development model and how you develop workspace-local automations. You can now scaffold a new plugin into your Nx workspace and run it right away which makes it an interesting approach to automate your monorepo.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/myqfGDWC2go"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;When creating automations with Nx you cannot just enhance existing Nx workspaces, but also develop a complete &lt;a href="https://nx.dev/extending-nx/recipes/create-preset" rel="noopener noreferrer"&gt;Nx preset&lt;/a&gt; that controls the entire appearance of an Nx workspace. Basically your own, personalized &lt;code&gt;create-nx-workspace&lt;/code&gt;. You can publish and then use your preset like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace myrepo --preset=@yourpkg/nx-preset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We wanted to make building on top of Nx even more pleasant, allowing you to introduce your own branding by &lt;a href="https://youtu.be/ocllb5KEXZk?si=1DK9ehMxbdaDvq1q" rel="noopener noreferrer"&gt;building your own CLI with Nx&lt;/a&gt;. The &lt;a href="https://github.com/qwikifiers/qwik-nx" rel="noopener noreferrer"&gt;Qwik-Nx&lt;/a&gt; repo is a great example where they allow you to scaffold a new Nx workspace for Qwik development with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-qwik-nx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, we extracted our own &lt;a href="https://verdaccio.org/" rel="noopener noreferrer"&gt;Verdaccio&lt;/a&gt; setup that we've been using to run our e2e tests in the &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx repo&lt;/a&gt; s.t. you can use it for your own plugin development as well. Check out &lt;a href="https://youtu.be/t1c925TzrzE?si=7oo2hYyPWKvT1raE" rel="noopener noreferrer"&gt;this video&lt;/a&gt; for a walkthrough on how this works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module Federation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://medium.com/swlh/webpack-5-module-federation-a-game-changer-to-javascript-architecture-bcdd30e02669" rel="noopener noreferrer"&gt;Module Federation&lt;/a&gt; is an exciting new feature of Webpack 5 that has gained a significant amount of interest in 2023.&lt;/p&gt;

&lt;p&gt;Simply put, Module Federation allows a Javascript application running in a browser to dynamically load code from another application hosted at a different url, while facilitating optimal loading of shared dependencies.&lt;/p&gt;

&lt;p&gt;This is an exciting development as it allows a paradigm shift in how you can architect, build, and deploy Javascript applications! And this is especially exciting for monorepo fans, as Nx has best-in-class support for module federation that makes a Module Federation approach easy to adopt and simple to understand!&lt;/p&gt;

&lt;p&gt;Currently, our &lt;code&gt;@nx/angular&lt;/code&gt; and &lt;code&gt;@nx/react&lt;/code&gt; plugins both have generators &lt;a href="https://nx.dev/recipes/module-federation/create-a-host" rel="noopener noreferrer"&gt;to create a "host" application&lt;/a&gt; that will load and consume federated modules from &lt;a href="https://nx.dev/recipes/module-federation/create-a-remote" rel="noopener noreferrer"&gt;"remote" applications&lt;/a&gt;, which you can also generate using Nx. Then, by running a simple command with Nx, you can serve all applications required for your host application with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% nx serve host-application --devRemotes=remote-application
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where in the example above your host application is named &lt;code&gt;host-application&lt;/code&gt; and a remote application that you want live updates on as you're developing is named &lt;code&gt;remote-application&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Throughout 2023, we've continued to increase Nx's support and general dev experience around Module Federation, including &lt;a href="https://nx.dev/recipes/module-federation/federate-a-module" rel="noopener noreferrer"&gt;adding a generator to federate an existing module&lt;/a&gt;, improving the local developer experience by improving local webserver performance, and introducing the concept of &lt;a href="https://nx.dev/recipes/angular/dynamic-module-federation-with-angular#advanced-angular-micro-frontends-with-dynamic-module-federation" rel="noopener noreferrer"&gt;Dynamic Module Federation&lt;/a&gt; which will allow you to dynamically specify the location of your remote applications via a &lt;code&gt;module-federation.manifest.json&lt;/code&gt; file!&lt;/p&gt;

&lt;p&gt;At Nx, we're excited about the Module Federation support we offer for our users, and think that it has many interesting applications when paired with Nx's CI capabilities - &lt;a href="https://nx.dev/concepts/module-federation/faster-builds-with-module-federation#faster-builds-with-module-federation" rel="noopener noreferrer"&gt;in particular allowing for much shorter build times&lt;/a&gt;, especially for larger Angular applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Many OSS repos adopt Nx
&lt;/h2&gt;

&lt;p&gt;By simply installing the &lt;code&gt;nx&lt;/code&gt; package (or initializing with &lt;code&gt;nx init&lt;/code&gt; in any project or monorepo), you already get some cool features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced task scheduling, including task pipelines and parallel execution.&lt;/li&gt;
&lt;li&gt;Efficient caching mechanisms.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to learn more about such setup, make sure to check out our &lt;a href="https://dev.to/nx/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-1eem"&gt;blog post on how to adopt Nx on a npm/yarn/pnpm workspace&lt;/a&gt; or the corresponding &lt;a href="https://youtu.be/ngdoUQBvAjo?si=0XH6Sp025xM3Rru5" rel="noopener noreferrer"&gt;video version&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Numerous open-source packages are adopting Nx in this lightweight manner. It enables them to maintain their existing setup while notably enhancing the local developer experience (DX) in task execution and accelerating processes on CI.&lt;/p&gt;

&lt;p&gt;I picked out some of the more well-known OSS repos that started using Nx this year:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://tanstack.com/" rel="noopener noreferrer"&gt;Tanstack&lt;/a&gt; -&lt;/strong&gt; Tanstack has evolved to an entire ecosystem consisting of the famous &lt;a href="https://github.com/tanstack/query" rel="noopener noreferrer"&gt;Tanstack (or React) Query&lt;/a&gt;, &lt;a href="https://github.com/tanstack/table" rel="noopener noreferrer"&gt;Tanstack Table&lt;/a&gt;, now also &lt;a href="https://github.com/tanstack/router" rel="noopener noreferrer"&gt;Tanstack Router&lt;/a&gt; and &lt;a href="https://github.com/tanstack/form" rel="noopener noreferrer"&gt;Tanstack Form&lt;/a&gt;. It started with Tanstack Query, which adopted Nx and Nx Cloud. &lt;a href="https://youtu.be/NvPXK6DVZGE?si=wguHJ2IrZq5-4xQx" rel="noopener noreferrer"&gt;Zack talked about this collab with Dominik&lt;/a&gt;, and we also had &lt;a href="https://twitter.com/TkDodo" rel="noopener noreferrer"&gt;Dominik&lt;/a&gt; on our &lt;a href="https://www.youtube.com/live/IbU6b6s0H1Q?si=0QZexPwulLXB9FIN" rel="noopener noreferrer"&gt;Nx live stream&lt;/a&gt;. Now, all the above-mentioned Tanstack libs have adopted Nx, and there's more coming.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/getsentry/sentry-javascript/" rel="noopener noreferrer"&gt;Sentry JavaScript&lt;/a&gt; -&lt;/strong&gt; Sentry, renowned for its comprehensive solutions in frontend monitoring and error logging, recently adopted Nx for their &lt;a href="https://github.com/getsentry/sentry-javascript/" rel="noopener noreferrer"&gt;official JavaScript SDK&lt;/a&gt;. This move integrates Nx's capabilities into their monorepo, containing packages for popular frontend and Node.js backend integrations. They also &lt;a href="https://sentry.engineering/blog/reduce-ci-time-with-nx-caching" rel="noopener noreferrer"&gt;published a blog post&lt;/a&gt; on the benefits they've seen following the adoption of Nx in their monorepo (hint: reducing CI times by 35%).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ReactiveX/rxjs" rel="noopener noreferrer"&gt;RxJS&lt;/a&gt; -&lt;/strong&gt; The library for reactive programming in JavaScript. It is widely popular, with over 40 million downloads/week on NPM. RxJS only recently adopted Nx, not only leveraging speed improvements via caching, but also leveraging Nx's latest &lt;code&gt;nx release&lt;/code&gt; feature to publish packages to NPM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://analogjs.org/" rel="noopener noreferrer"&gt;AnalogJS&lt;/a&gt;&lt;/strong&gt; - Analog is a full-stack Angular meta-framework that brings exciting features to Angular, like faster Vite setup, support for both server-side and static rendering, and easy file-based routing. Analog uses an Nx monorepo for its development and also uses &lt;a href="https://nx.dev/extending-nx/intro/getting-started" rel="noopener noreferrer"&gt;Nx's DevKit&lt;/a&gt; to create tools that work great in both Nx and Angular CLI workspaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/qwikifiers/qwik-nx" rel="noopener noreferrer"&gt;Qwikifier&lt;/a&gt; -&lt;/strong&gt; The Qwikifiers community built a dedicated Nx plugin to combine the power of Qwik and Nx. Their repo is a great example of building Nx plugins and using &lt;a href="https://nx.dev/extending-nx/recipes/create-install-package" rel="noopener noreferrer"&gt;Nx to build your own CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/BuilderIO/mitosis" rel="noopener noreferrer"&gt;Builder.io Mitosis&lt;/a&gt; -&lt;/strong&gt; &lt;a href="https://www.builder.io/" rel="noopener noreferrer"&gt;BuilderIO&lt;/a&gt; has an ambitious compiler project that allows you to write a component once and then compile it to different frameworks. Check out their &lt;a href="https://mitosis.builder.io/" rel="noopener noreferrer"&gt;mind-blowing demo page&lt;/a&gt;. They adopted Nx to &lt;a href="https://nx.dev/concepts/task-pipeline-configuration" rel="noopener noreferrer"&gt;coordinate task dependencies&lt;/a&gt; and speed up their CI builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/TryGhost/Ghost" rel="noopener noreferrer"&gt;Ghost&lt;/a&gt; -&lt;/strong&gt; Are you into blogging? You might want to look at &lt;a href="https://ghost.org/" rel="noopener noreferrer"&gt;Ghost&lt;/a&gt;. They were using Lerna in the past and migrated to a fully Nx-powered workspace.&lt;/p&gt;

&lt;p&gt;And these are just some of them that joined in 2023. If I missed some cool ones (which I'm pretty sure), &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;ping me&lt;/a&gt; and let me know!&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Community
&lt;/h2&gt;

&lt;p&gt;Nx has a huge community! We're lucky to have so many folks rooting for Nx, whether on socials, talking at conferences, writing blog posts or &lt;a href="https://nx.dev/plugin-registry" rel="noopener noreferrer"&gt;creating awesome plugins&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nx Champions -&lt;/strong&gt; This year we finally launched which we had planned for a long time. Our &lt;strong&gt;&lt;a href="https://nx.dev/community" rel="noopener noreferrer"&gt;Nx Champions&lt;/a&gt;&lt;/strong&gt; program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbr3t66dvx14h0kl7m6ei.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbr3t66dvx14h0kl7m6ei.jpg" alt="Nx Champions" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are individuals who stood out for their contributions and passion for helping within the NX community. We wanted to build a more connected relationship with these folks and have a channel to gather more direct feedback as well. Get to know &lt;a href="https://nx.dev/community" rel="noopener noreferrer"&gt;all of our champions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New Discord server -&lt;/strong&gt; Around September we also switched over from our previous Nx Slack community to a brand new &lt;strong&gt;&lt;a href="https://go.nx.dev/community" rel="noopener noreferrer"&gt;Nx community Discord&lt;/a&gt;&lt;/strong&gt;, which is already counting 2,600+ members. Discord is popular among OSS communities and allows new folks to join easily. In addition, we now have a dedicated forum integrated, as well as a couple of useful automations. More coming next year!&lt;/p&gt;

&lt;p&gt;Make sure &lt;a href="https://go.nx.dev/community" rel="noopener noreferrer"&gt;you join!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New Content &amp;amp; Improved Docs
&lt;/h2&gt;

&lt;p&gt;Our &lt;a href="https://youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Youtube channel&lt;/a&gt; has grown to over 15k subscribers and peaks of 65k views a month. We love to provide educational video content, so make sure to subscribe! It got a little silent towards the end of the year, but we've been working a lot behind the scenes. So stay tuned!&lt;/p&gt;

&lt;p&gt;We also poured a lot of &lt;a href="https://nx.dev/docs" rel="noopener noreferrer"&gt;effort into the docs&lt;/a&gt;. We restructured them following the &lt;a href="https://diataxis.fr/" rel="noopener noreferrer"&gt;Diataxis&lt;/a&gt; to make pages less overwhelming and more structured based on their type of content. You'll find&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nx.dev/concepts" rel="noopener noreferrer"&gt;Concept docs&lt;/a&gt; -&lt;/strong&gt; which explain some of the inner workings and mental model behind certain features. Like &lt;a href="https://nx.dev/concepts/how-caching-works" rel="noopener noreferrer"&gt;how caching works&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nx.dev/recipes" rel="noopener noreferrer"&gt;Recipes&lt;/a&gt; -&lt;/strong&gt; which are solution oriented. You already know how to cook, we provide the exact recipe for it. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nx.dev/getting-started/tutorials" rel="noopener noreferrer"&gt;Tutorials&lt;/a&gt; -&lt;/strong&gt; for when you just want to sit down and follow along, step by step to learn how to use Nx in a certain context. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nx.dev/reference" rel="noopener noreferrer"&gt;Reference&lt;/a&gt; and &lt;a href="https://nx.dev/nx-api" rel="noopener noreferrer"&gt;API docs&lt;/a&gt; -&lt;/strong&gt; pure, raw and to the point. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We created a brand new &lt;a href="https://nx.dev/getting-started/why-nx" rel="noopener noreferrer"&gt;"Why Nx" page&lt;/a&gt; explaining the overall architecture of Nx including a &lt;a href="https://youtu.be/-_4WMl-Fn0w?si=XyVkfFS-4JTyzqkq" rel="noopener noreferrer"&gt;brand new video&lt;/a&gt; giving you a holistic overview of what Nx is capable of.&lt;/p&gt;

&lt;p&gt;We also refreshed &lt;a href="https://nx.dev/docs" rel="noopener noreferrer"&gt;our entry pages&lt;/a&gt;, including dedicated examples of using Nx with popular stacks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ucl917d4thfx5gt942o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ucl917d4thfx5gt942o.jpg" alt="Nx Stacks" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also browse them in the &lt;a href="https://github.com/nrwl/nx-recipes" rel="noopener noreferrer"&gt;nx-recipes&lt;/a&gt; GitHub repository.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1736023402933318011-479" src="https://platform.twitter.com/embed/Tweet.html?id=1736023402933318011"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1736023402933318011-479');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1736023402933318011&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;And obviously, we jumped on the AI train as well. A couple of months ago, we added the &lt;a href="https://nx.dev/ai-chat" rel="noopener noreferrer"&gt;Nx Assistant&lt;/a&gt;. A ChatGPT-powered interface trained on our docs. &lt;a href="https://twitter.com/psybercity" rel="noopener noreferrer"&gt;Katerina&lt;/a&gt; wrote about it &lt;a href="https://blog.nrwl.io/nx-docs-ai-assistant-433d238e45d4?source=friends_link&amp;amp;sk=c895f9b513a56b182c77486cd459fb96" rel="noopener noreferrer"&gt;on our blog&lt;/a&gt;. The AI chat allows to interactively ask questions about Nx and will give you relevant answers from our docs (including linking to the sources).&lt;/p&gt;

&lt;h2&gt;
  
  
  New Tagline: Smart Monorepos - Fast CI
&lt;/h2&gt;

&lt;p&gt;Nx stands out for its flexibility, accommodating for both monorepo and non-monorepo project structures. This approach allows users to begin with simpler project configurations, leveraging the benefits of Nx's robust tooling, and later, when the need arises, seamlessly &lt;a href="https://nx.dev/recipes/tips-n-tricks/standalone-to-integrated" rel="noopener noreferrer"&gt;migrate to a monorepo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, Nx's true strength becomes most apparent at scale, typically within a monorepo setup. We wanted to capture it in our new tagline: &lt;strong&gt;Smart Monorepos - Fast CI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1734558895547568634-36" src="https://platform.twitter.com/embed/Tweet.html?id=1734558895547568634"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1734558895547568634-36');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1734558895547568634&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Setting up an efficient and maintainable CI process for monorepos can be a complex task, so we've also made it a focal point in our new tagline. Nx expands beyond the local development experience, helping you set up an efficient CI process. We're publicly launching &lt;a href="https://nx.dev/ci/features/nx-agents" rel="noopener noreferrer"&gt;Nx Agents&lt;/a&gt; to add seamless distribution to your CI pipeline, and more are coming in 2024.&lt;/p&gt;

&lt;p&gt;As part of that, we also restructured our docs to have a section entirely dedicated to CI: &lt;a href="https://nx.dev/ci" rel="noopener noreferrer"&gt;https://nx.dev/ci&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Conf
&lt;/h2&gt;

&lt;p&gt;We did it again! The second in-person Nx Conf was a resounding success, this time set against the vibrant backdrop of the Big Apple.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr21fv8qy4g0v82e8jlx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr21fv8qy4g0v82e8jlx.jpg" alt="Nx Conf 2023 - Victor Savkin" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's not much to say. Check out some of the amazing talks. I did a &lt;a href="https://dev.to/nx/nx-conf-2023-recap-53ep"&gt;Nx Conf 2023 recap blog post&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Looking ahead - 2024
&lt;/h2&gt;

&lt;p&gt;Although we shipped a lot in 2023, in many ways 2023 was about preparing for what we are planning to ship in Q1 2024.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solving CI
&lt;/h3&gt;

&lt;p&gt;Legacy CI systems are a performance and productivity bottleneck if you use a powerful build system like Nx. Big tech companies know it and that's why their CI systems look nothing like Circle or Jenkins. We've been narrowing this gap over the years, but only this year we finally built a turn-key CI solution that gives you great performance, scalability, dev ergonomics, and must better cost efficiency. &lt;/p&gt;

&lt;p&gt;It has three components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nx.dev/ci/features/remote-cache" rel="noopener noreferrer"&gt;Nx Cache&lt;/a&gt;&lt;/strong&gt;: Built-in local and remote caching to speed up your tasks and save you time and money. &lt;em&gt;Available now.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nx.dev/ci/features/nx-agents" rel="noopener noreferrer"&gt;Nx Agents&lt;/a&gt;&lt;/strong&gt;: A single line to enable distributed computation, across multiple machines. Fully managed agents, dynamically allocated based on PR size. &lt;em&gt;Available early Feb.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nx Workflows&lt;/strong&gt;: Next generation, fully managed CI solution with distribution at its core, designed from the ground up for monorepos. &lt;em&gt;Available late March.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optimal parallelization and distribution, using the right numbers of agents for each PR, rerunning flaky tests, splitting and distributing large test suites, handling dependencies between tasks across machines -- are just some of the things we can now handle automatically for you. Turn it on and enjoy the speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solving the Simplicity vs Power Dilemma
&lt;/h3&gt;

&lt;p&gt;Balancing simplicity and power is the trickiest part of the dev tools design. Simple onboarding for small projects or handling the biggest enterprise systems? Two years ago we solved this problem by giving you a choice between the package-based setup (a more powerful version of something like Turborepo) and the integrated setup (we manage your whole monorepo in the most optimal way). But now we believe we have a much better solution, where you have both, the simplicity of the former with the power of the latter. So you no longer have to choose.&lt;/p&gt;

&lt;p&gt;We took inspiration from VSCode. Any project you open in VSCode will work right away: it is simple, and you don't need to configure anything. If you install say a Playwright plugin, VSCode becomes aware of Playwright. It can run and debug your tests right in the editor. That's what the Nx experience is going to be like. Any project, any tool will work right away. But if you - for instance - install the Playwright plugin, Nx will become aware of Playwright and will be able to cache test runs in the most optimal way and distribute your e2e tests across machines for best efficiency. All the benefits with none of the costs.&lt;/p&gt;

&lt;p&gt;The whole team is excited about it as the new experience feels much more elegant. &lt;/p&gt;

&lt;p&gt;As always, we try very hard not to break folks, so all your current workspaces will keep working, and we will &lt;a href="https://nx.dev/core-features/automate-updating-dependencies" rel="noopener noreferrer"&gt;provide automatic migrations&lt;/a&gt; to bring you to this new way of using Nx.&lt;/p&gt;

&lt;p&gt;Exciting stuff! So keep an eye on our channels, and subscribe if you haven't already ;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;X / Twitter&lt;/a&gt; - &lt;a href="https://www.linkedin.com/company/nrwl" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.nx.dev/community" rel="noopener noreferrer"&gt;Nx Community Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>devtools</category>
      <category>monorepos</category>
    </item>
    <item>
      <title>Nx Conf 2023 - Recap</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Fri, 13 Oct 2023 18:22:55 +0000</pubDate>
      <link>https://forem.com/nx/nx-conf-2023-recap-53ep</link>
      <guid>https://forem.com/nx/nx-conf-2023-recap-53ep</guid>
      <description>&lt;p&gt;The 3rd edition of &lt;a href="https://nx.dev/conf" rel="noopener noreferrer"&gt;Nx Conf&lt;/a&gt;, this year live from New York City. If you missed the talks, no worries, we've got you covered. This article does a brief recap of all the presentations and has links to the individual recordings and slides.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/P_W8MwX25a0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt; 1. Keynote&lt;br&gt;
 2. Nx Cloud Workflows: Next-Gen CI with First-Class Monorepo Support&lt;br&gt;
 3. United by Nxcellent DX&lt;br&gt;
 4. Redefining Projects with Nx: A Dive into the New Inference API&lt;br&gt;
 5. Package-based to Integrated: One Small Step or One Giant Leap?&lt;br&gt;
 6. Nx't Level Publishing&lt;br&gt;
 7. Lightning Talk: What if your stories were - already - your e2e tests?&lt;br&gt;
 8. Lightning Talk: Nx Cloud Demo&lt;br&gt;
 9. From DIY to DTE - An Enterprise Experience&lt;br&gt;
 10. Vanquishing Deployment Dragons with Nx wizardry&lt;br&gt;
 11. Optimizing your OSS infrastructure with Nx Plugins&lt;br&gt;
 12. Level Up Your Productivity with Nx Console&lt;br&gt;
 13. That's a wrap&lt;/p&gt;
&lt;h2&gt;
  
  
  Keynote
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri Strumpflohner&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/victorsavkin" rel="noopener noreferrer"&gt;Victor Savkin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1CZAN57lNJrN01GRns7TGogge4FBUA0MI/view?usp=drive_link" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; • &lt;a href="https://youtu.be/WSqivWlEDFw" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Juri Strumpflohner (me 😅) opens the keynote. He focuses on the Nx ecosystem, how it is &lt;a href="https://nx.dev/getting-started/why-nx" rel="noopener noreferrer"&gt;much more than just monorepos&lt;/a&gt; by helping you integrate your framework of choice (whether that is Angular, React, or Vue) with tooling such as ESLint, Playwright, Cypress, Webpack, ESBuild, Vite etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqt6paftkfsgq79wutkv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqt6paftkfsgq79wutkv4.png" alt="Nx Ecosystem" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Such integration capabilities really help push the developer productivity, whether that's in single-project workspaces or monorepos.&lt;br&gt;
Juri also dives deeper into efforts from the team to provide high quality educational content around Nx and its capabilities. The &lt;a href="https://nx.dev/docs" rel="noopener noreferrer"&gt;Nx docs&lt;/a&gt; have been restructured to follow the &lt;a href="https://diataxis.fr/" rel="noopener noreferrer"&gt;Diataxis&lt;/a&gt;framework, dividing content into into learning-, task-, understanding- and information-oriented sections.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdl88snysyb75erkms6uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdl88snysyb75erkms6uc.png" alt="Diataxis" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This makes it easier to find keep the content organized and focused and makes it easier for the reader to choose between solution-oriented &lt;a href="https://nx.dev/recipes" rel="noopener noreferrer"&gt;recipes&lt;/a&gt; vs learning-oriented &lt;a href="https://nx.dev/getting-started/tutorials" rel="noopener noreferrer"&gt;tutorials&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Nx team not only produces written content, but also video content mainly on the &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;. Juri shows some of the growth stats, with the channel now having more than 14k subscribers and around 3.7k hours of watch time per month. The channel serves mostly short-form videos about new releases, highlighting new features as well as longer-form tutorial videos.&lt;/p&gt;

&lt;p&gt;The Nx Community also got a special place in the keynote. Juri highlighted in particular the transition from the "Nrwl Community Slack" to the new "Nx Community" on Discord.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cwoxw7vapypehupdgfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cwoxw7vapypehupdgfg.png" alt="Slack to Discord" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discord is built for managing communities and will open up a series of features to come. Things like a built-in forum to ask questions, the ability to highlight Nx events (e.g. the Nx live stream) and having powerful automation and moderation tools. Since the launch a couple of weeks ago, already 1500+ members have signed up. If you didn't sign up yet, go to &lt;a href="https://go.nx.dev/community" rel="noopener noreferrer"&gt;https://go.nx.dev/community&lt;/a&gt;.&lt;br&gt;
Juri also highlighted the &lt;a href="https://nx.dev/community" rel="noopener noreferrer"&gt;Nx Champions&lt;/a&gt; program that got launched this year which helps with efforts to grow the Nx community. The program features members that stood out in the Nx community by helping support others, producing content or speaking at conferences about Nx and related tech.&lt;/p&gt;

&lt;p&gt;Finally there were also two &lt;strong&gt;announcements&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the Nx team decided to move off Medium for a better publishing experience but mainly also to avoid the paywall, something that the team has no control over. The new blog is currently being built and will be hosted at &lt;a href="https://nx.dev/blog" rel="noopener noreferrer"&gt;https://nx.dev/blog&lt;/a&gt;. This also allows to better resurface information by being able to integrate blog articles into the Nx docs search and make them also accessible to the Nx AI Assistant which was the 2nd announcement.&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;Nx AI Assistant&lt;/strong&gt; is an experiment the team is running to use AI to improve discoverability on the Nx docs. The ChatGPT powered assistant allows to ask natural language questions and responds based on the Nx docs training data, also including links to the sources. Try it out at &lt;a href="https://nx.dev/ai-chat" rel="noopener noreferrer"&gt;https://nx.dev/ai-chat&lt;/a&gt; and use the feedback thumbs-up/down buttons to help improve it over time 🙏.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, Nx is open source: &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;https://github.com/nrwl/nx&lt;/a&gt;. Contribute! And while you're there, don't forget to give us a star 😃.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Victor Savkin&lt;/strong&gt; began the second segment of the keynote discussing the hidden expenses that often plague large teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx74fxt68j8w84me5a29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx74fxt68j8w84me5a29.png" alt="Hidden cost of software dev in large teams" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He emphasized that as an organization grows, so does the supporting work. This isn't limited to just communication and management. Every artifact, be it code, process, or otherwise, needs to be assimilated into the broader context. This supporting work becomes intricate and demanding. He pointed out that the remote work trend, while it started with a lot of momentum, struggles in larger corporations because it demands even more coordination and effort. In contrast, smaller entities often outshine their larger counterparts due to the reduced overhead of supporting work.&lt;/p&gt;

&lt;p&gt;One of Victor's main points was the potential of software developers. Given the right tools and environment, they can achieve remarkable feats. CI is one such tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81xtiavk2l86zzrabohw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81xtiavk2l86zzrabohw.png" alt="History of CI" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The state of CI configuration, Victor explained, is essentially a meticulous blueprint of tasks for the CI tool. This blueprint defines everything from the number of machines to their precise roles. Historically, these processes were performed manually, with individuals running test cases and subsequently approving or rejecting them.&lt;/p&gt;

&lt;p&gt;However, scaling CI is a challenge. In larger workspace, up to 50 agents is pretty common, all requiring careful coordination and configuration to ensure tasks run in the correct order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kcmvoohc3hczy1gyv6h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kcmvoohc3hczy1gyv6h.png" alt="Nx distribution CI" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This might be manageable in a static repository setup, but monorepos introduce an added layer of complexity. Here, static "CI recipes" just won't cut it. The result is either an overuse of computational resources, leading to waste of money, or a painfully slow CI.&lt;/p&gt;

&lt;p&gt;Victor critiqued that most current CI setups are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oriented towards machines&lt;/li&gt;
&lt;li&gt;Low-level in their configuration&lt;/li&gt;
&lt;li&gt;Maintenance-heavy&lt;/li&gt;
&lt;li&gt;Detached from developer intentions&lt;/li&gt;
&lt;li&gt;Challenging to implement with monorepos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big question: how can we revolutionize CI? Victor then showcased a demo workspace and highlights where the complexity of setting up CI comes from:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrz8jjd9hu992uwaff1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrz8jjd9hu992uwaff1y.png" alt="CI Complexity" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even running e2e tests on CI requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building the application to be tested to produce an artifact&lt;/li&gt;
&lt;li&gt;That usually requires first building all libraries the app depends on, in the correct order&lt;/li&gt;
&lt;li&gt;Once all libraries are built, the application itself can be build &lt;/li&gt;
&lt;li&gt;Finally e2e can be run on the application artifact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice, since we want to do this as fast as possible, we want to parallelize these operations across machines. This involves also taking care of transferring build artifacts between them.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Nx Cloud Workflows&lt;/strong&gt; shines. It enables developers to draft CI configurations at a far more abstract level. Instead of delving into the minutiae of tasks, developers specify &lt;strong&gt;what&lt;/strong&gt; commands to execute, with the &lt;strong&gt;how&lt;/strong&gt; being implicitly managed by Nx Cloud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;NODE_OPTIONS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--max_old_space_size=4096'&lt;/span&gt;
&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Git Checkout&lt;/span&gt;
    &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nx-cloud-steps/checkout'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Npm Install&lt;/span&gt;
    &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nx-cloud-steps/npm-install'&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI Checks&lt;/span&gt;
    &lt;span class="na"&gt;parallel-scripts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;nx affected -t build e2e --parallel=1&lt;/span&gt;
      &lt;span class="s"&gt;nx affected -t test lint --parallel=3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This elevated abstraction is possible because Nx Cloud &amp;amp; Nx are intimately familiar with the workspace, understanding the interdependencies between projects and tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmvqhzqg2mwjnmgeia14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmvqhzqg2mwjnmgeia14.png" alt="Legacy CI vs Nx Workflows" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond simplifying CI configurations, Nx Cloud Workflows helps optimize computational resource use. Agents are instantiated dynamically based on the project's requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7waqhu5nhtybijyw21a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7waqhu5nhtybijyw21a.png" alt="Agent utilization" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Victor highlighted that most current CI setups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistently utilize a predetermined number of agents, irrespective of the actual needs of the PR&lt;/li&gt;
&lt;li&gt;Possess non-reusable agents since each is tailored to a specific task, like building or testing&lt;/li&gt;
&lt;li&gt;Struggle with granular retries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a metaphor Victor mentions that &lt;strong&gt;Nx Cloud Workflows is to CI what S3 is to file uploads&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohfmgywzvcf4kw99tkhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohfmgywzvcf4kw99tkhl.png" alt="Nx Workflows is to CI what S3 is to file uploads" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sounds interesting? &lt;a href="https://youtu.be/WSqivWlEDFw" rel="noopener noreferrer"&gt;Watch the entire talk here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Cloud Workflows: Next-Gen CI with First-Class Monorepo Support
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; Simon Critchley&lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/18EHfZ4UUtnAlzl15Ul_GPsr5lxNFtEEFPuT1uvxIEAk/edit#slide=id.g28403cda9d5_0_183" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; • &lt;a href="https://youtu.be/JG1FWfZFByM" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simon Critchley (Senior Software Architect at Nx) dives into the more technical details of the newly announced &lt;strong&gt;Nx Cloud Workflows&lt;/strong&gt; (which is in private beta as of this writing).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffewpwyv5htwfh6cq2zho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffewpwyv5htwfh6cq2zho.png" alt="Nx Cloud Workflows" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apart from the distributed caching, Nx Cloud already offers &lt;a href="https://nx.dev/core-features/distribute-task-execution" rel="noopener noreferrer"&gt;DTE (Distributed Task Execution)&lt;/a&gt;, which is a mechanism to seamlessly distribute tasks across various machines to achieve a high degree of parallelism. Up until now it was on you to configure your existing CI in a way to provision machines (agents) to Nx Cloud DTE. This required some fine-tuning to understand the best level of parallelism given the underlying monorepo and tasks that need to be run. If you have too many machines, it'll be wasteful, if you have to few your CI will be slower.&lt;/p&gt;

&lt;p&gt;Nx Cloud Workflow is an advancement of the DTE mechanism, where machines can be automatically provisioned and scaled based on the tasks that need to be run. Essentially it is a replacement for your existing CI but way smarter because it is able to leverage the knowledge it has about the Nx workspace, historical data and can thus do a series of optimizations. Traditional CI systems are running low-level commands on machines. Nx Cloud Workflows is task oriented instead: you tell it to run builds, tests, e2e, linting on the affected projects of the Nx workspace and it figures out how to split them up into fine-grained tasks and then distributes them among dynamically provisioned agents.&lt;/p&gt;

&lt;p&gt;From a developer's perspective, Nx Cloud Workflows are written in Yaml (or alternatively in JSON which is handy if you need to generate them). The format is very similar to existing CI providers to make sure the knowledge you have easily transfers. If you want an example, we're dog-fooding Nx Cloud Workflows on the Nx repo (note the config will change as the product progresses): &lt;a href="https://github.com/nrwl/nx/blob/master/.nx/workflows/agents.yaml" rel="noopener noreferrer"&gt;https://github.com/nrwl/nx/blob/master/.nx/workflows/agents.yaml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simon then dives way deeper into the underlying architecture. In particular, how scheduling in Kubernetes works, which is used at the infrastructure level for Nx Cloud Workflows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrqkexoead4jc7ue64hf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrqkexoead4jc7ue64hf.png" alt="Nx CI Overview" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Workflow scheduling is handled by Kubernetes, specifically through a "Workflow Controller" that interacts with the K8s API Server and triggers Kubernetes Pods. Each Pod contains a Workflow executor and sidecar containers. All containers in the Nx Cloud workflow share a workspace volume for collaborative access. This allows for interesting optimizations in terms of sharing &lt;code&gt;node_modules&lt;/code&gt; and restoring cache results. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz75dfih2ygs5clsnmvtf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz75dfih2ygs5clsnmvtf.png" alt="Nx Cloud Workflow Executor" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Workflow executor, written in Go, is responsible for receiving and executing workflow steps, capturing output, buffering logs, and communicating with the Workflow Controller. It also exposes its own grpc API for distributed locking, file system cache operations, and setting output parameters for each step, ensuring efficient workflow execution.&lt;/p&gt;

&lt;p&gt;Nx Cloud Workflow is in its early development phase. The Kubernetes scheduler supports Docker based executors (basically any Docker image can be used as build image).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt7r5mdks2d068kbgg9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt7r5mdks2d068kbgg9e.png" alt="Supported Platforms" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Windows, macOS and Linux is currently in development which will use a Cloud VM scheduler on the cloud of your choice.&lt;/p&gt;
&lt;h2&gt;
  
  
  United by Nxcellent DX
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/Michael_Hladky" rel="noopener noreferrer"&gt;Michael Hladky&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/1F6_x3Jiu_3b9tZpxQnCrU60Eb1FhYR8E5jVnb1t7DjA/edit?usp=sharing" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; • &lt;a href="https://youtu.be/i0UdoImryJQ" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Michael talks about how to leverage Nx to migrate multiple repositories into a monorepo to streamline development and increase developer productivity. He goes through&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how a project gets started&lt;/li&gt;
&lt;li&gt;how to prep moving to a monorepo from a polyrepo situation&lt;/li&gt;
&lt;li&gt;how to do the move in parallel&lt;/li&gt;
&lt;li&gt;how to measure the progress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project usually starts with an architectural audit. That involves a detailed analysis of the underlying codebase, also including an executive summary for non technical folks. Once the audit is done, the actual move is planned and prepared. A part of that is to define "Nx migration goals", like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Version Policy&lt;/li&gt;
&lt;li&gt;Improved Maintenance&lt;/li&gt;
&lt;li&gt;Shared Infrastructure&lt;/li&gt;
&lt;li&gt;Shared Architecture&lt;/li&gt;
&lt;li&gt;Efficient Task Runs&lt;/li&gt;
&lt;li&gt;Frictionless Code-Sharing&lt;/li&gt;
&lt;li&gt;Frequent Deployments&lt;/li&gt;
&lt;li&gt;Decouple Deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To prioritize which ones to address first, Michael uses the following metaphor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fku5lr79q4qzbzxomnlz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fku5lr79q4qzbzxomnlz7.png" alt="Identifying bad apples in architecture" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important part here is to understand why "apples get bad" in the first place. Is it the harvesting process?&lt;/p&gt;

&lt;p&gt;Once the priorities are defined and roadmap laid out, the goal is to &lt;strong&gt;move in parallel&lt;/strong&gt;.&lt;br&gt;
As part of that move the following gets produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migration Guide&lt;/li&gt;
&lt;li&gt;Training Program&lt;/li&gt;
&lt;li&gt;Communication Strategy&lt;/li&gt;
&lt;li&gt;Impact Measurement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The migration guide defines where to start, what the company goals are, how the deliveries will be integrated into the existing process and how the interaction with the various teams will happen.&lt;/p&gt;

&lt;p&gt;The training program is there to tackle the bottleneck of missing knowledge, right from the beginning. Each stage of the process will have a different training content and collect feedback.&lt;/p&gt;

&lt;p&gt;Finally the impact measurement; Nx Cloud already has graphs to measure how much time got saved in CI due to the improvements made. Michael mentions they go further, also measuring communication and productivity. &lt;/p&gt;

&lt;p&gt;An interesting part is also how they perform the repository synching (from polyrepo to monorepo). They leverage an Nx plugin that&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;contains shared build logic&lt;/li&gt;
&lt;li&gt;has rules to run that produce actionable feedback about what is needed to sync/align the polyrepo repository s.t. it can be merged into the monorepo&lt;/li&gt;
&lt;li&gt;it also allows to track progress and produce according reporting of where the company is at&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds interesting? &lt;a href="https://youtu.be/i0UdoImryJQ" rel="noopener noreferrer"&gt;Watch the entire talk here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Redefining Projects with Nx: A Dive into the New Inference API
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/enderagent" rel="noopener noreferrer"&gt;Craigory Coppola&lt;/a&gt;&lt;br&gt;
&lt;a href="https://craigory.dev/presentations/view/nx-conf-2023-inference/" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; • &lt;a href="https://github.com/AgentEnder/inference-demo" rel="noopener noreferrer"&gt;Demo Repo&lt;/a&gt; • &lt;a href="https://youtu.be/bnjOu7iOrMg" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Craigory did a deep dive into the new Nx inference API. This is particularly interesting if you're developing &lt;a href="https://nx.dev/extending-nx/intro/getting-started" rel="noopener noreferrer"&gt;Nx plugins&lt;/a&gt; or if you have leverage/build some more advanced automation for your Nx workspace.&lt;/p&gt;

&lt;p&gt;What is project inference&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how Nx reads your project configuration&lt;/li&gt;
&lt;li&gt;introduced between v13.3 and v14&lt;/li&gt;
&lt;li&gt;initially to support package-based monorepos which use package.json scripts rather than &lt;code&gt;project.json&lt;/code&gt;. Generalizing the project config reading mechanism also allowed to define an API that community plugins can leverage and which allows to integrate even languages outside the JS ecosystem into Nx (e.g. where projects are just defined differently, such as .Net, Java, Python,..)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inference API v1&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;projectFilePatterns&lt;/code&gt; - identify files that represent the root of a project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;registerProjectTargets&lt;/code&gt; - takes a project file and converts to a list of targets that Nx knows how to run&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shortcomings have been&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;strict 1-1 mapping between project files and projects&lt;/li&gt;
&lt;li&gt;the logic of finding proj files and targets had to be decoupled which introduced potential failure points&lt;/li&gt;
&lt;li&gt;no way to add dynamic metadata to a project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Project graph API v2&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;createNodes&lt;/code&gt; - finds graph nodes based on files on disk&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createDependencies&lt;/code&gt; - finds edges to be added to the graph&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still 2 parts, but there's no overlap between these two and they have very specific purposes. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;createNodes&lt;/code&gt; is a tuple composed of&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;projectFilePattern&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CreateNodesFunction&lt;/code&gt;
It can return a map of projects and external nodes, so there's no more the shortcoming of a 1-1 as it was in v1 API.
With this new setup multiple plugins might detect the same project. Nx merges the configuration that has been identified. Kinda what happens right now if you mix &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;project.json&lt;/code&gt; targets in an Nx workspace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Craigory demoes the inference API by building a spell checking plugin for Nx.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;createDependencies&lt;/code&gt; replaces &lt;code&gt;processProjectGraph&lt;/code&gt;. It is more constrained but mainly because things like adding nodes should be done in a different function now (e.g. &lt;code&gt;createNodes&lt;/code&gt;). This has also advantages for Nx itself, as it knows all nodes will have been created after the &lt;code&gt;createNodes&lt;/code&gt; has terminated.&lt;/p&gt;

&lt;p&gt;This API is still marked as experimental, next steps will be&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mark as stable&lt;/li&gt;
&lt;li&gt;remove v1 API after deprecation period&lt;/li&gt;
&lt;li&gt;plugin authors should start looking into the new API, provide feedback and think about migration scenarios&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Package-based to Integrated: One Small Step or One Giant Leap?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/MannIsaac" rel="noopener noreferrer"&gt;Isaac Mann&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1V1ocFIjYkRrcNXWuvUK1T8dQEceDcjvw/view?usp=drive_link" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://github.com/isaacplmann/space-station-tracker/tree/final" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; · &lt;a href="https://youtu.be/nY0_o7zWBLM" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isaac&lt;/strong&gt; initiated his talk by drawing an analogy between software development and the moon landing. While Neil Armstrong is often singularly celebrated for setting foot on the moon, Isaac emphasized that the monumental achievement was the collective effort of countless individuals on the ground crew, from engineers to support staff.&lt;/p&gt;

&lt;p&gt;Isaac: Nx wants to be that indispensable ground support crew for developers, allowing them to push the boundaries of software development. &lt;/p&gt;

&lt;p&gt;Currently, Nx offers support for two predominant monorepo styles: package-based and integrated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Package-based Monorepos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These are tailored for flexibility and innovation.&lt;/li&gt;
&lt;li&gt;Packages within this setup can have diverse configurations.&lt;/li&gt;
&lt;li&gt;Every package boasts its individual node_modules and dependencies.&lt;/li&gt;
&lt;li&gt;Crucially, each can be upgraded independently, offering a high degree of autonomy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integrated Monorepos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These are structured to prioritize consistency and maintainability.&lt;/li&gt;
&lt;li&gt;Updates within this framework are automated, and the setup adheres to a single-version policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isaac then drew parallels between the Apollo program and the package-based mindset. The Apollo missions were evolutionary in nature, constantly pushing the envelope and embracing innovation with each successive mission. However, this trailblazing approach wasn't without its perils, as evidenced by tragic accidents. This experimental approach was feasible because the core team, responsible for creating the setup, remained consistent throughout the project's duration.&lt;/p&gt;

&lt;p&gt;In contrast, Isaac likened the International Space Station (ISS) to the integrated mindset. The ISS epitomizes the challenges of coordination, given its international collaboration involving numerous countries. Emphasizing longevity, the ISS necessitates that every new crew member be proficient in operating its intricate machinery.&lt;/p&gt;

&lt;p&gt;Shifting gears, Isaac delved into a hands-on demonstration. He outlined the process of transitioning from a package-based monorepo to an integrated one, including demoing&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializing Nx with &lt;code&gt;nx init&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Establishing new projects to facilitate type sharing across applications.&lt;/li&gt;
&lt;li&gt;Harnessing the power of the Nx graph visualization to navigate and understand the project structure.&lt;/li&gt;
&lt;li&gt;Employing the module boundary rule, ensuring constraints are maintained in the revamped structure.&lt;/li&gt;
&lt;li&gt;Devising a novel Nx generator, streamlining the process of setting up new libraries within the workspace.&lt;/li&gt;
&lt;li&gt;Finally, he showcased the seamless upgrade mechanism, ensuring the workspace is always aligned with the latest version.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Nx't Level Publishing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/MrJamesHenry" rel="noopener noreferrer"&gt;James Henry&lt;/a&gt;&lt;br&gt;
&lt;a href="https://main--idyllic-dieffenbachia-3699ec.netlify.app/" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://youtu.be/p5qW5-2nKqI" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;James Henry unveils the new versioning and publishing functionality that is now built into Nx itself.&lt;/p&gt;

&lt;p&gt;Nx has always given you the building blocks to do integrate the versioning and publishing; you could easily use Lerna with Nx, or changesets, release-it as well as a series of Nx Community plugins&lt;br&gt;
The nx core team decided to go into this problem space and provide an opinionated approach that is easy to use within existing Nx workspaces; something that works and scales; also something that works outside the JS ecosystem which Nx can also be used with&lt;/p&gt;

&lt;p&gt;new command &lt;code&gt;nx release&lt;/code&gt;&lt;br&gt;
    - &lt;code&gt;nx release version&lt;/code&gt; to determine and apply version updates&lt;br&gt;
    - &lt;code&gt;nx release changelog&lt;/code&gt; generate a &lt;code&gt;CHANGELOG.md&lt;/code&gt; file and optional GitHub releases based on git commits&lt;br&gt;
    - &lt;code&gt;nx release publish&lt;/code&gt; takes a newly versioned project and publishes them to a remote registry (e.g. NPM)&lt;/p&gt;

&lt;p&gt;this new command is not tight to &lt;code&gt;package.json&lt;/code&gt; files but is general purpose; clearly publishing JS/TS packages is the main use case right now in Nx&lt;br&gt;
Important to note that all the existing plugins are still valid and will still be going forward.&lt;/p&gt;

&lt;p&gt;James goes forward demoing how &lt;code&gt;nx release&lt;/code&gt; works in a simple NPM package: &lt;a href="https://youtu.be/p5qW5-2nKqI?si=xoIW0Q-mQWTGgrek&amp;amp;t=411" rel="noopener noreferrer"&gt;jump directly into the video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nx release can be added to any npm package. All that's needed is the &lt;code&gt;nx&lt;/code&gt; and &lt;code&gt;@nx/js&lt;/code&gt; package and a &lt;code&gt;nx: {}&lt;/code&gt; node in the &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;nx release has a dry-run mode; &lt;code&gt;nx release version --dry-run&lt;/code&gt;. This will output a diff of what version would be created and on which &lt;code&gt;package.json&lt;/code&gt; files (if there are multiple).&lt;br&gt;
The same mechanism also works for the &lt;code&gt;changelog&lt;/code&gt; command, e.g. &lt;code&gt;nx release changelog --dry-run&lt;/code&gt;. In addition to just dry-run, the &lt;code&gt;changelog&lt;/code&gt; command also has an &lt;code&gt;--interactive&lt;/code&gt; mode that allows to get the generated changelog in an interactive editor where you can adjust and add extra stuff.&lt;/p&gt;

&lt;p&gt;James then moves on to show how the release process works in a monorepo scenario using pnpm workspaces, where there are multiple NPM packages that need to be published: &lt;a href="https://youtu.be/p5qW5-2nKqI?si=BvFvRQjgtwOxu-Dv&amp;amp;t=777" rel="noopener noreferrer"&gt;Jump to the video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The monorepo has a &lt;code&gt;pkg-a&lt;/code&gt; and &lt;code&gt;pkg-b&lt;/code&gt; where there's a relationship between them as follows: &lt;code&gt;pkg-a --&amp;gt; pkg-b&lt;/code&gt; .&lt;br&gt;
If the &lt;code&gt;version&lt;/code&gt; command is used in such scenario, it will also be applied to the dependent packages (&lt;code&gt;pkg-b&lt;/code&gt;) since Nx knows about the dependencies via the project graph.&lt;br&gt;
A nice feature is also that the changelog will&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automatically group first by type (e.g. features grouped together, fixes etc)&lt;/li&gt;
&lt;li&gt;within each type grouping it will be grouped by scope such as &lt;code&gt;pkg-a&lt;/code&gt; etc which will be alphabetized&lt;/li&gt;
&lt;li&gt;if there's a fix on the entire repo that'll come first before the per-package changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;nx release changelog --create-release=github&lt;/code&gt; allows to also automatically push the changelog to a Github release.&lt;/p&gt;

&lt;p&gt;When running &lt;code&gt;nx release publish&lt;/code&gt;, Nx also takes into account the right order of how the packages should go on NPM. Like if there's a relationship &lt;code&gt;pkg-a --&amp;gt; pkg-b&lt;/code&gt;, Nx automatically detects such dependency and will go and publish &lt;code&gt;pkg-b&lt;/code&gt; first and then &lt;code&gt;pkg-a&lt;/code&gt; which depends on it. That to make sure that even if there's a network error in between packages, you'd still not break anything.&lt;/p&gt;

&lt;p&gt;Future roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ability to customize how the release works by defining it in &lt;code&gt;nx.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;"release groups" will allow to group packages and define whether versions should be in sync or versioned independently; filter by projects, or even just publish a subset of projects of a workspace&lt;/li&gt;
&lt;li&gt;publishing also automatically takes into account the provenance data on NPM&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Lightning Talk: What if your stories were - already - your e2e tests?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/psybercity" rel="noopener noreferrer"&gt;Katerina Skroumpelou&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1XY8tefqqcM4k4swNPhlSrJiKxurMGiup/view?usp=sharing" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://github.com/mandarini/storybook-play" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; · &lt;a href="https://storybook-play.vercel.app" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt; · &lt;a href="https://youtu.be/SWlvsDNXCsQ" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Katerina starts by introducing the concept of UI testing for error detection, usability verification, regression prevention but also for validating the user journey and making sure the software is reliability.&lt;/p&gt;

&lt;p&gt;Nx had support to use Storybook for doing component-level tests, both using a Cypress e2e setup as well as Cypress component tests. This is where Nx would fill in to launch Storybook to render a single component and then launch Cypress and run dedicated tests against that served component.&lt;br&gt;
Meanwhile Storybook has introduced so-called &lt;a href="https://storybook.js.org/docs/react/writing-tests/interaction-testing/" rel="noopener noreferrer"&gt;Interaction Tests&lt;/a&gt; which allow you to do something similar.&lt;/p&gt;

&lt;p&gt;You can read more on &lt;a href="https://storybook.js.org/docs/react/writing-tests/interaction-testing/" rel="noopener noreferrer"&gt;our docs&lt;/a&gt;. Or check out our &lt;a href="https://youtu.be/SaHoUx-TUs8?si=txUxKcs3cFQWYKxX" rel="noopener noreferrer"&gt;corresponding video&lt;/a&gt; on Youtube.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lightning Talk: Nx Cloud Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/jhannapearce" rel="noopener noreferrer"&gt;Johanna Pearce&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/xc6fJpwk4Lo" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Johanna gives us a tour through the Nx Cloud UI. So there's not much to say other than &lt;a href="https://youtu.be/xc6fJpwk4Lo" rel="noopener noreferrer"&gt;go watch the talk&lt;/a&gt; :)&lt;/p&gt;
&lt;h2&gt;
  
  
  From DIY to DTE - An Enterprise Experience
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; Adrian Baran&lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/1LPgCuYoVEIJqqhk8TLq4RAcHrJ5phJuiHHEGA3y_aws/edit?usp=sharing" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://youtu.be/MsUN0wQHPAs" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adrian Baran&lt;/strong&gt;, a Senior Software Engineer at Cisco, embarked on his talk by presenting the status quo of their monorepo which encompasses approximately 150 projects at the start of the experiment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi26ltq26ktuagtv4rfjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi26ltq26ktuagtv4rfjz.png" alt="Cisco repo stats at beginning" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Their CI workflow is powered by CircleCI. For the purpose of clarity, Adrian zoomed in on the frequently executed tasks: &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;lint&lt;/code&gt;, and &lt;code&gt;test&lt;/code&gt;. To execute these tasks, they leverage the &lt;a href="https://nx.dev/core-features/run-tasks#run-tasks-on-projects-affected-by-a-pr" rel="noopener noreferrer"&gt;Nx affected&lt;/a&gt; command to avoid running all commands on all projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw7csvfyvsbulzeyd8c0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw7csvfyvsbulzeyd8c0.png" alt="Circle scaling" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite that, on average CI runs on PRs still lingered around the 1-hour mark. The immediate remedy? Harnessing CircleCI to parallelize tasks across multiple machines, while continuing to utilize Nx affected. Adrian wrote about that journey in a blog post last year, titled &lt;a href="https://medium.com/@abaran30/nx-affected-circleci-parallelism-faster-ci-cd-pipelines-b4edc4caaaac" rel="noopener noreferrer"&gt;Nx Affected + CircleCI Parallelism = Faster CI/CD Pipelines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;They ended up with a loooot of parallelism:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fld5z8cxfqde7z95q3g2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fld5z8cxfqde7z95q3g2l.png" alt="DIY circleCI" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The outcome was promising though – they witnessed a significant reduction, approximately 75%, in execution time, even in scenarios where all projects were influenced by a PR. Done, right?&lt;/p&gt;

&lt;p&gt;However, as their monorepo burgeoned to encompass 400+ projects, the DIY solution began to show its limitations. The incessant parallelization implied the addition of more agents, leading to escalating costs. Furthermore, they observed considerable variability in task durations. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3p49z57j68qqt0dpqq77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3p49z57j68qqt0dpqq77.png" alt="Running times" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Their workaround was to manually allocate specific tasks to distinct agents. This method in addition to capping on a max number of agents helped keep costs under control, but regrettably, it also compromised performance due to the lowered parallelism.&lt;/p&gt;

&lt;p&gt;This is when Cisco looked into running an &lt;a href="https://nx.app/enterprise" rel="noopener noreferrer"&gt;Nx Enterprise&lt;/a&gt; pilot, specifically with the goal of adopting &lt;a href="https://nx.dev/core-features/distribute-task-execution" rel="noopener noreferrer"&gt;DTE&lt;/a&gt;. In the 2nd part of the talk, Adrian outlined their journey of setting up DTE, starting with the generation of the initial CI setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx g @nx/workspace:ci-workflow --ci=circleci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They tuned the generated configuration, but failed to get it properly running, many of the issues leading to resource exhaustion. As a result, they went the route of going on a 1-1 mapping setup between DIY and DTE. That made sure the DTE setup was as close as possible and allowed for a gradual transition approach, which proved invaluable, allowing them to maintain stability whilst progressively migrating to DTE.&lt;/p&gt;

&lt;p&gt;The comparative analysis of their DIY solution versus DTE revealed roughly equivalent performance metrics. However, the DTE framework shone in its simplicity, maintainability, and resource efficiency, achieving similar outcomes with a 75% reduction in resource utilization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtnl3h94xbejh06da4mf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtnl3h94xbejh06da4mf.png" alt="DTE resource reduction" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adrian's Key Insights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DTE setup warrants a dual-pronged strategy: an immediate plan for initiation and a long-term vision for transition. Notably, Nx DTE supports incremental adoption.&lt;/li&gt;
&lt;li&gt;Patience is paramount during the tuning phase to determine the optimal number of agents.&lt;/li&gt;
&lt;li&gt;While results might vary, Adrian humorously assures that one can always bank on the Nx team for support. 😅&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Vanquishing Deployment Dragons with Nx wizardry
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/meeroslav" rel="noopener noreferrer"&gt;Miroslav Jonas&lt;/a&gt;&lt;br&gt;
&lt;a href="https://speakerdeck.com/meeroslav/vanquishing-deployment-dragons-with-nx-wizardry" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://www.youtube.com/live/IQ5YyEYZw68?si=TQRfAG7CtNbd3Xu4&amp;amp;t=24348" rel="noopener noreferrer"&gt;Jump to the live stream&lt;/a&gt; · &lt;a href="https://youtu.be/jGF8vo2ChfI" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's not much to say here. Lean back and &lt;a href="https://youtu.be/jGF8vo2ChfI" rel="noopener noreferrer"&gt;emerse yourself into the world of dragons and wizards&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing your OSS infrastructure with Nx Plugins
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/brandontroberts" rel="noopener noreferrer"&gt;Brandon Roberts&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/brandonroberts/nx-conf-2023/blob/main/nx-oss-infrastructure.pdf" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://youtu.be/bNuXH25CTO0" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brandon&lt;/strong&gt; discussed his work on the open-source tool Analog and how Nx Plugins are crucial to its development.&lt;/p&gt;

&lt;p&gt;He introduced &lt;a href="https://analogjs.org/" rel="noopener noreferrer"&gt;Analog&lt;/a&gt;, shedding light on its foundational ecosystem and the its core features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzaq3o3xet9wwgmnixg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzaq3o3xet9wwgmnixg6.png" alt="AnalogJS features" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nx plays a crucial role in helping integrate and maintain these different tools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi3xge9lcid4hrvu8mgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi3xge9lcid4hrvu8mgc.png" alt="Analog Ecosystem" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How? Brandon dives straight into it by explaining how Nx plugins in particular can be useful, explaining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Features of Nx plugins such as generators, executors, automated migrations, presets and how to use them just locally to automate your workspace&lt;/li&gt;
&lt;li&gt;how to create a new plugin&lt;/li&gt;
&lt;li&gt;the anatomy of a generator and how they can be useful in scaffolding new setups, but also integrating technology, like adding tRPC to your stack etc&lt;/li&gt;
&lt;li&gt;Similarly Nx executors provide a thin abstraction layer over the actual commands, allowing the plugin developer to update the underlying tooling without necessarily disrupting the end user&lt;/li&gt;
&lt;li&gt;most importantly allowing to write automatic migrations he can leverage with Analog, like running &lt;code&gt;nx migrate @analogjs/platform@latest&lt;/code&gt; to update a given workspace automatically to the latest version, across potentially breaking changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Brandon highlighted a pivotal aspect for OSS package/framework authors: the power to not just assimilate into pre-existing Nx workspaces via custom Nx plugins but also to steer the entire workspace setup process. This is particularly beneficial when tailored setups specific to individual use cases are required. By leveraging an &lt;a href="https://nx.dev/extending-nx/recipes/create-preset" rel="noopener noreferrer"&gt;Nx preset&lt;/a&gt;, one can achieve this tailored configuration. Brandon also touched upon the possibility of advancing further by constructing an &lt;a href="https://nx.dev/extending-nx/recipes/create-install-package" rel="noopener noreferrer"&gt;install package&lt;/a&gt; through Nx.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level Up Your Productivity with Nx Console
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/jcammisuli" rel="noopener noreferrer"&gt;Jonathan Cammisuli&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/MaxKless" rel="noopener noreferrer"&gt;Max Kless&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Cammisuli/nx-conf-2023/tree/main/tools/presentation" rel="noopener noreferrer"&gt;Slides&lt;/a&gt; · &lt;a href="https://youtu.be/TTjVcWCdwVY" rel="noopener noreferrer"&gt;Watch on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jon and Max are the masterminds behind &lt;a href="https://nx.dev/core-features/integrate-with-editors#integrate-with-editors" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;, the Nx IDE extension for Code and JetBrains.&lt;/p&gt;

&lt;p&gt;They mention the release of the JetBrains IDE support earlier this year and give a big shoutout to &lt;a href="https://github.com/iguissouma" rel="noopener noreferrer"&gt;Issam&lt;/a&gt; who was the original author of the Nx Console Webstorm community plugin and who helped a lot with the official Nx Console version for JetBrains IDE.&lt;/p&gt;

&lt;p&gt;Jon and Max demo the new IntelliJ version of Nx console and how it properly integrates as well as how they wrote the new UI completely from the ground up &lt;a href="https://blog.nrwl.io/nx-console-gets-lit-ca339743ff4f" rel="noopener noreferrer"&gt;using Lit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Clearly they did not spare showing off the awesome new graph capabilities built into Nx Console that allow you to directly navigate to files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefokfuf2ydcutxejwfoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefokfuf2ydcutxejwfoj.png" alt="Nx Console Graph" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That's a wrap
&lt;/h2&gt;

&lt;p&gt;If you enjoyed these, make sure you &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;subscribe to our Youtube channel&lt;/a&gt; where we keep releasing educational content and fun videos. &lt;/p&gt;

&lt;p&gt;Also&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;say hi on &lt;a href="https://twitter.com/@nxdevtools" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.nrwl.io/nx-newsletter" rel="noopener noreferrer"&gt;subscribe to our Newsletter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>conferences</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Evergreen Tooling - More than Just CodeMods</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Wed, 26 Jul 2023 13:15:48 +0000</pubDate>
      <link>https://forem.com/nx/evergreen-tooling-more-than-just-codemods-497a</link>
      <guid>https://forem.com/nx/evergreen-tooling-more-than-just-codemods-497a</guid>
      <description>&lt;p&gt;As developers, we always want to use the latest shiny tools. There’s a new bundler? Let’s try! A new code editor, I’m in! For your side-project: for sure! At work: nah, not really. Keeping your tooling up to date with the relatively fast-moving JS ecosystem can be a significant challenge. Nx provides a mechanism that can help mitigate that by providing a command to upgrade your tooling automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Prefer a video? I’ve got you covered!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Ss6MfcXi0jE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;You can run the following command to automatically upgrade your Nx workspace to the latest version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Balancing Act: Updating Tooling vs Shipping Features
&lt;/h2&gt;

&lt;p&gt;If you’re anything like me, you’ve probably found that discussions about updating tooling tend to fall to the bottom of the priority list when talking to your product owner. It’s understandable - their primary goal is to ship features. However, sticking with outdated tooling can impact our ability to deliver these features swiftly (not to speak about potential security concerns due to outdated libraries).&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, I’m not suggesting that we should always be on the bleeding edge of technological innovation - especially in an enterprise environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jason Lengstorf has some opinions there as well: &lt;a href="https://youtu.be/u0j-DlsimZ4" rel="noopener noreferrer"&gt;“The Hidden Danger of Switching Tech Stacks in 2023&lt;/a&gt;?).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s wise to let security patches land and initial bugs get fixed before jumping on the upgrade bandwagon. But here’s the catch - don’t wait too long. The &lt;strong&gt;longer you delay upgrading, the more challenging and time-consuming&lt;/strong&gt; it becomes. And the more effort it requires, the harder it is to sell the idea to your product owner.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Key: Making Updates Easy(ier)!
&lt;/h2&gt;

&lt;p&gt;Updating tooling is never easy, but the Nx team aims at making it “easier” at least. We try to embrace the concept of “evergreen tooling”, a strategy that’s been around since Google decided to automatically update Chrome for all users. The Angular team adopted this approach for their Angular CLI, and Nx has followed suit. But what exactly is it, and how does it work?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if I told you Nx users have been automatically updating their React applications from Webpack 4 to Webpack 5!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The “why” is pretty straightforward. From the perspective of an open-source project, you want users to adopt the latest version as quickly as possible. This minimizes the maintenance work involved in supporting older versions, which can be a real headache. Looking at how Nx manages it, it seems to be successful in this regard (&lt;a href="https://www.craigory.dev/npm-burst/?package=nx" rel="noopener noreferrer"&gt;Source&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3w04kj978mblnshpm4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3w04kj978mblnshpm4t.png" alt="Chart showing the distribution of Nx version installs" width="800" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The distribution of Nx installs by version demonstrates the effectiveness of this approach. For instance, v16.5, which accounts for 19.7% of all versions, has already been adopted by many users, despite &lt;a href="https://nx.dev/changelog#16.5.0" rel="noopener noreferrer"&gt;its recent release&lt;/a&gt;. The latest major accounts for 34.7% already and 41.4% are on the previous v15, a large majority of which is on the latest 15.9 minor. Hence, v16 &amp;amp; v15 make up 3/4 of all Nx installs.&lt;/p&gt;
&lt;h2&gt;
  
  
  How? Database Migration Scripts for Code?
&lt;/h2&gt;

&lt;p&gt;If you know what “database migration scripts” are, then yes, it’s the same concept but applied at the code level. A series of small functions invoked to bring your workspace from version X to version Y (usually the latest). That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;update &lt;code&gt;nx&lt;/code&gt; itself&lt;/li&gt;
&lt;li&gt;update all Nx plugins and the technology they are responsible for (for example: &lt;code&gt;@nx/react&lt;/code&gt; will upgrade React as well, &lt;code&gt;@nx/webpack&lt;/code&gt; is upgrading Webpack)&lt;/li&gt;
&lt;li&gt;automatically adjust relevant config files and source code (e.g., adjusting imports, functions etc..)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything that is required to get you to the latest version and still have a running code, even if there have been breaking changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How?!&lt;/strong&gt; Because the &lt;strong&gt;Nx team (and plugin authors) do the work for you&lt;/strong&gt;! Nx has a built-in mechanism where you can define so-called “migrations” for each Nx package. Here’s an excerpt of the &lt;code&gt;@nx/webpack&lt;/code&gt;'s migration file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;“generators”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"add-babel-inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“cli”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“nx”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“version”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mf"&gt;15.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;-beta.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“description”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“Adds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;babel.config.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;hash&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tasks”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"factory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/migrations/update-15-0-0/add-babel-inputs"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remove-es2015-polyfills-option"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“cli”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“nx”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“version”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mf"&gt;15.4&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="err"&gt;-beta.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“description”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“Removes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;es&lt;/span&gt;&lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="err"&gt;Polyfills&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;since&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;legacy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;browsers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;longer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;supported.”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"factory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/migrations/update-15-4-5/remove-es2015-polyfills-option"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webpack-config-setup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“cli”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“nx”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“version”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mf"&gt;15.6&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;-beta.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“description”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“Creates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;updates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;webpack.config.js&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;webpack.”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"factory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/migrations/update-15-6-3/webpack-config-setup"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"add-babelUpwardRootMode-flag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“cli”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“nx”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“version”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mf"&gt;15.7&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;-beta.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“description”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“Add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;babelUpwardRootMode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;executor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options.”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"factory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/migrations/update-15-7-2/add-babelUpwardRootMode-flag"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"update-16-0-0-add-nx-packages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“cli”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“nx”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;“version”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;-beta.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Replace @nrwl/webpack with @nx/webpack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"implementation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;They are defined in a &lt;code&gt;migrations.json&lt;/code&gt; config file within the NPM package. Each entry defines a &lt;code&gt;version&lt;/code&gt; for which the entry should be run, a &lt;code&gt;description&lt;/code&gt; (just for humans to read) and a &lt;code&gt;factory&lt;/code&gt; property which points to a TypeScript file.&lt;/p&gt;

&lt;p&gt;Example: if you’re on Nx 15.5 and you run &lt;code&gt;nx migrate latest&lt;/code&gt; it would run the corresponding “factory functions” for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;webpack-config-setup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;add-babelUpwardRootMode-flag&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update-16-0-0-add-nx-packages&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the nature of the update, these functions can be as simple as performing text replacements to more complex AST parsing and TypeScript source file manipulations. Let’s have a look at the &lt;code&gt;add-babelUpwardRootMode-flag&lt;/code&gt; migration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  formatFiles,
  readProjectConfiguration,
  Tree,
  updateProjectConfiguration,
} from '@nx/devkit';
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
import { WebpackExecutorOptions } from '../../executors/webpack/schema';

export default async function (tree: Tree) {
  forEachExecutorOptions&amp;lt;WebpackExecutorOptions&amp;gt;(
    tree,
    ‘@nrwl/webpack:webpack’,
    (
      options: WebpackExecutorOptions,
      projectName,
      targetName,
      _configurationName
    ) =&amp;gt; {
      if (options.babelUpwardRootMode !== undefined) {
        return;
      }

      const projectConfiguration = readProjectConfiguration(tree, projectName);
      projectConfiguration.targets[targetName].options.babelUpwardRootMode =
        true;
      updateProjectConfiguration(tree, projectName, projectConfiguration);
    }
  );

  await formatFiles(tree);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It leverages the utility functions provided by the &lt;code&gt;@nx/devkit&lt;/code&gt; package to read the various &lt;code&gt;projects.json&lt;/code&gt; files to adjust the &lt;code&gt;babelupwardRootMode&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Nx’s modular design helps as each plugin is responsible for a particular area and can thus contribute according migration scripts. To give you some context. There is the &lt;a href="https://www.npmjs.com/package/nx" rel="noopener noreferrer"&gt;nx package&lt;/a&gt; at the core - which you can use nicely in combination with a &lt;a href="https://dev.to/nx/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-1eem"&gt;PNPM workspaces repo&lt;/a&gt; to speed things up - and then there are plugins built on top.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonmtkg559cwjyy0s5rff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonmtkg559cwjyy0s5rff.png" alt="Nx Architecture Overview" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Source: &lt;a href="https://nx.dev/getting-started/why-nx" rel="noopener noreferrer"&gt;https://nx.dev/getting-started/why-nx&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These plugins are usually technology-specific, like a plugin to help you manage React, Next, Remix, or Angular projects and tooling like ESLint, Cypress, Playwright, Vite, Jest, and so on. There are no limits as you can &lt;a href="https://nx.dev/extending-nx/intro/getting-started" rel="noopener noreferrer"&gt;create your own&lt;/a&gt;. They are &lt;strong&gt;optional&lt;/strong&gt;, in that you can use Nx and React and set everything up on your own. But it might be worth relying on them for some better DX and automation, such as the update mechanism we’re currently looking at.&lt;/p&gt;

&lt;p&gt;Plugins are helpful here, because each plugin has a clearly defined responsibility. Like the &lt;code&gt;@nx/webpack&lt;/code&gt; we looked at earlier, handles everything related to Webpack. So it’ll be responsible for updating the &lt;code&gt;webpack&lt;/code&gt; NPM package and adjusting config Webpack-related files.&lt;/p&gt;
&lt;h2&gt;
  
  
  Performing the Update
&lt;/h2&gt;

&lt;p&gt;Alright, we’ve learned how these updates work behind the scenes. Let’s look at what the experience looks like as a developer performing the update on your codebase.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note, it is highly recommended to start with a clean Git workspace s.t. you can quickly revert the update.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To run the update, use the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note &lt;code&gt;latest&lt;/code&gt; stands for the target version. You can also provide a specific Nx version if you cannot update to the latest one for some reason.&lt;/p&gt;

&lt;p&gt;At this point, Nx &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;analyzes your workspace and finds all the plugins you’re using&lt;/li&gt;
&lt;li&gt;downloads the version of the plugins specified in the migrate command above&lt;/li&gt;
&lt;li&gt;collects all the &lt;code&gt;migration.json&lt;/code&gt; files from these plugins&lt;/li&gt;
&lt;li&gt;picks out the relevant ones based on your current workspace version&lt;/li&gt;
&lt;li&gt;creates a &lt;code&gt;migrations.json&lt;/code&gt; at the root of your workspace&lt;/li&gt;
&lt;li&gt;updates the &lt;code&gt;package.json&lt;/code&gt; to point to the matching NPM package versions (without performing an install just yet)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now inspect the &lt;code&gt;migration.json&lt;/code&gt; and the &lt;code&gt;package.json&lt;/code&gt; before you run the following command to run the migrations on your codebase.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate —-run-migrations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After that, your codebase should have been updated. Run your (ideally automated) sanity checks and fix the remaining issues that couldn’t be adjusted automatically.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;That’s it! If you want to dive deeper, here are some potentially helpful links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/Ss6MfcXi0jE" rel="noopener noreferrer"&gt;Watch our YT video about Code Migrations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/core-features/automate-updating-dependencies" rel="noopener noreferrer"&gt;https://nx.dev/core-features/automate-updating-dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you haven’t already, give us a ⭐️ on Github: &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;https://github.com/nrwl/nx&lt;/a&gt;. We’d appreciate it 😃.&lt;/p&gt;


&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
    </item>
    <item>
      <title>Nx Cloud 3.0 - Faster Cache, More Powerful DTE, Better Ergonomics</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Wed, 19 Apr 2023 18:25:35 +0000</pubDate>
      <link>https://forem.com/nx/nx-cloud-30-faster-cache-more-powerful-dte-better-ergonomics-18a4</link>
      <guid>https://forem.com/nx/nx-cloud-30-faster-cache-more-powerful-dte-better-ergonomics-18a4</guid>
      <description>&lt;p&gt;It has been almost 2 years since we released &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Nx Cloud 2.0&lt;/a&gt;. Since then, it has saved over 400 years of computation by leveraging its distributed caching and task execution. And we keep adding 8 years every single week. Not only does this tremendously &lt;a href="https://dev.to/nx/helping-the-environment-by-saving-two-centuries-of-compute-time-4nep"&gt;impact our environment&lt;/a&gt;, but it also helps developers be more productive and companies save money.&lt;/p&gt;

&lt;p&gt;In the last couple of months we have quadrupled the team and have done some amazing things. And we have some big plans for what is coming next. Here's all you need to know!&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt; 1. New, Streamlined UI&lt;br&gt;
 2. Prefetching and Faster Cache Uploading&lt;br&gt;
 3. DTE Just got Better&lt;br&gt;
 4. Direct Integration With GitHub, GitLab and Bitbucket&lt;br&gt;
 5. Enterprise Support&lt;br&gt;
 6. New, Simplified Plans and Pricing Model&lt;br&gt;
 7. Coming Next&lt;br&gt;
 8. Learn more&lt;/p&gt;
&lt;h2&gt;
  
  
  Prefer a Video? We've got you Covered!
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/cG2hEI5L3qI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  New, Streamlined UI
&lt;/h2&gt;

&lt;p&gt;This latest release of Nx Cloud comes with a new, streamlined design that offers users a more modern and visually appealing experience. This includes the main &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Nx Cloud website&lt;/a&gt;, where we improved our messaging, including interactive visualizations to better explain some core concepts around remote caching and distributed task execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgy1j7d4o43mnavsmxa7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgy1j7d4o43mnavsmxa7.png" alt="Nx Cloud website screenshot about DTE" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Nx Cloud application - showing your runs, cache saved, and stats - also got a significant overhaul, making the UI more lightweight and easier to parse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfnlqlr935xr5t1qv4ji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfnlqlr935xr5t1qv4ji.png" alt="Screenshot of Nx Cloud run view on the Nx Cloud app" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More UI-related updates and improvements are already underway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefetching and Faster Cache Uploading
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw32cta2wuic0o7c3har.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw32cta2wuic0o7c3har.png" alt="Nx CLI log output when running multiple commands" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At Nx, we are performance addicts! Especially when it comes to local development, every millisecond counts! In the latest update of the Nx CLI, we added the ability to &lt;strong&gt;offload some of the remote cache management to the &lt;a href="https://nx.dev/more-concepts/nx-daemon" rel="noopener noreferrer"&gt;Nx Daemon&lt;/a&gt;&lt;/strong&gt;. As a result you no longer have to wait for the cache to upload. This saves valuable time, allowing the command to complete instantly and immediately providing you with the necessary link.&lt;br&gt;
We also &lt;strong&gt;prefetch cache results in the background&lt;/strong&gt; to have them ready when needed. &lt;/p&gt;

&lt;p&gt;Both optimizations can save seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  DTE Just got Better
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh28te0y4jvw5rjom2luw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh28te0y4jvw5rjom2luw.png" alt="Live visualization on Nx Cloud how tasks are distributed among nodes" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nx.dev/core-features/distribute-task-execution" rel="noopener noreferrer"&gt;Distributed Task Execution (short DTE)&lt;/a&gt; is a core part of what makes Nx Cloud stand out compared to other solutions. And we made some significant improvements to both the ergonomics and speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identify failed tasks early -&lt;/strong&gt; You can now view information about the in-progress DTEs, allowing you to quickly identify and address any failed functions without waiting for the command to complete. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplified CI setup -&lt;/strong&gt; We simplified the setup process for most CI systems, eliminating the need to pass environment variables manually. Instead, everything is automatically derived from the context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved performance and efficiency -&lt;/strong&gt; Nx Cloud now intelligently figures out which tasks will be cache hits before sending them to agents. Rather it can directly send them to the main job, reducing unnecessary round trips and drastically speeding up CI pipeline executions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Efficient agent management -&lt;/strong&gt;  We have introduced a new command, &lt;code&gt;npx nx-cloud start-ci-run –stop-agents-after=e2e&lt;/code&gt;, that allows you to notify Nx Cloud when specific commands, such as long-running e2e tasks, have started. This helps Nx Cloud proactively identify and shut down agents that will not be needed, improving compute efficiency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reduce fix costs -&lt;/strong&gt; Even though cache hits are basically free, spinning processes still have fixed costs. We fixed that (see what I did there) by leveraging a new Nx feature that allows to have a long-running process on an agent to which we can arbitrarily feed new tasks. This removed the DTE overheads and also improved the predictability of runs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Direct Integration With GitHub, GitLab and Bitbucket
&lt;/h2&gt;

&lt;p&gt;Our GitHub integration has been enhanced. Now, the list of runs is updated in real-time as soon as they are created or their status changes, providing developers with up-to-date information directly on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk42bo13baue6jbyakonf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk42bo13baue6jbyakonf.png" alt="Nx Cloud GitHub integration" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to the GitHub, we expanded our Nx Cloud live status updates to work on GitLab and BitBucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5332jj0f6ayivoot6ex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5332jj0f6ayivoot6ex.png" alt="Nx Cloud app integrations with various VCS" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Enterprise Support
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zvunv7l4vcne64183ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zvunv7l4vcne64183ga.png" alt="Enterprise on-prem offer" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have extensive experience working with Fortune 500 companies, helping them scale their development using monorepos. This has given us valuable insight into the unique security requirements of these companies. Our &lt;a href="https://nx.app/enterprise" rel="noopener noreferrer"&gt;Enterprise plan&lt;/a&gt; reflects that allowing organizations to have a &lt;strong&gt;fully self-contained version of Nx Cloud&lt;/strong&gt; that can be &lt;strong&gt;hosted on their own servers&lt;/strong&gt; and comes with dedicated support from the Nx and Nx Cloud core team.&lt;/p&gt;

&lt;p&gt;We've recently made a couple of improvements to our enterprise offering. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Helm Charts -&lt;/strong&gt; We added a &lt;strong&gt;Helm chart&lt;/strong&gt; to simplify the process of deploying Nx Cloud to on-premises infrastructure, allowing organizations to quickly set up and manage their own instance of Nx Cloud within their secure environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability improvements -&lt;/strong&gt; We significantly reworked our on-premises solution to be identical to our SaaS deployment. This revamp resulted in a more robust and reliable on-premises deployment of Nx Cloud, ensuring enterprise-grade performance and reliability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSO -&lt;/strong&gt; We now support AWS Identity and Access Management (IAM) for seamless integration with existing AWS environments and the SAML protocol for a more flexible single sign-on integration across various providers. This enables organizations to leverage their existing identity management systems for authentication and authorization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more at &lt;a href="https://nx.app/enterprise" rel="noopener noreferrer"&gt;https://nx.app/enterprise&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  New, Simplified Plans and Pricing Model
&lt;/h2&gt;

&lt;p&gt;Nx Cloud has evolved a lot since we first released it in 2020, and is changing even more in 2023. To better adapt to Nx Cloud being a critical CI tool, we changed our pricing model to be more consistent and predictable for CI workloads.&lt;/p&gt;

&lt;p&gt;Nx Cloud's previous pricing was based on time savings from Nx Cloud, which made sense when Nx Cloud was strictly a distributed caching service. The &lt;a href="https://nx.app/pricing/" rel="noopener noreferrer"&gt;new pricing model&lt;/a&gt; is based entirely on the number of CI pipeline executions per calendar month. We believe this is a simpler and more transparent model that should help you predict your costs far more easily.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6f0262j38u8kldrdew4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6f0262j38u8kldrdew4.png" alt="Nx Cloud Plans" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our Free plan allows one administrator and up to 300 CI pipeline executions per month. Our Pro plan allows more administrators, and uncapped CI pipeline executions, with a flat fee and incremental charges per 100 CI pipeline executions. The OSS plan comes with unlimited CI pipeline executions. Nx has been open source from the beginning and we care a lot about that ecosystem. So this is our contribution to help OSS projects and make their CI pipeline executions faster. &lt;/p&gt;

&lt;p&gt;Finally, the &lt;strong&gt;Enterprise plan&lt;/strong&gt; is for companies that want full control over where their data is hosted, get hands-on, dedicated support from the Nx &amp;amp; Nx Cloud team, and enterprise features such as SSO &amp;amp; SAML-based authentication support.&lt;/p&gt;

&lt;p&gt;All these changes should allow developers to choose the plan that best suits their needs and budget more easily, ensuring a seamless and transparent experience regarding pricing and subscription management. &lt;/p&gt;

&lt;p&gt;Learn more at &lt;a href="https://nx.app/pricing" rel="noopener noreferrer"&gt;https://nx.app/pricing&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Coming Next
&lt;/h2&gt;

&lt;p&gt;We've got some big plans for Nx Cloud. You really want to write your CI script by focusing on what you want to achieve rather than thinking about making it fast. We're going to make this happen!&lt;/p&gt;

&lt;p&gt;The current Distributed Task Execution (DTE) already goes a long way, but you still have to provision the agents by yourself. Providing the correct number of agents is crucial for maximizing efficiency and reducing idle time. And it is not even a static number but might depend on the actual run itself. Nx has extensive knowledge about the structure of the workspace and according tasks. We want to leverage that information. Imagine a setup where you have a roughly 20 line CI config for a repo with hundreds of developers and Nx Cloud automatically determines for each run the ideal number of agents required, provisions them, distributes all tasks efficiently and then disposes all agents again. All fully automatically. And it will be fast. To the point where you wouldn't even need your Jenkins, CircleCI etc at all.&lt;/p&gt;

&lt;p&gt;In addition, we are actively exploring ways to provide advanced analytics for your workspace, including insights into the frequency and duration of specific tasks. This valuable information can help identify large tasks that could benefit from being broken down into smaller ones, leveraging caching and other speed improvements to optimize performance. Stay tuned for more to come!&lt;/p&gt;


&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Nx Cloud Website&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Website&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
    </item>
    <item>
      <title>Rspack - Getting up to speed with Nx</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Fri, 10 Mar 2023 09:04:57 +0000</pubDate>
      <link>https://forem.com/nx/rspack-getting-up-to-speed-with-nx-56f2</link>
      <guid>https://forem.com/nx/rspack-getting-up-to-speed-with-nx-56f2</guid>
      <description>&lt;p&gt;At Nx, we are excited to see the JavaScript tooling ecosystem evolve, particularly when it comes to improving speed! Performance is at the core of Nx. Faster tools with which we can integrate make our lives easier and allow us to provide a better experience for developers.&lt;/p&gt;

&lt;p&gt;Almost a year ago &lt;a href="https://www.bytedance.com/" rel="noopener noreferrer"&gt;ByteDance&lt;/a&gt; started developing a new, faster Webpack alternative: &lt;strong&gt;Rspack&lt;/strong&gt;. &lt;a href="https://valor-software.com/" rel="noopener noreferrer"&gt;Valor Software&lt;/a&gt; joined the collaboration and reached out to us about developing a dedicated Nx plugin. The goal: give developers an easy onboarding path to Rspack and React!&lt;/p&gt;

&lt;h2&gt;
  
  
  Faster than Webpack? What is Rspack?
&lt;/h2&gt;

&lt;p&gt;Rspack is a rewrite of Webpack with the primary goal of improving performance. Rust is the main language, allowing for a highly parallelized architecture that takes full advantage of modern multi-core CPUs. In addition, it also comes with essential bundling features already built-in to avoid further bottlenecks from 3rd-party packages. It also highly optimizes HMR (Hot Module Replacement) using a specialized incremental compilation strategy.&lt;/p&gt;

&lt;p&gt;ByteDance developed Rspack to solve performance issues they faced when developing and maintaining their internal monolithic applications, all of which rely heavily on complex Webpack configurations. Rspack being a rewrite allows to rely on Webpack's mature architecture and is, at the same time, an easy drop-in replacement.&lt;/p&gt;

&lt;p&gt;ByteDance already applied Rspack on some of their internal business applications and has seen between 5 to 10x improvement in compilation performance.&lt;/p&gt;

&lt;p&gt;More on the official Rspack docs: &lt;a href="https://rspack.dev" rel="noopener noreferrer"&gt;https://rspack.dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting up to speed with Rspack &amp;amp; Nx!
&lt;/h2&gt;

&lt;p&gt;Our goal at Nx is to be the best CLI for your framework of choice. We want to remove friction so developers can easily leverage these new tools and focus on shipping features using a production-ready setup. This is why we developed a dedicated Rspack plugin that lets everyone quickly get up to speed.&lt;/p&gt;

&lt;p&gt;Check out the following video for a complete walkthrough of how Nx and Rspack work together to create production-ready React applications.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/jGTE7xAcg24"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  React Standalone App with Rspack
&lt;/h3&gt;

&lt;p&gt;You can create a new Rspack-based React application using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace myrspackapp --preset=@nrwl/rspack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This creates a pre-configured setup with React, TypeScript, ESLint, Jest (optionally Vite), Cypress for e2e testing, and obviously Rspack as the bundler.&lt;/p&gt;

&lt;p&gt;All the usual Nx features, such as &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev/concepts/affected" rel="noopener noreferrer"&gt;affected commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nx.dev/core-features/cache-task-results" rel="noopener noreferrer"&gt;computation caching&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;remote caching with &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Nx Cloud&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;..work out of the box.&lt;/p&gt;

&lt;p&gt;But not just the "speed features". All the code generators, automate code migrations, and &lt;a href="https://nx.dev/core-features/integrate-with-editors" rel="noopener noreferrer"&gt;code editor extensions&lt;/a&gt; work too.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rspack in an Nx Monorepo
&lt;/h3&gt;

&lt;p&gt;Similarly, you can use Rspack-based applications in existing Nx monorepos. Just install the NPM package:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @nrwl/rspack -D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then generate a new application:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx g @nrwl/rspack:app myrspackapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This creates a new application in your Nx monorepo that uses Rspack as the bundler. You can even import existing React libraries, which can also be an excellent way to experiment with Rspack in an existing production setup.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Go and learn more on the&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;official Rspack website: &lt;a href="https://rspack.dev" rel="noopener noreferrer"&gt;https://rspack.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;learn about the Nx Rspack plugin: &lt;a href="https://nx.dev/packages/rspack" rel="noopener noreferrer"&gt;https://nx.dev/packages/rspack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🦀 &lt;a href="https://nx.dev/packages/rspack" rel="noopener noreferrer"&gt;Rspack and Nx docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🥚 &lt;a href="https://egghead.io/courses/scale-react-development-with-nx-4038" rel="noopener noreferrer"&gt;Free Egghead course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>rspack</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Nx 15.8 - Rust Hasher, Nx Console for IntelliJ, Deno, Node and Storybook</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Wed, 08 Mar 2023 20:35:22 +0000</pubDate>
      <link>https://forem.com/nx/nx-158-rust-hasher-nx-console-for-intellij-deno-node-and-storybook-27ng</link>
      <guid>https://forem.com/nx/nx-158-rust-hasher-nx-console-for-intellij-deno-node-and-storybook-27ng</guid>
      <description>&lt;p&gt;Just weeks after the &lt;a href="https://blog.nrwl.io/nx-15-7-node-support-angular-lts-lockfile-pruning-46f067090711?source=friends_link&amp;amp;sk=fbfb1119ff9369ccaa6e5f9010cbce26" rel="noopener noreferrer"&gt;release of Nx 15.7&lt;/a&gt; (release video &lt;a href="https://www.youtube.com/watch?v=IStJODzZSoc" rel="noopener noreferrer"&gt;here&lt;/a&gt;), the Nx team has now launched Nx 15.8, with exciting new features and enhancements aimed at improving developer experience, productivity, and efficiency. Let's dive straight in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt; 1. Pefer a video? I've got you covered!&lt;br&gt;
 2. Heads-up: Release Live stream tomorrow&lt;br&gt;
 3. Rustifying the Nx Hasher&lt;br&gt;
 4. Deno Support&lt;br&gt;
 5. Nx Console - IntelliJ Support&lt;br&gt;
 6. Nx Console Field Prioritization (x-priority)&lt;br&gt;
 7. Modular Node Applications&lt;br&gt;
 8. Storybook&lt;br&gt;
 9. How to Update Nx&lt;/p&gt;
&lt;h2&gt;
  
  
  Prefer a video? I've got you covered!
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4XdHT5Y7zj4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Heads-up: Release Live stream tomorrow
&lt;/h2&gt;

&lt;p&gt;We have the Nx live stream on Thursday, March 9th at 7 PM CET, to talk about all the features that went into Nx 15.7 and 15.8. So tune in to ask your questions :)&lt;/p&gt;

&lt;p&gt;Enable notifications here:&lt;br&gt;
&lt;a href="https://www.youtube.com/live/P3TinTe3O2g?feature=share" rel="noopener noreferrer"&gt;https://www.youtube.com/live/P3TinTe3O2g?feature=share&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Rustifying the Nx Hasher
&lt;/h2&gt;

&lt;p&gt;Starting with Nx 15.8, we now have a Rust-based Hasher enabled by default!&lt;/p&gt;

&lt;p&gt;Performance is at the core of what we do at Nx. Hence it isn't surprising that Nx is the fastest JS-based monorepo solution out there. We've shown &lt;a href="https://github.com/vsavkin/large-monorepo" rel="noopener noreferrer"&gt;that a couple of times&lt;/a&gt;. But every millisecond counts! As such, we decided to experiment with Rust to see whether we could further optimize our project graph creation as well as the hasher function that is used for the &lt;a href="https://nx.dev/core-features/cache-task-results" rel="noopener noreferrer"&gt;computation cache&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our original implementation used Git to calculate the hash. But it had some downsides as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it didn't work if you don't have or use Git (obviously)&lt;/li&gt;
&lt;li&gt;it didn't work if you used Git submodules&lt;/li&gt;
&lt;li&gt;it became super slow if you had a lot of file changes on your Git working tree, like when switching between branches&lt;/li&gt;
&lt;li&gt;it triggered a lot of &lt;code&gt;execSync&lt;/code&gt; calls to get different git status which was a fragile implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In some situations where we couldn't rely on or use the Git hasher, we did a fallback to a node implementation which made things even slower.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All nice and good, but show me the numbers!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So we did run some experiments on a small repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avg. time for Rust hasher: 17ms&lt;/li&gt;
&lt;li&gt;avg. time for Git hasher: 24ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also tried it on the &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx repository&lt;/a&gt; itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust hasher: 50ms&lt;/li&gt;
&lt;li&gt;Git hasher: 69ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When running these tests on Windows (not WSL), the Nx repo hashing timings turned out to be&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust hasher: 72ms&lt;/li&gt;
&lt;li&gt;Git hasher: 330ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right now, we only observed the Rust hasher to be slightly slower on large repositories when you don't have any changes. Once you start making changes the Git hasher becomes slower again and is overtaken by the Rust version which remains stable in performance.&lt;/p&gt;

&lt;p&gt;An interesting side-effect of using the Rust-based hasher is the size of the generated hashes, which are much smaller and thus allow for a quicker serialization between the &lt;a href="https://nx.dev/more-concepts/nx-daemon" rel="noopener noreferrer"&gt;Nx Daemon&lt;/a&gt; and Nx.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Future work&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While we started with the hasher optimization, the next implementation we’re exploring is using a binary format to communicate between the Nx Daemon and the Nx client. Currently, we serialize the JSON to a string, and pass that through an IPC socket. Using a binary format will significantly speed up the communication here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opting out&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We build the binary for the Rust hasher for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;macOS x64&lt;/li&gt;
&lt;li&gt;macOS arm&lt;/li&gt;
&lt;li&gt;linux arm&lt;/li&gt;
&lt;li&gt;linux gnu&lt;/li&gt;
&lt;li&gt;linux musl&lt;/li&gt;
&lt;li&gt;windows arm64&lt;/li&gt;
&lt;li&gt;windows x64&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As such, it should work on most CI and local developer machines. If we missed something, please reach out an &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;open an issue on GitHub&lt;/a&gt;! In case something breaks though, you can also disable the Rust hasher by using the environment variable &lt;code&gt;NX_NON_NATIVE_HASHER=true&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deno Support
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/NpH8cFSp51E"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Nx Deno support &lt;a href="https://blog.nrwl.io/nx-15-7-node-support-angular-lts-lockfile-pruning-46f067090711?source=friends_link&amp;amp;sk=fbfb1119ff9369ccaa6e5f9010cbce26" rel="noopener noreferrer"&gt;already landed in 15.7&lt;/a&gt;, but didn't make it into the blog post. So here we go: we have a brand new Nx Deno plugin published at &lt;code&gt;@nrwl/deno&lt;/code&gt;. For now, it is experimental and lives in our &lt;a href="https://github.com/nrwl/nx-labs" rel="noopener noreferrer"&gt;labs repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This plugin features the ability to generate Deno applications and libraries inside of an Nx workspace. Obviously, all the other much-loved Nx features such as caching, affected commands and the project graph visualization work out of the box as well.&lt;/p&gt;

&lt;p&gt;To use Deno in an existing Nx workspace, just install the &lt;code&gt;@nrwl/deno&lt;/code&gt; plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @nrwl/deno
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then run the generator to create a new application:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx g @nrwl/deno:app mydenoapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or generate a new library with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx g @nrwl/deno:lib mydenolib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We're excited to see folks welcome in Deno APIs to their Nx workspaces and be able to easily share their Typescript packages across Deno, Node, and web applications, all inside the same monorepo.&lt;/p&gt;

&lt;p&gt;Given this is still experimental, we're more than happy to receive feedback and hear about ways you are using Deno right now and/or plan to use it in an Nx workspace.&lt;/p&gt;

&lt;p&gt;To see some of this in action, be sure to check out our &lt;a href="https://youtu.be/Um8xXR54upQ" rel="noopener noreferrer"&gt;recent livestream with Caleb and Chau&lt;/a&gt;, two of our engineers that have been working on this plugin:&lt;/p&gt;
&lt;h2&gt;
  
  
  Nx Console - IntelliJ Support
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xUTm6GDqwJM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Developer tool CLIs are known for being, well, command-line interfaces. Nx comes with many of such CLI commands for scaffolding projects, running tasks, and more. We wanted to make some of this more approachable, so we introduced Nx Console, an extension to the Visual Studio Code editor. And it turned out to be highly successful. Nx Console now has over 1.2 million downloads on the &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Visual Studio Code marketplace&lt;/a&gt;. We kept improving it over the years, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;adding support for &lt;a href="https://youtu.be/ZST_rmhzRXI" rel="noopener noreferrer"&gt;rendering the Nx graph&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/NxDevTools/status/1573323012476051456" rel="noopener noreferrer"&gt;providing IntelliSense&lt;/a&gt; support for Nx configuration files&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/WfWmK1x52HE" rel="noopener noreferrer"&gt;integrating Nx Cloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the growing popularity, the ask for an equivalent extension for JetBrains' IntelliJ &amp;amp; WebStorm editors got louder and louder. At Nx, we're lucky to have an awesome community.  &lt;a href="https://twitter.com/iguissouma" rel="noopener noreferrer"&gt;Issam Guissouma&lt;/a&gt; and &lt;a href="https://twitter.com/etkachev" rel="noopener noreferrer"&gt;Edward Tkachev&lt;/a&gt; from the Nx community jumped in and provided their implementation of Nx Console for IntelliJ.&lt;/p&gt;

&lt;p&gt;Since our team &lt;a href="https://blog.nrwl.io/from-bootstrapped-to-venture-backed-nx-raises-8-6m-2ae2228eff76" rel="noopener noreferrer"&gt;now works full-time on Nx&lt;/a&gt; and the surrounding tooling, we decided to have a dedicated Nx Console extensions for IntelliJ and WebStorm that is actively maintained and developed by the core team. We reached out to Issam and Edward and started collaborating on it. The result can now be installed from the JetBrains marketplace:&lt;br&gt;
&lt;a href="https://plugins.jetbrains.com/plugin/21060-nx-console" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/21060-nx-console&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read all the details &lt;a href="https://blog.nrwl.io/expanding-nx-console-to-jetbrains-ides-8a5b80fff2d7?source=friends_link&amp;amp;sk=967080ea30bdbf9f8132f098a2cdd188" rel="noopener noreferrer"&gt;on our blog post&lt;/a&gt; or check out our docs page about &lt;a href="https://nx.dev/core-features/integrate-with-editors" rel="noopener noreferrer"&gt;integrating with editors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Nx Console Field Prioritization (x-priority)
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/JJ12zKedwIs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Nx Console has proven a highly valuable tool for exploring Nx generators. Especially if you cannot recall all the various parameters, you can possibly pass. And sure, you could always pass the &lt;code&gt;--help&lt;/code&gt; or browse &lt;a href="https://nx.dev/packages/react/generators/library" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;, but it is just less convenient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz8lquxgehamp34mhbih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz8lquxgehamp34mhbih.png" alt="Nx Generator CLI help" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With a growing number of parameters that a generator can take, it started to get messy and overwhelming. Furthermore, in 80% of the cases, you would probably need the main parameters such as the name, bundler, and directory where to generate the output.&lt;br&gt;
This is the main reason we introduced a &lt;code&gt;x-priority&lt;/code&gt; flag to our generator metadata, to have a way to prioritize certain flags and show them more prominently to the end user. Available values are &lt;code&gt;important&lt;/code&gt; and &lt;code&gt;internal&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The property can be defined for the desired parameters in the generator's &lt;code&gt;schema.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"directory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The directory of the new application."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"x-priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"important"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;All required properties and those marked with an &lt;code&gt;x-priority: important&lt;/code&gt;  will be shown at the top of both, the CLI output (when using &lt;code&gt;--help&lt;/code&gt;) as well as the Nx Console UI. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj3ygduioqi5umgs6ghq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj3ygduioqi5umgs6ghq.png" alt="Decluttered Nx Console UI" width="800" height="813"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read all about it &lt;a href="https://nx.dev/recipes/generators/generator-options" rel="noopener noreferrer"&gt;in the doc about Customizing Generator Options&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Modular Node Applications
&lt;/h2&gt;

&lt;p&gt;Nx has had Node backend support since the very beginning, where you could add an &lt;a href="https://nx.dev/packages/express" rel="noopener noreferrer"&gt;ExpressJS&lt;/a&gt; or &lt;a href="https://nx.dev/packages/nest" rel="noopener noreferrer"&gt;Nest.js&lt;/a&gt; based application to your monorepo. This is a powerful approach as it allows you to colocate your frontend and backend code, which helps share code and, in particular, TypeScript types for your APIs!!&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://blog.nrwl.io/nx-15-7-node-support-angular-lts-lockfile-pruning-46f067090711" rel="noopener noreferrer"&gt;Nx 15.7&lt;/a&gt;, we then announced &lt;a href="https://youtu.be/qEaVzh-oBBc" rel="noopener noreferrer"&gt;Nx Standalone Projects&lt;/a&gt; support for Node. This allows to develop a Node backend in isolation but still leverage all the features from Nx in terms of code generators, automated migrations and obviously speed features such as &lt;a href="https://nx.dev/concepts/affected" rel="noopener noreferrer"&gt;affected commands&lt;/a&gt;, &lt;a href="https://nx.dev/concepts/how-caching-works" rel="noopener noreferrer"&gt;caching&lt;/a&gt; and &lt;a href="https://nx.dev/core-features/distribute-task-execution" rel="noopener noreferrer"&gt;optimized CI setups&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In 15.8, we kept improving our Node support. Our main focus was on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allowing to have a non-bundled output, while still being able to modularize the codebase with local libraries&lt;/li&gt;
&lt;li&gt;generating a pruned lock file when building in production mode&lt;/li&gt;
&lt;li&gt;improving our docker setup to account for non-bundled output and properly install node packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the following video walkthrough on using these features for modularizing a Fastify application:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LHLW0b4fr2w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h2&gt;
  
  
  Storybook
&lt;/h2&gt;

&lt;p&gt;Nx now generates stories using &lt;a href="https://storybook.js.org/blog/storybook-csf3-is-here/" rel="noopener noreferrer"&gt;Component Storybook Format 3 (CSF3)&lt;/a&gt;. If you are using our &lt;code&gt;@nrwl/react:storybook-configuration&lt;/code&gt;, &lt;code&gt;@nrwl/angular:storybook-configuration&lt;/code&gt;, &lt;code&gt;@nrwl/react:stories&lt;/code&gt; and &lt;code&gt;@nrwl/angular:stories&lt;/code&gt; generators, you will notice that the stories are now generated in the new format. You can check out our documentation for &lt;a href="https://nx.dev/packages/storybook/documents/overview-angular#example-files" rel="noopener noreferrer"&gt;Storybook and Angular&lt;/a&gt; or &lt;a href="https://nx.dev/packages/storybook/documents/overview-react#example-files" rel="noopener noreferrer"&gt;Storybook and React&lt;/a&gt; to see the new syntax.&lt;/p&gt;

&lt;p&gt;As the Storybook docs mentions, CSF3 &lt;em&gt;reduces boilerplate code and improves ergonomics. This makes stories more concise, faster to write and easier to maintain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can migrate your existing stories in your Nx workspace to CSF3 using the &lt;a href="https://storybook.js.org/blog/storybook-csf3-is-here/#upgrade-to-csf3-today" rel="noopener noreferrer"&gt;Storybook &lt;code&gt;csf-2-to-3&lt;/code&gt; migrator&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx storybook@next migrate csf-2-to-3 --glob="**/*.stories.ts"`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  How to Update Nx
&lt;/h2&gt;

&lt;p&gt;Updating Nx is done with the following command and will update your Nx workspace dependencies and code to the latest version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After updating your dependencies, run any necessary migrations.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate --run-migrations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🥚 &lt;a href="https://egghead.io/courses/scale-react-development-with-nx-4038" rel="noopener noreferrer"&gt;Free Egghead course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Nx 15.7 - Node Support, Angular LTS, Lockfile Pruning</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Fri, 17 Feb 2023 09:52:51 +0000</pubDate>
      <link>https://forem.com/nx/nx-157-node-support-angular-lts-lockfile-pruning-3m6l</link>
      <guid>https://forem.com/nx/nx-157-node-support-angular-lts-lockfile-pruning-3m6l</guid>
      <description>&lt;p&gt;Here's all you need to know about our latest Nx release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prefer a video? We've got you covered!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/IStJODzZSoc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;10k Subscribers on Youtube&lt;/li&gt;
&lt;li&gt;Updates to our Nx Plugin Guides&lt;/li&gt;
&lt;li&gt;Nx meets Node - First-Class Support landed&lt;/li&gt;
&lt;li&gt;Detaching Angular versions&lt;/li&gt;
&lt;li&gt;Bootstrapping a new Angular app with Standalone API support&lt;/li&gt;
&lt;li&gt;Lockfile parsing and pruning&lt;/li&gt;
&lt;li&gt;Storybook 7.0 beta support&lt;/li&gt;
&lt;li&gt;More flexible Webpack config&lt;/li&gt;
&lt;li&gt;How to Update Nx&lt;/li&gt;
&lt;li&gt;Coming up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10k Subscribers on Youtube
&lt;/h2&gt;

&lt;p&gt;It's almost a tradition to have some stats at the beginning of our Nx release blog posts. This time, about our YT channel: incredibly, we crossed 10k subscribers &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;on our Youtube channel&lt;/a&gt;!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox8xb935v7ptow3j88pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox8xb935v7ptow3j88pv.png" alt="Youtube 10k stats" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apart from delivering high-quality engineering work, we're very invested in producing educational content around developer tooling and monorepos. We've been almost consistently shipping new content every week, whether that is blog posts on the &lt;a href="https://blog.nrwl.io" rel="noopener noreferrer"&gt;Nx blog&lt;/a&gt; or on &lt;a href="https://dev.to/nx"&gt;dev.to&lt;/a&gt; or in the form of new videos and live streams on our channel. Seeing our audience grow on Youtube confirms we're on the right track and gives us new fuel to keep pushing!!&lt;/p&gt;

&lt;p&gt;If you haven't subscribed yet, please do 🙏: &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;https://www.youtube.com/@nxdevtools&lt;/a&gt;. We also announce most of our new videos and live streams &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;on Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to our Nx Plugin Guides
&lt;/h2&gt;

&lt;p&gt;Nx has been designed to be extensible from the ground up. Which is precisely why Nx Plugins are so powerful. They don't just come as part of an Nx integrated monorepo or standalone setup. Still, you can leverage them in the same way to automate your local workspace or even share them as proper Nx plugins with the community.&lt;/p&gt;

&lt;p&gt;Please have a look at our updated guide: &lt;a href="https://nx.dev/plugin-features/create-your-own-plugin" rel="noopener noreferrer"&gt;https://nx.dev/plugin-features/create-your-own-plugin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/zackderose" rel="noopener noreferrer"&gt;Zack&lt;/a&gt; from our team wrote a full in-depth blog post on how &lt;a href="https://blog.nrwl.io/create-your-own-trpc-stack-de42209f83a3" rel="noopener noreferrer"&gt;to create your own stack with tRPC and Nx&lt;/a&gt;. He was also on the &lt;a href="https://www.youtube.com/live/W-9cwIn-YSM?feature=share" rel="noopener noreferrer"&gt;Nx live stream&lt;/a&gt; together with tRPC core member &lt;a href="https://twitter.com/ixahmedxii" rel="noopener noreferrer"&gt;Ahmed Elsakaan&lt;/a&gt;. An edited version of the livestream &lt;a href="https://youtu.be/Wxy898MKguo" rel="noopener noreferrer"&gt;can be found here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx meets Node - First-Class Support landed
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/K4f-fMuAoRY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Due to a lack of time we never invested much more into streamlining the Node experience within Nx, though. This &lt;a href="https://blog.nrwl.io/from-bootstrapped-to-venture-backed-nx-raises-8-6m-2ae2228eff76" rel="noopener noreferrer"&gt;changed now&lt;/a&gt;, which is why we're committed to making Nx the best developer tool for node based apps. Starting with v15.7 we improved support for &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;ExpressJS&lt;/a&gt;, &lt;a href="https://fastify.io" rel="noopener noreferrer"&gt;Fastify&lt;/a&gt; and &lt;a href="https://koajs.com/" rel="noopener noreferrer"&gt;Koa&lt;/a&gt;.&lt;br&gt;
When starting a new Nx workspace, you now have a new option: "Standalone Node Server app".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wv4ds0yiz3aen4qqfri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wv4ds0yiz3aen4qqfri.png" alt="Node Standalone option in create-nx-workspace cmd" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is when you want a single-project Nx workspace to build out your Node backend.&lt;/p&gt;

&lt;p&gt;All the features Nx is known for also apply to backend development. That includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;code generation support&lt;/strong&gt; for all the previously mentioned Node frameworks&lt;/li&gt;
&lt;li&gt;avoiding monolithic codebases via &lt;strong&gt;modularizing it with local libraries&lt;/strong&gt; (with code generation support)&lt;/li&gt;
&lt;li&gt;Ability to &lt;strong&gt;automatically setup a Dockerfile&lt;/strong&gt; for packaging your app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optionally bundle&lt;/strong&gt; your Node app for easy deployment in the case of edge-functions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; via running building, linting, testing for only &lt;strong&gt;(&lt;a href="https://nx.dev/concepts/affected" rel="noopener noreferrer"&gt;affected&lt;/a&gt;) parts of your applications&lt;/strong&gt;, via &lt;a href="https://nx.dev/concepts/how-caching-works" rel="noopener noreferrer"&gt;caching&lt;/a&gt; and &lt;a href="https://nx.dev/core-features/distribute-task-execution" rel="noopener noreferrer"&gt;optimized CI setups&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;the ability to use and/or expand to a monorepo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the first iteration with first-class Node support. But we're already working on a whole set of improvements for the Nx + Node story. So stay tuned!&lt;/p&gt;
&lt;h2&gt;
  
  
  Detaching Angular versions
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/AQV4WFldwlY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The Angular CLI supports a single version of Angular and requires the user to upgrade them together with the help of automated upgrade mechanisms like &lt;code&gt;ng update&lt;/code&gt;. On the other hand, Nx operates on a different release cycle and is independent of Angular versions. However, prior technical limitations resulted in each Nx major version only being compatible with a specific Angular major version. This caused challenges for Angular developers and corporations who were either stuck on an older Angular version or unable to upgrade promptly but still wanted access to the latest and greatest Nx features for increased productivity. &lt;/p&gt;

&lt;p&gt;Starting with v15.7.0, the &lt;code&gt;@nrwl/angular&lt;/code&gt; plugin will support both Angular v14 and v15, and our goal is to continue supporting the Angular LTS versions from Angular v14 onwards.&lt;/p&gt;

&lt;p&gt;New workspaces will always be created with the latest Angular version, but during migration, you can skip some package updates as defined by Nx plugin authors. For Angular, this means you can skip migrating to newer versions. This feature can be enabled by running the following command in an interactive mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nx migrate latest --interactive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When collecting migrations in interactive mode, you'll be prompted to apply any optional migrations, and any updates you choose to skip won't be applied. The rest of the updates will be used as usual. &lt;/p&gt;

&lt;p&gt;If you need to apply an Angular update that you previously skipped, you can collect migrations from an older version of Nx by running:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nx migrate latest --from=nx@&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In particular, we're working on making that part more intuitive in upcoming versions.&lt;/p&gt;

&lt;p&gt;Also, have a look at our &lt;a href="https://nx.dev/recipes/other/advanced-update#choosing-optional-package-updates-to-apply" rel="noopener noreferrer"&gt;updated docs&lt;/a&gt; as well as our &lt;a href="https://nx.dev/packages/angular/documents/angular-nx-version-matrix" rel="noopener noreferrer"&gt;Nx and Angular compatibility matrix&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bootstrapping a new Angular app with Standalone API support
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Hi3aJ0Rlkls"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Angular's new &lt;a href="https://angular.io/guide/standalone-components" rel="noopener noreferrer"&gt;standalone APIs&lt;/a&gt; is exciting as it provides a new, more lightweight way of developing and composing Angular applications without the need for &lt;code&gt;NgModules&lt;/code&gt;. Nx has had the ability to generate new Angular components using the Standalone API for a while. With v15.7, we now also allow you to quickly bootstrap a new single-project Nx workspace with a NgModule-less Angular application.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx create-nx-workspace@latest ngapp 
  --preset=angular-standalone 
  --standaloneApi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Lockfile parsing and pruning
&lt;/h2&gt;

&lt;p&gt;Lockfiles can be highly complex, and different formats across the NPM, Yarn, and PNPM package managers don't make it easier. Nx used to consider the lock-file a black box. Starting with 15.7, this changes! Nx can now properly process the lock-file of all three major package managers (and their different versions!).&lt;/p&gt;

&lt;p&gt;Why is this useful? Glad you asked! Mostly for three reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;more &lt;strong&gt;accurately map the nodes and dependencies&lt;/strong&gt; in the Nx graph (yep the graph also includes npm packages used by every single project)&lt;/li&gt;
&lt;li&gt;generate a &lt;code&gt;package.json&lt;/code&gt; with &lt;strong&gt;precise snapshot of the used versions&lt;/strong&gt; (especially useful in a monorepo with single-version policy)&lt;/li&gt;
&lt;li&gt;ability to &lt;strong&gt;generate a pruned lock-file&lt;/strong&gt; that can be used along-side the &lt;code&gt;package.json&lt;/code&gt; when packaging your app in a Docker container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of our plugins' &lt;code&gt;build&lt;/code&gt; executors include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generatePackageJson&lt;/code&gt; flag (&lt;code&gt;@nrwl/webpack:webpack&lt;/code&gt; and &lt;code&gt;@nrwl/node:webpack&lt;/code&gt;) that automatically generates &lt;code&gt;package.json&lt;/code&gt; and lock file. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generateLockfile&lt;/code&gt; flag (&lt;code&gt;@nrwl/js:swc&lt;/code&gt;, &lt;code&gt;@nrwl/js:tsc&lt;/code&gt; and &lt;code&gt;@nrwl/next:build&lt;/code&gt;) that generates lock file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're an Nx plugin developer, you can generate &lt;code&gt;package.json&lt;/code&gt; and lock file using the following functions from the &lt;code&gt;@nrwl/devkit&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPackageJson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createLockFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nrwl/devkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;projectGraph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createProjectGraphAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;packageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createPackageJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectGraph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lockFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createLockFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// save files using e.g. `fs.writeFileSync`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Stay tuned for a more in-depth blog post coming soon to &lt;a href="https://blog.nrwl.io" rel="noopener noreferrer"&gt;our blog&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Storybook 7.0 beta support
&lt;/h2&gt;

&lt;p&gt;Nx provides support for Storybook version 7.0 beta, with generators and executors, so that you can try it out now, either in a new or in your existing Nx workspace. Storybook version 7 is a major release that brings a lot of new features and improvements. You can read more about it in the &lt;a href="https://storybook.js.org/blog/7-0-beta/" rel="noopener noreferrer"&gt;Storybook 7 beta announcement blog post&lt;/a&gt;. Apart from the new features and enhancements, it also brings some breaking changes. You can read more about them in the &lt;a href="https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-65x-to-700" rel="noopener noreferrer"&gt;Storybook 7 migration docs&lt;/a&gt; and the &lt;a href="https://chromatic-ui.notion.site/Storybook-7-migration-guide-dbf41fa347304eb2a5e9c69b34503937" rel="noopener noreferrer"&gt;Storybook 7 migration guide&lt;/a&gt;. Do note that &lt;em&gt;version 7 is still in beta&lt;/em&gt;, and so is the Nx support for it.&lt;/p&gt;

&lt;p&gt;You can try out Storybook 7.0 beta in a new Nx workspace by passing the &lt;code&gt;--storybook7betaConfiguration&lt;/code&gt; flag when generating the Storybook configuration for your projects. Read more in our &lt;a href="https://nx.dev/packages/storybook/documents/storybook-7-setup" rel="noopener noreferrer"&gt;Storybook 7 setup guide&lt;/a&gt;. If you want to migrate your existing Storybook configuration to Storybook 7.0 beta, please read our &lt;a href="https://nx.dev/packages/storybook/documents/migrate-storybook-7" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  More flexible Webpack config
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/CIT4MFMraXg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Previously when you created a new React application with the Nx &lt;code&gt;@nrwl/react&lt;/code&gt; plugin, the actual Webpack config was hidden within the plugin itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpnm5hqsb7y5i9it0j17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpnm5hqsb7y5i9it0j17.png" alt="Nx old webpack setup" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was for a good reason, but at the same time, it is a thin line to walk between giving more flexibility and ensuring integrity and consistency (not to speak about features such as &lt;a href="https://nx.dev/core-features/automate-updating-dependencies" rel="noopener noreferrer"&gt;automated code migrations&lt;/a&gt;). We wrote a &lt;a href="https://blog.nrwl.io/configuration-files-and-potholes-in-your-codebase-f8e0f9f016c2" rel="noopener noreferrer"&gt;blog post about it last week&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Inspired by our new &lt;a href="https://nx.dev/packages/vite" rel="noopener noreferrer"&gt;Vite setup&lt;/a&gt;, which allows for a more modular configuration in the &lt;code&gt;vite.config.ts&lt;/code&gt;, we wanted to bring some of the same flexibility to our Webpack setup as well. As such, now every Nx Webpack setup (e.g. a new React + Webpack based app) have a &lt;code&gt;webpack.config.js&lt;/code&gt; in the project root. Old project are automatically migrated to this new setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk69kxoo2kinog3v0ml5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk69kxoo2kinog3v0ml5y.png" alt="Nx new webpack config" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to upgrade but still retain the previous behavior, we introduced an &lt;code&gt;isolatedConfig&lt;/code&gt; mode that can be set to &lt;code&gt;false&lt;/code&gt;. More details on our docs: &lt;a href="https://nx.dev/packages/webpack/documents/webpack-config-setup" rel="noopener noreferrer"&gt;https://nx.dev/packages/webpack/documents/webpack-config-setup&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Update Nx
&lt;/h2&gt;

&lt;p&gt;Updating Nx is done with the following command and will update your Nx workspace dependencies and code to the latest version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After updating your dependencies, run any necessary migrations.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx migrate --run-migrations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Coming up
&lt;/h2&gt;

&lt;p&gt;We are currently working on some exciting stuff, including&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deno support&lt;/li&gt;
&lt;li&gt;Improvements to Nx Console, including support for IntelliJ&lt;/li&gt;
&lt;li&gt;NestJS&lt;/li&gt;
&lt;li&gt;Rust 👀&lt;/li&gt;
&lt;li&gt;Nx for non-JS environments&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So keep an eye on our &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Youtube&lt;/a&gt; and &lt;a href="https://blog.nrwl.io" rel="noopener noreferrer"&gt;blog&lt;/a&gt; to not miss those announcements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🥚 &lt;a href="https://egghead.io/courses/scale-react-development-with-nx-4038" rel="noopener noreferrer"&gt;Free Egghead course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Setup React and Tailwind - The Easy Way</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Mon, 13 Feb 2023 10:48:16 +0000</pubDate>
      <link>https://forem.com/nx/setup-react-and-tailwind-the-easy-way-2nb7</link>
      <guid>https://forem.com/nx/setup-react-and-tailwind-the-easy-way-2nb7</guid>
      <description>&lt;p&gt;Developers love to argue about whether Tailwind is good, almost like arguing about code formatting or tabs vs. spaces (I use spaces!!). But whether you love it or hate it, Tailwind has found massive adoption among the frontend developer community. In fact, I'm right now in the process of refreshing and rebuilding my personal site (it will be at &lt;a href="https://juri.dev" rel="noopener noreferrer"&gt;https://juri.dev&lt;/a&gt; soon, so keep an eye on that).&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt; 1. Prefer a video? I've got you covered!&lt;br&gt;
 2. Configuring Tailwind for React&lt;br&gt;
 3. There is an easier way - Code Generators&lt;br&gt;
 4. Generating a Tailwind Setup&lt;br&gt;
 5. That's it!&lt;/p&gt;
&lt;h2&gt;
  
  
  Prefer a video? I've got you covered!
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hHh0xhzSnx8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Tailwind for React
&lt;/h2&gt;

&lt;p&gt;Tailwind has good docs around getting started quickly. There are options to set up Tailwind with their Tailwind CLI, PostCSS, and framework-specific guides.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q3ef6c5aku3otvf2ns3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q3ef6c5aku3otvf2ns3.png" alt="Tailwind docs screenshot installation instructions" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These steps mostly involve&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;installing &lt;code&gt;tailwindcss&lt;/code&gt;, &lt;code&gt;postcss&lt;/code&gt; and &lt;code&gt;autoprefixer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;configuring your &lt;code&gt;tailwind.config.js&lt;/code&gt; to make sure Tailwind can properly "purge" its generated CSS file based on the content files (usually your &lt;code&gt;html&lt;/code&gt;, &lt;code&gt;[j|t]sx&lt;/code&gt;, &lt;code&gt;[t|j]s&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;adjusting your main CSS file to include the Tailwind base classes (in case you want to use Tailwind also in your CSS files, a heated topic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;One important thing:&lt;/strong&gt; if you use &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create-React-App&lt;/a&gt; you might want to check out &lt;a href="https://tailwindcss.com/docs/guides/create-react-app" rel="noopener noreferrer"&gt;what the Tailwind docs say&lt;/a&gt; first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0afcnevhyuouu61eolu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0afcnevhyuouu61eolu8.png" alt="Tailwind docs CRA warning" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This came up a couple of weeks ago due to a &lt;a href="https://github.com/reactjs/reactjs.org/pull/5487" rel="noopener noreferrer"&gt;PR opened on the CRA repo&lt;/a&gt; asking to kinda deprecate it as the main choice for new React projects. I couldn't help but share my opinion on this as well:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/fkTz6KJxhhE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And so did also &lt;a href="https://youtu.be/2OTq15A5s0Y" rel="noopener noreferrer"&gt;Fireship&lt;/a&gt; and ultimately &lt;a href="https://github.com/reactjs/reactjs.org/pull/5487#issuecomment-1409720741" rel="noopener noreferrer"&gt;Dan Abramov&lt;/a&gt;. Anyway, if you're in the &lt;strong&gt;"CRA situation", read on&lt;/strong&gt;. There's a way to get unblocked there.&lt;/p&gt;

&lt;h2&gt;
  
  
  There is an easier way - Code Generators
&lt;/h2&gt;

&lt;p&gt;Code generators speed up such configuration tasks. They are valuable for scaffolding the initial project structure and adding new features to the app setup, such as Tailwind.&lt;/p&gt;

&lt;p&gt;Nx has such generators. To use them, you need an Nx-based React setup. If you're starting new, you can create an &lt;a href="https://nx.dev/getting-started/react-standalone-tutorial" rel="noopener noreferrer"&gt;Nx Standalone React project&lt;/a&gt; easily using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx create-nx-workspace reactapp --preset=react-standalone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqovccyo2uvczcqn79ha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqovccyo2uvczcqn79ha.png" alt="Nx react bundler choice" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, this allows you to choose which bundler to use as well as other options (such as the CSS setup). Again, this is already such a code generator that creates this initial project scaffold.&lt;/p&gt;

&lt;p&gt;Alternatively, &lt;strong&gt;if you happen to use CRA already&lt;/strong&gt;, you can easily convert to an Nx and Vite (or also Webpack) based setup by running:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx nx@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can pass &lt;code&gt;--vite=false&lt;/code&gt; if you still want to keep the Webpack configuration or pass &lt;code&gt;--integrated&lt;/code&gt; if you already plan to have a monorepo instead of a single-project setup. The &lt;a href="https://nx.dev/recipes/adopting-nx/migration-cra" rel="noopener noreferrer"&gt;Nx docs go into more detail here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Generating a Tailwind Setup
&lt;/h2&gt;

&lt;p&gt;Once you have a &lt;a href="https://nx.dev/getting-started/react-standalone-tutorial" rel="noopener noreferrer"&gt;Nx-based React&lt;/a&gt; setup, adding Tailwind is as easy as running:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx nx g @nrwl/react:setup-tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This launches a generator that will guide you through the setup. It works &lt;strong&gt;not only for Nx React-based projects&lt;/strong&gt;, but &lt;strong&gt;also if you use Next.js&lt;/strong&gt; in an Nx workspace.&lt;/p&gt;

&lt;p&gt;You'll get&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tailwind, PostCSS, and Autoprefixer installed&lt;/li&gt;
&lt;li&gt;Tailwind configured together with PostCSS&lt;/li&gt;
&lt;li&gt;your main &lt;code&gt;styles.css&lt;/code&gt; file updated with the Tailwind base classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovvoiwotce986zvjnnuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovvoiwotce986zvjnnuy.png" alt="Nx React Tailwind setup result" width="800" height="527"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  That's it!
&lt;/h2&gt;

&lt;p&gt;You should be all setup and ready now! Here are some related resources to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev/getting-started/react-standalone-tutorial" rel="noopener noreferrer"&gt;Nx docs: React Standalone tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/react-tutorial/1-code-generation" rel="noopener noreferrer"&gt;Nx docs: React Monorepo tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/fkTz6KJxhhE" rel="noopener noreferrer"&gt;Youtube: Is CRA Dead&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/recipes/adopting-nx/migration-cra" rel="noopener noreferrer"&gt;Nx docs: Migrate CRA to React and Vite&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🥚 &lt;a href="https://egghead.io/courses/scale-react-development-with-nx-4038" rel="noopener noreferrer"&gt;Free Egghead course&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>react</category>
      <category>webdev</category>
      <category>tailwindcss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>React, Vite and TypeScript: Get started in under 2 minutes</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Thu, 12 Jan 2023 15:48:24 +0000</pubDate>
      <link>https://forem.com/nx/react-vite-and-typescript-get-started-in-under-2-minutes-56f</link>
      <guid>https://forem.com/nx/react-vite-and-typescript-get-started-in-under-2-minutes-56f</guid>
      <description>&lt;p&gt;Let's be honest. Dealing with tooling is not something enjoyable if you have to deliver code. It should just work and not be in the way. So let's explore how to kickstart your next React project using Vite, in under 2 minutes, without worrying about the setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt; 1. How do I create a new project setup?&lt;br&gt;
 2. Running, building and testing the app&lt;br&gt;
 3. Building the app&lt;br&gt;
 4. Testing the app&lt;br&gt;
 5. Running integration tests with Cypress&lt;br&gt;
 6. Linting&lt;br&gt;
 7. Customize Vite and Vitest&lt;br&gt;
 8. Hidden gem: Caching&lt;br&gt;
 9. Hidden gem: Easily modularize your app&lt;br&gt;
 10. Hidden gem: Visualize your architecture&lt;br&gt;
 11. Hidden gem: Guard your boundaries&lt;br&gt;
 12. Hidden gem: Just run what changed&lt;br&gt;
 13. Hidden gem: A dedicated Editor extension&lt;br&gt;
 14. Hidden gem: Automated Upgrades&lt;br&gt;
 15. Using CRA? Automatically migrate to Vite + Nx&lt;br&gt;
 16. Conclusion&lt;br&gt;
 17. Learn more&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/fkTz6KJxhhE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Traditionally, you might lean towards &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create-React-App (CRA)&lt;/a&gt; started to do precisely that. But what if I told you there's a better alternative, providing&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;not just scaffolding for the initial setup but helping you along the way to generate components, routing, etc&lt;/li&gt;
&lt;li&gt;automatically sets you up with best practices tools for e2e testing, unit testing, code formatting, and linting&lt;/li&gt;
&lt;li&gt;has built-in support for Vite and Vitest (alternatively Webpack &amp;amp; Jest)&lt;/li&gt;
&lt;li&gt;caches your scripts to speed up things&lt;/li&gt;
&lt;li&gt;helps you modularize your application&lt;/li&gt;
&lt;li&gt;comes with automated upgrade features to keep your tooling evergreen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm talking about &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx&lt;/a&gt;. Nx comes with a set of plugins that come with code generation abilities and help abstract some of the lower-level tooling setups. And this can be really interesting for the use case we wanna tackle today.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reader:&lt;/strong&gt; "Wait a minute, I heard about Nx. Isn't that for monorepos?"&lt;br&gt;
&lt;strong&gt;Me:&lt;/strong&gt; "Yeah you're right. But in 15.3 they introduced something called 'standalone apps'"&lt;br&gt;
&lt;strong&gt;Reader:&lt;/strong&gt; "Standalone?"&lt;br&gt;
&lt;strong&gt;Me:&lt;/strong&gt; "Yeah, a fancy term for a setting up a single app and allows for some cool modularization. There's a video introducing that feature here: &lt;a href="https://youtu.be/qEaVzh-oBBc" rel="noopener noreferrer"&gt;https://youtu.be/qEaVzh-oBBc&lt;/a&gt;"&lt;br&gt;
&lt;strong&gt;Reader:&lt;/strong&gt; "ha, interesting 🤔"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's go and set up our &lt;strong&gt;React + Vite + TypeScript project&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I create a new project setup?
&lt;/h2&gt;

&lt;p&gt;To set up a new project, just invoke the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-nx-workspace@latest awesomereactapp &lt;span class="nt"&gt;--preset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;react-standalone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note &lt;code&gt;awesomereactapp&lt;/code&gt; is the name of the app and folder being created, and &lt;code&gt;--preset=react-standalone&lt;/code&gt; tells Nx which template to use when scaffolding the initial setup. You can also invoke it like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace@latest awesomereactapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And then choose the option you prefer in the terminal prompt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpe1tec94oaj2xweklky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpe1tec94oaj2xweklky.png" alt="New standalone app option when creating a new workspace" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, what you'll get is the following structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvbam2jo7dbp2r2yw2e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvbam2jo7dbp2r2yw2e6.png" alt="React + Vite setup structure" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Running, building and testing the app
&lt;/h2&gt;

&lt;p&gt;First off, let's run our new, shiny application. Just invoke&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And in a matter of milliseconds, your app should be served at &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm start&lt;/code&gt; just invokes the script defined in the  &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nx serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nx build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nx test"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Internally this delegates to &lt;code&gt;nx serve&lt;/code&gt;, where &lt;code&gt;serve&lt;/code&gt; is the &lt;a href="https://nx.dev/reference/glossary#target" rel="noopener noreferrer"&gt;Nx target&lt;/a&gt; to be invoked. You can find those in the &lt;code&gt;project.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;project.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/nx/schemas/project-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sourceRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"projectType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"executor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nrwl/vite:dev-server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"defaultConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"buildTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp:build"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"buildTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp:build:development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"hmr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"buildTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp:build:production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"hmr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is where you can see all the targets available for a given project, and you can &lt;a href="https://youtu.be/iygb-KhAeik" rel="noopener noreferrer"&gt;add your own&lt;/a&gt;! In a Nutshell, an Nx target contains&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;executor&lt;/code&gt; - a function (here &lt;code&gt;dev-server&lt;/code&gt;) exposed by the plugin (here &lt;code&gt;@nrwl/vite&lt;/code&gt;) to run the task at hand. Think of it as the wrapper of your usual Npm scripts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;options&lt;/code&gt; - this is where you can pass options to the &lt;code&gt;executor&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configurations&lt;/code&gt; - allows you to create different versions of the &lt;code&gt;options&lt;/code&gt; . You control which configuration is used by passing it via the &lt;code&gt;--configuration=production&lt;/code&gt; flag to your commands. Also, note the &lt;code&gt;defaultConfiguration&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can go more in-depth if you want on the &lt;a href="https://nx.dev/plugin-features/use-task-executors" rel="noopener noreferrer"&gt;Nx docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building the app
&lt;/h2&gt;

&lt;p&gt;Just in the same way as serving our web app, we can build it with&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This places an output into a &lt;code&gt;dist&lt;/code&gt; folder. Now that we've seen the &lt;code&gt;project.json&lt;/code&gt; targets, you probably guessed that you could customize that output folder directly in those settings.&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing the app
&lt;/h2&gt;

&lt;p&gt;This setup also comes with testing baked in using &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;. And you probably guessed it, you can just run tests as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Running integration tests with Cypress
&lt;/h2&gt;

&lt;p&gt;You might have noticed the &lt;code&gt;e2e&lt;/code&gt; folder. That's a fully-functioning setup of &lt;a href="https://cypress.io" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; for doing integration-level or even full end-to-end tests.&lt;/p&gt;

&lt;p&gt;This is excellent because you don't have to configure anything at all. No need to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cypress configured to use Vite (instead of Webpack)&lt;/li&gt;
&lt;li&gt;set up linting for the e2e project (yes writing good quality test code is just as important)&lt;/li&gt;
&lt;li&gt;spinning up our development server manually first that serves our React app such that we can load it in our Cypress tests environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All we need to do is to use&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx e2e e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This might look weird initially, but basically, we run the &lt;code&gt;e2e&lt;/code&gt; target (see &lt;code&gt;e2e/project.json&lt;/code&gt;) on the &lt;code&gt;e2e&lt;/code&gt; project.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;e&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;e/project.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e2e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"../node_modules/nx/schemas/project-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sourceRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e2e/src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"projectType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"e2e"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"executor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nrwl/cypress:cypress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"cypressConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e2e/cypress.config.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"devServerTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp:serve:development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"testingType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e2e"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"devServerTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesomereactapp:serve:production"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By default, these tests run in headless mode, but you can pass &lt;code&gt;--watch&lt;/code&gt; to run it interactively with the Cypress test runner such that the tests get re-executed whenever we change our source.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want Cypress Component testing? There's an Nx generator that can help set that up. Check out the docs: &lt;a href="https://nx.dev/packages/react/generators/cypress-component-configuration" rel="noopener noreferrer"&gt;https://nx.dev/packages/react/generators/cypress-component-configuration&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Linting
&lt;/h2&gt;

&lt;p&gt;And similarly, linting can be triggered by running the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There's a &lt;code&gt;.eslintrc.json&lt;/code&gt; file already at the workspace's root that contains some best practices rules.&lt;/p&gt;
&lt;h2&gt;
  
  
  Customize Vite and Vitest
&lt;/h2&gt;

&lt;p&gt;The project setup is made in a way that you can easily customize your &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; and &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt; setup. Just open the pre-generated &lt;code&gt;vite.config.ts&lt;/code&gt; at the root of your workspace and add custom Vite plugins or fine-tune Vitest.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;reference types="vitest" /&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;viteTsConfigPaths&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-tsconfig-paths&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;viteTsConfigPaths&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="c1"&gt;// vitest config&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./node_modules/.vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Hidden gem: Caching
&lt;/h2&gt;

&lt;p&gt;Nx is known for its caching that helps optimize the speed in monorepos. Caching takes the inputs (the command, source files, environment variables...) and computes a hash.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1esq669veju641f7adx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1esq669veju641f7adx.png" alt="How Caching works in Nx" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On every run, Nx compares that hash against a local cache folder. If the hash exists, Nx restores the command line output and potential artifacts (JS, CSS,... files) produced by a previous run. This helps speed up computation because you don't run it if you don't need to.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;See Nx the docs for more info: &lt;a href="https://nx.dev/concepts/how-caching-works" rel="noopener noreferrer"&gt;https://nx.dev/concepts/how-caching-works&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this obviously makes a lot of sense in a monorepo, it can also help &lt;strong&gt;speed up single-project workspaces&lt;/strong&gt;. Most projects have multiple targets, such as &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;lint&lt;/code&gt;. These can be cached! Imagine you have a PR where you change some &lt;code&gt;*.spec.ts&lt;/code&gt; files because you add a test or fix some. Your CI script probably runs all the targets (&lt;code&gt;build&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;lint&lt;/code&gt;) all the time. And it should totally do that. But you could avoid the &lt;code&gt;build&lt;/code&gt; step because your spec file should not influence that outcome. As such, it could be restored from the cache. &lt;code&gt;test&lt;/code&gt; needs to run and potentially also &lt;code&gt;lint&lt;/code&gt; if you run linting also for spec files.&lt;/p&gt;

&lt;p&gt;You can fine-tune what goes into the cache for each command. &lt;a href="https://nx.dev/more-concepts/customizing-inputs" rel="noopener noreferrer"&gt;More on the Nx docs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hidden gem: Easily modularize your app
&lt;/h2&gt;

&lt;p&gt;Imagine a storefront application. You will probably have domain areas like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product list - which would have facilities for listing all currently available products, their ratings, user reviews etc&lt;/li&gt;
&lt;li&gt;Orders - for viewing your currently open orders as a user or browsing past orders. Things like placing a new order or triggering a refund on a previously acquired product&lt;/li&gt;
&lt;li&gt;Payments - for handling the payment flow, asking for the credit card, triggering the payment, and starting the order placement process once the payment is successful&lt;/li&gt;
&lt;li&gt;Authentication - which handles the whole signup/login flow and provides lower-level utilities for other domain areas in the app, like getting access to the current user.&lt;/li&gt;
&lt;li&gt;User Profile - which manages everything user related. Think of it when you access Amazon and go to your account. Things like managing your addresses&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're just scratching the surface here. This can become big quickly. The only way to manage such a structure with the current tooling (including CRA) is to organize these domains in folders. So you'd have something like this in a CRA setup:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cra-app
  ├─ public/
  ├─ src/
  │   ├─ authentication/
  │   │  ├─ current-user/
  │   │  │   ├─ ...
  │   │  │   └─ index.ts
  │   │  ├─ login/
  │   │  └─ signup/
  │   ├─ orders/
  │   │   ├─ checkout/
  │   │   ├─ place-order/
  │   │   ├─ refund/
  │   │   └─ order-list/
  │   ├─ payments/
  │   ├─ products/
  │   ├─ user-profile/
  │   │   ├─ addresses/
  │   │   └─ credit-cards/
  │   ├─ App.css
  │   ├─ App.tsx
  │   ...
  ├─ package-lock.json
  ├─ package.json 
  └─ README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Most devtools (including CRA) force you into a monolithic structure, where you divide your features into folders. Folders are limited in terms of isolation, though; as your application grows, this might quickly go out of hand.&lt;/p&gt;

&lt;p&gt;We can impose a different, stronger structure with Nx by extracting these areas into dedicated libraries or modules. These live side-by-side with your application. Let's say we have a folder named "domains" which contains these domain areas. Then you can easily generate a new library with the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx g @nrwl/react:lib checkout &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;domains/orders/checkout &lt;span class="nt"&gt;--bundler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above command creates a new " checkout " library in the &lt;code&gt;domains/orders/&lt;/code&gt; folder. Here's what it looks like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awesomereactapp
├─ public
│  └─ favicon.ico
├─ src
│  ├─ app
│  ├─ ...
├─ domains
│  └─ orders
│     └─ checkout
│        ├─ src
│        │  ├─ index.ts
│        │  └─ lib
│        │     ├─ domains-orders-checkout.module.css
│        │     ├─ domains-orders-checkout.spec.tsx
│        │     └─ domains-orders-checkout.tsx
│        ├─ tsconfig.json
│        ├─ tsconfig.lib.json
│        ├─ tsconfig.spec.json
│        └─ vite.config.ts
├─ ... 
├─ index.html
├─ package-lock.json
├─ package.json
├─ ...
├─ tsconfig.app.json
├─ tsconfig.base.json
├─ tsconfig.json
├─ tsconfig.spec.json
└─ vite.config.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice the &lt;code&gt;domains/orders/checkout/src/index.ts&lt;/code&gt;: this is the public API of the &lt;code&gt;checkout&lt;/code&gt; library where you can decide what to export and what should remain private within the library. This conscious process of selecting what to expose and what not leads to a much stronger encapsulation than just a folder structure. It also greatly helps with the maintainability aspect as your app grows.&lt;/p&gt;

&lt;p&gt;When generating the library, a TypeScript path mapping is automatically created in the root-level &lt;code&gt;tsconfig.base.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compileOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@awesomereactapp/domains/orders/checkout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"domains/orders/checkout/src/index.ts"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tmp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this way, anything that's being exported from the &lt;code&gt;checkout&lt;/code&gt; library can be consumed like&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@awesomereactapp/domains/orders/checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also just run linting or testing in isolation for these new libraries:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx test domains-orders-checkout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And obviously, caching (as seen previously) would work on these new libraries as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note, &lt;code&gt;domains-orders-checkout&lt;/code&gt; is the unique name of the project, composed by its file structure. You can change the name in the &lt;code&gt;domains/orders/checkout/project.json&lt;/code&gt; if you'd like.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Hidden gem: Visualize your architecture
&lt;/h2&gt;

&lt;p&gt;Another side-effect of splitting up your codebase into libraries is that your code structure and architecture emerge and becomes visible. Nx comes with a &lt;code&gt;graph&lt;/code&gt; command built-in, so you can even visualize it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfe1v8ruhlk1u880u3u7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfe1v8ruhlk1u880u3u7.png" alt="Nx graph visualization of the app structure" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It becomes even more interesting if you select the "Group by folder" checkbox as the domains become visible at that point:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayg1oc0q3rksenmmpyvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayg1oc0q3rksenmmpyvi.png" alt="Folder grouping in Nx graph" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note this is a hypothetical app to demo some of the features of the Nx graph visualization. Some of the connections might only make a little sense.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Hidden gem: Guard your boundaries
&lt;/h2&gt;

&lt;p&gt;Scaling a software product is more than just the initial structuring and modularization. It consists of a constant ongoing process of ensuring modules stay in shape and don't contain any undesired cross-references or circular dependencies. You could leverage the Nx graph to verify that visually, but that doesn't scale.&lt;/p&gt;

&lt;p&gt;To help with that, Nx has a built-in &lt;a href="https://nx.dev/core-features/enforce-project-boundaries" rel="noopener noreferrer"&gt;module boundary lint rule&lt;/a&gt;. Projects can be assigned "tags", like &lt;code&gt;type:domain&lt;/code&gt;, &lt;code&gt;type:utils&lt;/code&gt;, &lt;code&gt;type:shared&lt;/code&gt; and &lt;code&gt;domain:products&lt;/code&gt;, &lt;code&gt;domain:orders&lt;/code&gt;, &lt;code&gt;domain:auth&lt;/code&gt;. These tags can be assigned in the &lt;code&gt;project.json&lt;/code&gt;, like&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;configuration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;here&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"domain:products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type:domain"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Note that &lt;code&gt;type:domain&lt;/code&gt; or &lt;code&gt;domain:products&lt;/code&gt; are really just strings. You can define them however you want.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;code&gt;.eslintrc.base.json&lt;/code&gt; you can then define the rules. Here for instance we're stating that a library of &lt;code&gt;type:utils&lt;/code&gt; can only depend on other utility libraries, while a &lt;code&gt;type:domain&lt;/code&gt; can depend on both, other domain libraries as well as utility libraries.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.eslintrc.base.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"overrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@nrwl/nx/enforce-module-boundaries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"depConstraints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"sourceTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type:utils"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"onlyDependOnLibsWithTags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"type:utils"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"sourceTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type:domain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"onlyDependOnLibsWithTags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"type: domain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type:utils"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"sourceTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"domain:products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"onlyDependOnLibsWithTags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"domain:products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"domain:orders"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If some of these lint rules need to be followed, your editor will show it right in your code, and you can also run lint checks for each PR on CI.&lt;/p&gt;

&lt;p&gt;If you're curious, you can read more here: &lt;a href="https://blog.nrwl.io/mastering-the-project-boundaries-in-nx-f095852f5bf4" rel="noopener noreferrer"&gt;https://blog.nrwl.io/mastering-the-project-boundaries-in-nx-f095852f5bf4&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hidden gem: Just run what changed
&lt;/h2&gt;

&lt;p&gt;In such a modular structure (as shown above) where your code is organized in smaller modules/libraries, it is very common that a given team member just works within a single domain area. Hence, very often PRs just touch a subset of the entire set of libraries. Nx comes with a backed-in command that allows you to take advantage of that on CI, using the so-called "&lt;a href="https://nx.dev/concepts/affected" rel="noopener noreferrer"&gt;affected commands&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;Let's say we make a change in the &lt;code&gt;product-detail&lt;/code&gt; library of our application. This would affect all other libraries that depend on it. You can also visualize it by running&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx affected:graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiq9l4xl8delr9fxbm1zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiq9l4xl8delr9fxbm1zl.png" alt="Graph showing affected Nodes" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run tasks only for the affected areas, use:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx affected:&amp;lt;target&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To make a concrete example, running just tests for those projects:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx affected:test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Hidden gem: A dedicated Editor extension
&lt;/h2&gt;

&lt;p&gt;If you are not the "command line interface type" developer and you'd rather prefer something integrated within your IDE, then there's good news. The Nx core team also ships a dedicated VSCode extension: &lt;a href="https://nx.dev/core-features/integrate-with-editors" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It has a dedicated view within VSCode to trigger common commands, browse the workspace structure and even inline render the graph.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnm1zyka8l1rnvq9oq4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnm1zyka8l1rnvq9oq4l.png" alt="NxConsole graph view" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also comes with contextual menus to quickly access most of the commonly used functionality:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6twk7xpca3prefu8u3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6twk7xpca3prefu8u3i.png" alt="Nx Console context menu for generating a new things" width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a walkthrough video showing some of the powerful capabilities of Nx Console: &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZST_rmhzRXI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h2&gt;
  
  
  Hidden gem: Automated Upgrades
&lt;/h2&gt;

&lt;p&gt;To keep workspaces evergreen, Nx comes with automated code migrations that&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;upgrade your &lt;code&gt;package.json&lt;/code&gt; packages to the next version&lt;/li&gt;
&lt;li&gt;can automatically update your configuration files if necessary&lt;/li&gt;
&lt;li&gt;can automatically update your source files if necessary (in case of breaking changes in the API)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows for smooth transitions even if there are breaking changes. Just run&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Nx gathers the currently installed packages and updates them to the latest version. If a package comes with Nx migration scripts, Nx collects them in a &lt;code&gt;migrations.json&lt;/code&gt; file. You can inspect and then run them. This dramatically helps to keep your project tooling up to date.&lt;/p&gt;

&lt;p&gt;Read more about how &lt;a href="https://nx.dev/core-features/automate-updating-dependencies" rel="noopener noreferrer"&gt;Nx migrations work&lt;/a&gt; on the docs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using CRA? Automatically migrate to Vite + Nx
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zvYb7XCLQzU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you're currently on a &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;CRA&lt;/a&gt; setup, you can easily migrate to an Nx + React + Vite-based setup by running the following command in your CRA project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Read more on the Nx docs: &lt;a href="https://nx.dev/recipes/adopting-nx/migration-cra" rel="noopener noreferrer"&gt;https://nx.dev/recipes/adopting-nx/migration-cra&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If for some reason you cannot migrate to Vite just yet, you can pass &lt;code&gt;--vite=false&lt;/code&gt; to keep a Webpack-based setup for now.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ready? Give it a try:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace mycoolapp --preset=react-standalone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And let us know what you think :)&lt;/p&gt;


&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nrwl Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nrwl Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🥚 &lt;a href="https://egghead.io/courses/scale-react-development-with-nx-4038" rel="noopener noreferrer"&gt;Free Egghead course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧐 &lt;a href="https://nx.app/enterprise" rel="noopener noreferrer"&gt;Need help with Angular, React, Monorepos, Lerna or Nx? Talk to us 😃&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>nx</category>
      <category>react</category>
      <category>vite</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Reflecting on 2022 - The Year in Review</title>
      <dc:creator>Juri Strumpflohner</dc:creator>
      <pubDate>Thu, 29 Dec 2022 18:55:22 +0000</pubDate>
      <link>https://forem.com/nx/reflecting-on-2022-the-year-in-review-i66</link>
      <guid>https://forem.com/nx/reflecting-on-2022-the-year-in-review-i66</guid>
      <description>&lt;p&gt;As clichéd as it is to start a "year in review" post by stating how exciting the year has been... 2022 was an exciting year for Nx! In 2022 we've seen amazing growth in Nx usage, and in the community, we hosted our first in-person event and received our first round of funding so we can focus our efforts on making Nx and Nx Cloud better than ever.&lt;/p&gt;

&lt;p&gt;Here are some 2022 highlights.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launching monorepo.tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31vod399fx7p8km95o4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31vod399fx7p8km95o4n.png" alt="Screenshot of monorepo.tools" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the beginning of 2022, we saw a significant increase in the interest in monorepos, especially in the JavaScript community. Since we had a couple of years of experience in the area, we decided to launch &lt;a href="https://monorepo.tools" rel="noopener noreferrer"&gt;monorepo.tools&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We wanted to make this a place where interested developers can go to get a high-level overview of what a monorepo is about, what features you should be looking for and what tools are available. &lt;/p&gt;

&lt;p&gt;Although we kick-started the page, we reached out to all the mentioned monorepo tool maintainers and got some really good feedback and &lt;a href="https://github.com/nrwl/monorepo.tools/pull/32" rel="noopener noreferrer"&gt;complete PRs to add new tools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  From 1 to 3 Million Weekly Downloads
&lt;/h2&gt;

&lt;p&gt;The popularity of Nx exploded in 2022. We were at 1 million weekly downloads in January 2022, crossed 2 million by end of June, and, as this year comes to a close, we've exceeded 3 million! It's incredible to see such an adoption rate, but it very much motivates us to continue our path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xia8fn9z9xmapmcpho3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xia8fn9z9xmapmcpho3.png" alt="3 million downloads per week" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Nrwl takes over Stewardship of Lerna
&lt;/h2&gt;

&lt;p&gt;Lerna has been around for a long time, and it was actually the first proper solution for implementing JavaScript-based monorepos. Long before NPM/Yarn/PNPM workspaces were a thing. Lerna allowed to easily link packages locally and had first-class support for versioning and publishing monorepo packages.&lt;/p&gt;

&lt;p&gt;Around the summer of 2020 Lerna's development got slower and was mainly on the shoulders of a single developer, doing it in his free time. Lerna was in maintenance mode. At Nx, we added an easy transition with an automated migration script. It was only later around March 2022, that someone merged a PR stating in big letters that Lerna is deprecated and people should migrate to an alternative. Still, Lerna is pretty popular at 1.5 million downloads/week on NPM and developers loved the automated versioning and publishing flow.&lt;/p&gt;

&lt;p&gt;We wanted to keep Lerna alive and reached out to its core maintainer &lt;a href="https://twitter.com/evocateur" rel="noopener noreferrer"&gt;Daniel Stockman&lt;/a&gt; and offered to move it forward. Nx has been open source since the beginning which gives us a lot of experience in managing projects in the open. Furthermore, Nx was already closely aligned with Lerna's functionality (with Lerna providing the added benefit of automated versioning and publishing). And obviously, we saw the potential of being able to easily modernize Lerna with features such as caching. So we did it! If you're curious, we &lt;a href="https://blog.nrwl.io/lerna-is-dead-long-live-lerna-61259f97dbd9?source=friends_link&amp;amp;sk=60349b9dc0be3ff730ad052c4cf69df3" rel="noopener noreferrer"&gt;wrote an in-depth blog post about it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since then,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we released &lt;a href="https://blog.nrwl.io/lerna-5-1-new-website-new-guides-new-lerna-example-repo-distributed-caching-support-and-speed-64d66410bec7?source=friends_link&amp;amp;sk=fc349af13ce1935a7ca149b4f3c123c3" rel="noopener noreferrer"&gt;Lerna v5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;we completely redesigned both the website and docs at &lt;a href="https://lerna.js.org" rel="noopener noreferrer"&gt;https://lerna.js.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;we released &lt;a href="https://blog.nrwl.io/lerna-reborn-whats-new-in-v6-10aec6e9091c?source=friends_link&amp;amp;sk=05bfe6160d197277daab6a14cf94f82f" rel="noopener noreferrer"&gt;Lerna v6&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;and made upgrading a &lt;a href="https://blog.nrwl.io/upgrade-your-lerna-workspace-make-it-fast-and-modern-a8d17c4f95a2?source=friends_link&amp;amp;sk=6171be4f0ea70e81e1fbdef5db2af5e5" rel="noopener noreferrer"&gt;no-brainer&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nx Conf Lite and our first in-person Nx Conf
&lt;/h2&gt;

&lt;p&gt;This year we hosted two events featuring members of the Nx Team and community: &lt;a href="https://youtube.com/playlist?list=PLakNactNC1dGmYYdDqWTMae5YiC_DRrTx" rel="noopener noreferrer"&gt;Nx Conf Lite&lt;/a&gt;, an online mini-conference held in the spring; and &lt;a href="https://youtube.com/playlist?list=PLakNactNC1dGicwFn2Y5L9yYm7kh22wyH" rel="noopener noreferrer"&gt;Nx Conf&lt;/a&gt;, in-person, in Arizona, this past fall. &lt;/p&gt;

&lt;p&gt;Both were a huge success, and we had some fantastic in-depth talks around Nx, Lerna, monorepos and developer tooling. You can check out the recordings here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PLakNactNC1dGmYYdDqWTMae5YiC_DRrTx" rel="noopener noreferrer"&gt;Nx Conf Lite 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=RgPOLDRTHWw&amp;amp;list=PLakNactNC1dGicwFn2Y5L9yYm7kh22wyH" rel="noopener noreferrer"&gt;Nx Conf October 2022&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nx Funding and New Focus on Product Development
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nrwl.io" rel="noopener noreferrer"&gt;Nrwl&lt;/a&gt;, the company behind Nx, is fully bootstrapped. Our work is divided into roughly 80% consulting for some of the biggest companies in the world and 20% open source work on Nx and Nx Cloud.&lt;/p&gt;

&lt;p&gt;Seeing the traction Nx got in 2022, we wanted to invest more and hence in November 2022 we raised the first round of funding of $8.6 million.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvc17d8aigzg1frkza3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvc17d8aigzg1frkza3i.png" alt="Nx funding" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allows us to work mostly full-time on improving Nx and Nx Cloud. And you can see that effect already in our latest 15.3 and 15.4 releases (continue reading for that).&lt;/p&gt;

&lt;p&gt;Here's our official &lt;a href="https://blog.nrwl.io/from-bootstrapped-to-venture-backed-nx-raises-8-6m-2ae2228eff76?source=friends_link&amp;amp;sk=b6e3b9959f2298c3e03b8dbba09b05ea" rel="noopener noreferrer"&gt;fundraising announcement blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Epic Releases
&lt;/h2&gt;

&lt;p&gt;We had some epic releases this year. Want to get a feel for it? Just have a look at our latest &lt;a href="https://blog.nrwl.io/nx-15-3-standalone-projects-vite-task-graph-and-more-3ed23f7827ed?source=friends_link&amp;amp;sk=6f924b58b80f0d46ea1d5fe02f74d8fe" rel="noopener noreferrer"&gt;Nx 15.3&lt;/a&gt; and &lt;a href="https://blog.nrwl.io/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more-77cbf6c9a711?source=friends_link&amp;amp;sk=c5a82dc1872a1892659ceb1497e42aae" rel="noopener noreferrer"&gt;Nx 15.4&lt;/a&gt; releases.&lt;/p&gt;

&lt;p&gt;Here's some more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Improved docs -&lt;/strong&gt; Documentation is hard but extremely important. We invested and kept investing a lot of time in optimizing how we structure our docs to serve newcomers and expert users alike.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed -&lt;/strong&gt; we drastically improved the speed of Nx, making it the &lt;a href="https://github.com/vsavkin/large-monorepo" rel="noopener noreferrer"&gt;fastest monorepo solution&lt;/a&gt; in the frontend space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved terminal output -&lt;/strong&gt; It might not sound as important. But if you run a command in a monorepo it usually involves running it for potentially hundreds of projects. A &lt;a href="https://twitter.com/NxDevTools/status/1520085544008503298" rel="noopener noreferrer"&gt;decent visualization of what's relevant&lt;/a&gt; can make a huge difference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local plugins -&lt;/strong&gt; Making Nx extensible has been a key for our community adoption. But Nx plugins go beyond and can be useful even for just automating a local Nx workspace without publishing the plugin to some public registry. Check out our &lt;a href="https://nx.dev/plugin-features/create-your-own-plugin#local-workspace-plugins" rel="noopener noreferrer"&gt;docs for local plugins&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in Module Federation -&lt;/strong&gt; We added some pretty cool support for working with Webpack module federation. That includes migrating an existing Angular or React app to MF and generating new ones, including SSR support. Explore &lt;a href="https://nx.dev/recipes/module-federation" rel="noopener noreferrer"&gt;our docs for more details&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Massive improvements on Nx Console -&lt;/strong&gt; &lt;a href="https://nx.dev/core-features/integrate-with-editors" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt; exceeded 1 million installations but also experienced some huge improvements. You can now &lt;a href="https://youtu.be/ZST_rmhzRXI" rel="noopener noreferrer"&gt;visualize the graph&lt;/a&gt; from within VSCode, &lt;a href="https://youtu.be/zR2abex3AtY" rel="noopener noreferrer"&gt;autocompletion for config files&lt;/a&gt; and &lt;a href="https://youtu.be/-oPfa7zET1o" rel="noopener noreferrer"&gt;even use it with your Lerna workspace&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Packaged-based and Integrated repositories -&lt;/strong&gt; There are different styles of monorepos: &lt;a href="https://nx.dev/concepts/integrated-vs-package-based" rel="noopener noreferrer"&gt;package-based and integrated&lt;/a&gt;. Nx has been strong with integrated monorepos since the beginning. This year we made Nx a first-class citizen for package-based monorepos as well. Check out the &lt;a href="https://dev.to/nx/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-1eem"&gt;blog post on how to add Nx to a PNPM workspace monorepo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy migration -&lt;/strong&gt; We made migrating to Nx is as easy as running &lt;code&gt;nx init&lt;/code&gt;. Regardless of whether you want to add Nx &lt;a href="https://nx.dev/recipes/adopting-nx/adding-to-monorepo" rel="noopener noreferrer"&gt;to an existing monorepo&lt;/a&gt;, &lt;a href="https://nx.dev/recipes/adopting-nx/migration-cra" rel="noopener noreferrer"&gt;migrating from CRA&lt;/a&gt;, the &lt;a href="https://nx.dev/recipes/adopting-nx/migration-angular" rel="noopener noreferrer"&gt;Angular CLI&lt;/a&gt; or even &lt;a href="https://nx.dev/recipes/adopting-nx/adding-to-existing-project" rel="noopener noreferrer"&gt;a non-monorepo project&lt;/a&gt;. &lt;a href="https://youtu.be/KBFQZw5ynFs?t=314" rel="noopener noreferrer"&gt;More here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standalone apps support -&lt;/strong&gt; Nx's powerful generators, executors and ability to modularize a large codebase are not only valuable for a monorepo scenario. That's the main driver why in Nx 15.3 we introduced "standalone apps". Here's a short video walkthrough: &lt;a href="https://youtu.be/qEaVzh-oBBc" rel="noopener noreferrer"&gt;https://youtu.be/qEaVzh-oBBc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vite support -&lt;/strong&gt; The Vite community is growing fast, and many of our users asked for an Nx plugin coming from the core team. Even though you could use Nx in a package-based monorepo with Vite already, we wanted to make it the best experience for developing React applications with Nx and beyond. Check out &lt;a href="https://nx.dev/packages/vite" rel="noopener noreferrer"&gt;our Vite docs&lt;/a&gt; for all the details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nx Watch -&lt;/strong&gt; Watching for changes in a monorepo (especially package-based) can be tricky or require some weird hacks involving 3rd-party packages. In Nx 15.4 we added a native &lt;code&gt;nx watch&lt;/code&gt; command. See &lt;a href="https://nx.dev/recipes/other/workspace-watching" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And these are just some of the highlights. Want all the details? Check out our release blog posts: &lt;a href="https://blog.nrwl.io/changelog/home" rel="noopener noreferrer"&gt;https://blog.nrwl.io/changelog/home&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to look forward to in 2023
&lt;/h2&gt;

&lt;p&gt;We have some huge plans for 2023 for Nx, Nx Cloud, Lerna, and beyond. Let's make 2023 even more epic than 2022 has been 😉.&lt;/p&gt;

&lt;p&gt;Make sure you follow us on our socials not to miss anything. We are on &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/nrwl" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Youtube&lt;/a&gt;, &lt;a href="https://www.tiktok.com/@nxdevtools" rel="noopener noreferrer"&gt;TikTok&lt;/a&gt;, &lt;a href="https://blog.nrwl.io" rel="noopener noreferrer"&gt;our blog&lt;/a&gt; and &lt;a href="https://dev.to/nx"&gt;dev.to&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nrwl Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nrwl Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you liked this, click the ❤️ and make sure to follow &lt;a href="https://twitter.com/juristr" rel="noopener noreferrer"&gt;Juri&lt;/a&gt; and &lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; on Twitter for more!&lt;/p&gt;


&lt;div class="ltag__tag ltag__tag__id__18643"&gt;
    &lt;div class="ltag__tag__content"&gt;
      &lt;h2&gt;#&lt;a href="https://dev.to/t/nx" class="ltag__tag__link"&gt;nx&lt;/a&gt; Follow
&lt;/h2&gt;
      &lt;div class="ltag__tag__summary"&gt;
        
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>devtools</category>
      <category>monorepos</category>
    </item>
  </channel>
</rss>
