<?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>DEV Community: Nx</title>
    <description>The latest articles on DEV Community by Nx (@nx).</description>
    <link>https://dev.to/nx</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%2Forganization%2Fprofile_image%2F2995%2F95998d2a-00f2-4e8e-9ebc-0b06de97c37f.png</url>
      <title>DEV Community: Nx</title>
      <link>https://dev.to/nx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nx"/>
    <language>en</language>
    <item>
      <title>Monorepos - Why Speed Matters</title>
      <dc:creator>Katerina Skroumpelou</dc:creator>
      <pubDate>Wed, 20 Mar 2024 20:52:22 +0000</pubDate>
      <link>https://dev.to/nx/monorepos-why-speed-matters-chf</link>
      <guid>https://dev.to/nx/monorepos-why-speed-matters-chf</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of software development, efficiency and speed are vital. As projects grow in complexity, developers and teams need tools that can keep up without sacrificing quality or performance.&lt;/p&gt;

&lt;p&gt;Nx is a suite of powerful tools designed to optimize your development workflow, which sets the &lt;a href="https://nx.dev/ci/concepts/building-blocks-fast-ci"&gt;building blocks for a fast CI&lt;/a&gt;. Nx is always innovating in many ways to make developers’ lives easier, but this post is exclusively focused on the things Nx has done in the past year to make development faster and faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why speed matters
&lt;/h2&gt;

&lt;p&gt;The ability to iterate quickly and efficiently is vital for any software project. Speed in the development process offers several critical advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster feedback loops:&lt;/strong&gt; Quick iterations mean immediate feedback, allowing teams to adapt, learn, and improve their work on the fly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced time to market:&lt;/strong&gt; Accelerating the development process can significantly cut down the overall time to market, providing a competitive edge which reclaims revenue that would have otherwise been lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decreased developer frustration:&lt;/strong&gt; &lt;a href="https://nx.dev/ci/concepts/reduce-waste"&gt;No more waiting for builds and tests to complete&lt;/a&gt;. A streamlined workflow keeps morale high and productivity higher.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re using Nx already, you’re already familiar with &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nx.dev/ci/features/affected"&gt;&lt;strong&gt;Affected&lt;/strong&gt;&lt;/a&gt; - identifying and running tasks only on projects impacted by code changes,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nx.dev/ci/features/remote-cache"&gt;&lt;strong&gt;Nx Replay&lt;/strong&gt;&lt;/a&gt; - our powerful cache and&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nx.dev/ci/features/distribute-task-execution"&gt;&lt;strong&gt;Nx Agents&lt;/strong&gt;&lt;/a&gt; - the concept of &lt;a href="https://nx.dev/ci/concepts/parallelization-distribution"&gt;Parallelization and Distribution&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But let’s see all the extra things we did this past year to make everything faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed at the core
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Rustifying Nx
&lt;/h3&gt;

&lt;p&gt;The Nx daemon has seen significant enhancements, notably through the use of Rust to calculate file hashes behind the scenes. This improvement not only speeds up the start-up times but also optimizes performance even without the daemon, especially on CI environments where the daemon isn't used. The benchmark results at &lt;a href="https://github.com/vsavkin/large-monorepo"&gt;this repo&lt;/a&gt; showcase the remarkable speed improvements, making Nx competitive with native code solutions while maintaining the accessibility and flexibility of Node.js. Nx is still Node-first, so contributions are easier and only the most performance-critical parts of Nx are native code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Task Hasher and archive file innovations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The introduction of a task hasher written in Rust, alongside the use of an archive file to store workspace file hashes (&lt;code&gt;.nx/cache&lt;/code&gt;), has significantly reduced the need for repetitive file system accesses. This innovation means that running multiple Nx commands in CI is much faster, as file hashing becomes unnecessary after the initial run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Archive file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The archive file is a binary file that contains the workspace file hashes with their last modified time. Every time Nx starts (ie, running &lt;code&gt;nx run project:target&lt;/code&gt;) it gets all the files with their last modified time, and compares it to the archive. If the file exists in the archive, then Nx does not access the file system to read the file to hash (reading individual files is slower than just getting a list of files from a directory). So running multiple nx commands in CI is quick to start because Nx does not need to constantly hash files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nx Replay
&lt;/h3&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%2Fad6umaibcczq2ztkti8r.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%2Fad6umaibcczq2ztkti8r.png" alt="Nx Replay" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nx Replay enables caching and reusing of task results. It’s our well known Nx remote cache! It allows developers to avoid re-running expensive tasks by retrieving the cached results from a remote cache. This significantly improves build and test performance, as well as developer productivity. Nx Replay is also critical to the functioning of Nx Agents, which rely on the remote cache to ensure that the results of a task will be shared with every agent that needs them. By using Nx Replay, developers can optimize their workflows and reduce the time spent waiting for tasks to complete.&lt;/p&gt;

&lt;p&gt;With Nx Replay, you can see significant speed improvements in your CI pipelines for modified PRs. What’s also important is that if a task has been executed in CI, a developer running that same task locally can reuse the task result instead of actually running the task. So you will also see improvements locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Nx Agents&lt;/strong&gt;
&lt;/h3&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%2Fra4u8gspdavty040mpz9.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%2Fra4u8gspdavty040mpz9.png" alt="Nx Agents" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nx.dev/ci/features/distribute-task-execution"&gt;Nx Agents&lt;/a&gt; represent the pinnacle of task distribution optimization, ensuring that tasks are executed as efficiently as possible based on the specific requirements of each change. Some features that make up this effort are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nx.dev/ci/features/distribute-task-execution#cicd-guides"&gt;Easy integration with existing providers&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Distribution is handled on the Nx Cloud infrastructure and all you need is a single line. What’s more, all results are played back to your original CI provider script which triggers the Nx Cloud distribution, so that you can make use of the resulting artifacts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nx.dev/ci/features/dynamic-agents"&gt;Efficient task distribution&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Save compute resources and reduce costs, minimizing idle time and compute waste&lt;/li&gt;
&lt;li&gt;Dynamic sizing based on PR size&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nx.app/products/tusky"&gt;Tusky&lt;/a&gt; - our AI solution - coming soon

&lt;ul&gt;
&lt;li&gt;You set your desired cost/speed ratio, and you forget about any more configuration. We ensure maximum speed up to limits you set yourself.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read more about Nx Agents &lt;a href="https://nx.app/products/agents#content"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;TaskAtomizer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://nx.dev/ci/features/split-e2e-tasks"&gt;TaskAtomizer&lt;/a&gt; splits your Cypress or Playwright e2e tests by file. This significantly enhances granularity for caching, parallel execution, and flaky test identification. This granular approach ensures that individual test results can be cached and only the necessary tests rerun, greatly reducing CI pipeline times and facilitating more accurate flaky test detection.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;Addressing flaky tests with test deflaking&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Flaky tests can be a significant bottleneck in the CI process. Nx tackles this issue head-on by intelligently &lt;a href="https://nx.dev/ci/features/flaky-tasks"&gt;re-running only the flaky tasks&lt;/a&gt;, rather than the entire pipeline. This approach not only saves time but also provides developers with more confidence in their CI pipeline's reliability. &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%2Fm84osyn5mz4n0ut351w6.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%2Fm84osyn5mz4n0ut351w6.png" alt="Flaky tests" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nx creates a hash of all the inputs for a task whenever it is run. If it encounters a task that fails with a particular set of inputs and then succeeds with those same inputs, Nx knows for a fact that the task is flaky. &lt;/p&gt;

&lt;h2&gt;
  
  
  New Nx features that tie in with our core speed improvements
&lt;/h2&gt;

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

&lt;p&gt;With the help of Nx and the Module Federation setup that Nx offers, you can split up large Angular apps into smaller “vertical slices”. This can significantly speed up your builds and app startup time. Nx has revolutionized the use of Module Federation, especially in how static remotes are built and served. We make use of Nx’s task orchestration, allowing users to fine tune the number of builds happening in parallel to improve local startup time, manage machine resources better, allow for scaling.&lt;/p&gt;

&lt;h3&gt;
  
  
  First-Class Playwright support
&lt;/h3&gt;

&lt;p&gt;With first-class support for Playwright through &lt;strong&gt;&lt;code&gt;@nx/playwright&lt;/code&gt;&lt;/strong&gt;, Nx offers out-of-the-box generators to run Playwright tests efficiently. This integration is especially powerful with features like TaskAtomizer, enhancing the testing process's speed and reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Nx provides an unparalleled toolkit for developers and teams looking to optimize their development workflows, and we keep making it faster. By intelligently leveraging modern technologies and innovative optimizations, Nx delivers speed, efficiency, and reliability, allowing teams to focus on what matters most: building great software.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev"&gt;Nx Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/nxdevtools"&gt;X / Twitter&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/company/nrwl"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.nx.dev/community"&gt;Nx Community Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.app"&gt;Speed up your CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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>nxdevtools</category>
      <category>speed</category>
      <category>ci</category>
    </item>
    <item>
      <title>Add Cypress, Playwright, and Storybook to Nx Expo Apps</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Mon, 19 Feb 2024 21:18:25 +0000</pubDate>
      <link>https://dev.to/nx/add-cypress-playwright-and-storybook-to-nx-expo-apps-2ob1</link>
      <guid>https://dev.to/nx/add-cypress-playwright-and-storybook-to-nx-expo-apps-2ob1</guid>
      <description>&lt;p&gt;Expo has first-class support for building full-stack websites with React, so I can leverage that to add &lt;a href="https://nx.dev/nx-api/cypress" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;/&lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; for E2E testing and add the &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; for UI components.&lt;/p&gt;

&lt;p&gt;In this blog, I am going to add &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;, and &lt;a href="https://nx.dev/nx-api/storybook" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; to my &lt;a href="https://nx.dev/nx-api/expo" rel="noopener noreferrer"&gt;Nx Expo&lt;/a&gt; app:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/xiongemi" rel="noopener noreferrer"&gt;
        xiongemi
      &lt;/a&gt; / &lt;a href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;
        nx-expo-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a repo showing 2 apps created by @nx/expo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NxExpoMonorepo&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This workspace is created using &lt;a href="https://nx.dev/packages/expo" rel="nofollow noopener noreferrer"&gt;@nx/expo&lt;/a&gt; (&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx&lt;/a&gt; and &lt;a href="https://expo.io/" rel="nofollow noopener noreferrer"&gt;Expo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fnrwl%2Fnx%2Fmaster%2Fimages%2Fnx-logo.png" width="45"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;This workspace has been generated by &lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx, a Smart, fast and extensible build system.&lt;/a&gt;&lt;/strong&gt; ✨&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Workspace structure&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;It contains 2 apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cats and its e2e (cypress/playwright)&lt;/li&gt;
&lt;li&gt;dogs and its e2e (cypress/playwright)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 libs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;queries: &lt;a href="https://react-query.tanstack.com/" rel="nofollow noopener noreferrer"&gt;tanstack react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;states: redux state management&lt;/li&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/cats.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fcats.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/dogs.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fdogs.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Commands&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx start cats&lt;/code&gt; to start the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx start dogs&lt;/code&gt; to start the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build cats&lt;/code&gt; to build the cats app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build dogs&lt;/code&gt; to build the dogs app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test cats&lt;/code&gt; to test the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test dogs&lt;/code&gt; to test the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint cats&lt;/code&gt; to lint the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint dogs&lt;/code&gt; to lint the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run deploy&lt;/code&gt; to deploy the cats app to github page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-cypress&lt;/code&gt; to run cypress e2e tests on cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-playwright&lt;/code&gt; to…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It is an app that shows a random fact about cats:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F3aiggy817vkpdxoep26c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F3aiggy817vkpdxoep26c.png" alt="My example Nx Expo app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is &lt;a href="https://nx.dev/nx-api/expo" rel="noopener noreferrer"&gt;@nx/expo&lt;/a&gt;? Nx is a build system that helps you maintain and scale monorepos, both locally and on CI. @nx/expo contains generators for managing Expo applications and libraries within an Nx workspace.&lt;/p&gt;

&lt;p&gt;I am going to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  How to add &lt;a href="https://nx.dev/nx-api/cypress" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  How to add &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  How to add &lt;a href="https://nx.dev/nx-api/storybook" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Add Cypress
&lt;/h2&gt;

&lt;p&gt;In this section, I am going to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When I already have an existing Nx Workspace, how do I add the Expo and Cypress projects?&lt;/li&gt;
&lt;li&gt;  When I already have an existing Nx Expo app, how do I add the Cypress tests to my app?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add a new Expo App in an Nx Workspace
&lt;/h3&gt;

&lt;p&gt;In any Nx workspace, I can install &lt;code&gt;@nx/expo&lt;/code&gt; 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 add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now when I generate a new Expo app, I can simply use &lt;a href="https://nx.dev/nx-api/expo/generators/application" rel="noopener noreferrer"&gt;@nx/expo:application generator&lt;/a&gt; with the flag &lt;code&gt;--e2eTestRunner=cyperss&lt;/code&gt;:&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 generate @nx/expo:app &lt;span class="nt"&gt;--e2eTestRunner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cypress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It should create the expo app and its Cypress e2e tests. I can run &lt;code&gt;npx nx run &amp;lt;your-app-name&amp;gt;-e2e:e2e&lt;/code&gt; to run the Cypress e2e tests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add Cypress to an Existing Nx Expo App
&lt;/h3&gt;

&lt;p&gt;Before I start, I need to make sure I can serve my Expo app for the web view. In this example, in my &lt;code&gt;apps/cats/project.json&lt;/code&gt;, I got a serve target defined:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "serve": {  
      "executor": "@nx/expo:serve",  
      "options": {  
        "port": 8081  
      }  
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So I can run the command &lt;code&gt;npx nx run cats:serve&lt;/code&gt; to serve the app on &lt;a href="http://localhost:8081/" rel="noopener noreferrer"&gt;http://localhost:8081/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fh52u18np8xqbz33c7cfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fh52u18np8xqbz33c7cfu.png" alt="Cats in Web View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can also use &lt;a href="https://nx.dev/nx-api/expo#how-nxexpo-infers-tasks" rel="noopener noreferrer"&gt;@nx/expo inferred tasks&lt;/a&gt; without having a serve target in project.json. In &lt;code&gt;.env&lt;/code&gt; file, set &lt;code&gt;NX_ADD_PLUGINS=true&lt;/code&gt;; then run the 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 add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then I can still run the serve command &lt;code&gt;npx nx run &amp;lt;your expo project&amp;gt;:serve&lt;/code&gt; without a serve target defined.&lt;/p&gt;

&lt;p&gt;Then I can set up the cypress e2e project against the web app.&lt;/p&gt;

&lt;p&gt;First, I need to install &lt;code&gt;@nx/cypress&lt;/code&gt;:&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 add @nx/cypress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Second, I create a project.json for my Cypress project. In this example, I create a project.json at &lt;code&gt;apps/cats-cypress/project.json&lt;/code&gt;, I name the project &lt;code&gt;cats-cypress&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;"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;"cats-cypress"&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;Third, run the below command to generate Cypress configuration:&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 generate @nx/cypress:configuration &lt;span class="nt"&gt;--project&lt;/span&gt; cats-cypress &lt;span class="nt"&gt;--devServerTarget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cats:serve &lt;span class="nt"&gt;--baseUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081 &lt;span class="nt"&gt;--verbose&lt;/span&gt; &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;Since the serve command is &lt;code&gt;npx nx run cats:serve&lt;/code&gt;, so the flag is &lt;code&gt;--devServerTarget&lt;/code&gt; is &lt;code&gt;cats:serve&lt;/code&gt;. Also, the &lt;code&gt;--baseUrl&lt;/code&gt; is &lt;code&gt;http://localhost:8081&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It should generate &lt;code&gt;cypress.config.ts&lt;/code&gt; and a sample test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fybfhq6behvubn1hhjtqs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fybfhq6behvubn1hhjtqs.png" alt="Cypress Project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can run the Cypress test using the below 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 run cats-cypress:e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Add Cypress Tests
&lt;/h3&gt;

&lt;p&gt;I change the example tests:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now I can run the command &lt;code&gt;npx nx run cats-cypress:e2e&lt;/code&gt; and it should pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 2 passing (867ms)  


  (Results)  

  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐  
  │ Tests:        2                                                                                │  
  │ Passing:      2                                                                                │  
  │ Failing:      0                                                                                │  
  │ Pending:      0                                                                                │  
  │ Skipped:      0                                                                                │  
  │ Screenshots:  0                                                                                │  
  │ Video:        false                                                                            │  
  │ Duration:     0 seconds                                                                        │  
  │ Spec Ran:     app.cy.ts                                                                        │  
  └────────────────────────────────────────────────────────────────────────────────────────────────┘  


\===================================================================================  

  (Run Finished)  


       Spec                                              Tests  Passing  Failing  Pending  Skipped    
  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐  
  │ ✔  app.cy.ts                                869ms        2        2        -        -        - │  
  └────────────────────────────────────────────────────────────────────────────────────────────────┘  
    ✔  All specs passed!                        869ms        2        2        -        -        -    


 —————————————————————————————————————————————————————————————————————————————————  

 &amp;gt;  NX   Successfully ran target e2e for project cats-cypress (15s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Add Playwright
&lt;/h2&gt;

&lt;p&gt;Alternatively, I can use Playwright to e2e test.&lt;/p&gt;

&lt;p&gt;In this section, I am going to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When I already have an existing Nx Workspace, how do I add the Expo and Playwright projects?&lt;/li&gt;
&lt;li&gt;  When I already have an existing Nx Expo app, how do I add the Playwright tests to my app?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add a new Expo App in an Nx Workspace
&lt;/h3&gt;

&lt;p&gt;In any Nx workspace, I can install &lt;code&gt;@nx/expo&lt;/code&gt; 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 add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when I generate a new Expo app, I can simply use &lt;a href="https://nx.dev/nx-api/expo/generators/application" rel="noopener noreferrer"&gt;@nx/expo:application generator&lt;/a&gt; with the flag &lt;code&gt;--e2eTestRunner=playwright&lt;/code&gt;:&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 generate @nx/expo:app &lt;span class="nt"&gt;--e2eTestRunner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should create the expo app and its Playwright e2e tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Playwright to an Existing Nx Expo App
&lt;/h3&gt;

&lt;p&gt;Similarly to Cypress steps, before I start, I need to make sure I can serve my Expo app for the web view. In this example, in my &lt;code&gt;apps/cats/project.json&lt;/code&gt;, I got a serve target defined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "serve": {  
      "executor": "@nx/expo:serve",  
      "options": {  
        "port": 8081  
      }  
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, I need to install &lt;code&gt;@nx/playwright&lt;/code&gt;:&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 add @nx/playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, I create a project.json for my Playwright project. In this example, I create a project.json at &lt;code&gt;apps/cats-playwright/project.json&lt;/code&gt;, I name the project &lt;code&gt;cats-playwright&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;"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;"cats-playwright"&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;Third, run the below command to generate Cypress configuration:&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 @nx/playwright:configuration &lt;span class="nt"&gt;--project&lt;/span&gt; cats-playwright &lt;span class="nt"&gt;--webServerCommand&lt;/span&gt; &lt;span class="s2"&gt;"nx run cats:serve"&lt;/span&gt; &lt;span class="nt"&gt;--webServerAddress&lt;/span&gt; http://localhost:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the serve command is &lt;code&gt;npx nx run cats:serve&lt;/code&gt;, so the flag is &lt;code&gt;--webServerCommand&lt;/code&gt; is &lt;code&gt;nx run cats:serve&lt;/code&gt;. Also, the &lt;code&gt;--webServerAddress&lt;/code&gt; is &lt;code&gt;[http://localhost:8081](http://localhost:8081.)&lt;/code&gt;&lt;a href="http://localhost:8081." rel="noopener noreferrer"&gt;.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should generate &lt;code&gt;playwright.config.ts&lt;/code&gt; and a sample test file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AtwF-sWslGutXfCX7IjpYyQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AtwF-sWslGutXfCX7IjpYyQ.png" alt="playwright test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this example, I change the example test at &lt;code&gt;apps/cats-playwright/e2e/example.spec.ts&lt;/code&gt; to:&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;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&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;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has title&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;page&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&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="c1"&gt;// Expect h1 to contain a substring.  &lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cat Facts&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run command &lt;code&gt;npx nx run cats-playwright:e2e&lt;/code&gt;, and the tests should pass:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2Aye3g01hteuWjs_hZEkCD_g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2Aye3g01hteuWjs_hZEkCD_g.png" alt="Playwright Report"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Add Storybook
&lt;/h2&gt;

&lt;p&gt;To add the storybook, simply run the 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 generate @nx/react:storybook-configuration &amp;lt;your expo app name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I should see in the console output:&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 @nx/react:storybook-configuration cats  

&amp;gt;  NX  Generating @nx/react:storybook-configuration  

✔ Do you want to set up Storybook interaction tests? (Y/n) · true  
✔ Automatically generate \*.stories.ts files for components declared in this project? (Y/n) · true  

✔ Configure a static file server for the storybook instance? (Y/n) · true  
UPDATE nx.json  
UPDATE package.json  
CREATE apps/cats/.storybook/main.ts  
CREATE apps/cats/.storybook/preview.ts  
CREATE apps/cats/tsconfig.storybook.json  
UPDATE apps/cats/tsconfig.app.json  
UPDATE apps/cats/tsconfig.json  
UPDATE apps/cats/project.json  
CREATE apps/cats/src/app/App.stories.tsx  
CREATE apps/cats/src/app/bookmarks/bookmarks.stories.tsx  
CREATE apps/cats/src/app/facts/facts.stories.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it! In one single, it should generate the Storybook for me. Run the command to see Storybook in web view:&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 run &amp;lt;your-expo-app&amp;gt;:storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It interpolates my native UI components to web components and then creates the Storybook. How does it achieve that?&lt;/p&gt;

&lt;p&gt;In this example, it generates a file &lt;code&gt;apps/cats/.storybook/main.ts&lt;/code&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&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;@storybook/react-webpack5&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;stories&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/lib/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*.stories.@(js|jsx|ts|tsx|mdx)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;addons&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-essentials&lt;/span&gt;&lt;span class="dl"&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;@storybook/addon-interactions&lt;/span&gt;&lt;span class="dl"&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;@nx/react/plugins/storybook&lt;/span&gt;&lt;span class="dl"&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="na"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react-webpack5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;options&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="na"&gt;webpackFinal&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="nx"&gt;config&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;react-native$&lt;/span&gt;&lt;span class="dl"&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;react-native-web&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&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;.web.tsx&lt;/span&gt;&lt;span class="dl"&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;.web.ts&lt;/span&gt;&lt;span class="dl"&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;.web.jsx&lt;/span&gt;&lt;span class="dl"&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;.web.js&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="err"&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="err"&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;return&lt;/span&gt; &lt;span class="nx"&gt;config&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="c1"&gt;// To customize your webpack configuration you can use the webpackFinal field.  &lt;/span&gt;
&lt;span class="c1"&gt;// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config  &lt;/span&gt;
&lt;span class="c1"&gt;// and https://nx.dev/recipes/storybook/custom-builder-configs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice there is a line:&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;react-native$&lt;/span&gt;&lt;span class="dl"&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;react-native-web&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses Webpack to bundle and alias react-native to react-native-web.&lt;/p&gt;

&lt;p&gt;When serving up my Storybook for the first time, I have some issues and problems preventing components from rendering. Below are the issues I run into and how I troubleshoot them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Root Element
&lt;/h4&gt;

&lt;p&gt;“Full-screen React Native apps with a root &lt;code&gt;&amp;lt;ScrollView&amp;gt;&lt;/code&gt; may require the following styles inlined in the HTML document shell.” (&lt;a href="https://necolas.github.io/react-native-web/docs/setup/#root-element" rel="noopener noreferrer"&gt;https://necolas.github.io/react-native-web/docs/setup/#root-element&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In this example, I do have a root element, so I need to add styles to &lt;code&gt;apps/cats/.storybook/preview-head.html&lt;/code&gt; to make my root full height:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;These&lt;/span&gt; &lt;span class="nt"&gt;styles&lt;/span&gt; &lt;span class="nt"&gt;make&lt;/span&gt; &lt;span class="nt"&gt;the&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="nt"&gt;full-height&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;  
  &lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  
  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;These&lt;/span&gt; &lt;span class="nt"&gt;styles&lt;/span&gt; &lt;span class="nt"&gt;disable&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="nt"&gt;scrolling&lt;/span&gt; &lt;span class="nt"&gt;if&lt;/span&gt; &lt;span class="nt"&gt;you&lt;/span&gt; &lt;span class="nt"&gt;are&lt;/span&gt; &lt;span class="nt"&gt;using&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ScrollView&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;  
  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;These&lt;/span&gt; &lt;span class="nt"&gt;styles&lt;/span&gt; &lt;span class="nt"&gt;make&lt;/span&gt; &lt;span class="nt"&gt;the&lt;/span&gt; &lt;span class="nt"&gt;root&lt;/span&gt; &lt;span class="nt"&gt;element&lt;/span&gt; &lt;span class="nt"&gt;full-height&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;  
  &lt;span class="nf"&gt;#storybook-root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Error: Couldn’t find a navigation object.
&lt;/h4&gt;

&lt;p&gt;Because I am using the library &lt;code&gt;@react-navigation/native&lt;/code&gt; and I use its hooks like &lt;code&gt;useNavigtion&lt;/code&gt; and &lt;code&gt;useRoute&lt;/code&gt; inside my component, I have this error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2ApA8gWYSeqJMFE0N2azCzGw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2ApA8gWYSeqJMFE0N2azCzGw.png" alt="Error: Couldn’t find a navigation object"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The easiest way is just to mock this library and create a &lt;a href="https://storybook.js.org/docs/react/writing-stories/decorators" rel="noopener noreferrer"&gt;decorator&lt;/a&gt; for it. In this example, I create a Navigation Decorator at &lt;code&gt;apps/cats/.storybook/mocks/navigation-decorator.tsx&lt;/code&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;NavigationContainer&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;@react-navigation/native&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;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NavigationContainer&lt;/span&gt; &lt;span class="nx"&gt;independent&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;story&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/NavigationContainer&amp;gt; &lt;/span&gt;&lt;span class="err"&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;p&gt;Then I can add this decoration to my story file. In this example, I add it to &lt;code&gt;apps/cats/src/app/bookmarks/bookmarks.stories.tsx&lt;/code&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&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;@storybook/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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&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;./bookmarks&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;within&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;@storybook/testing-library&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&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;@storybook/jest&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&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;../../../.storybook/mocks/navigation-decorator&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;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;---- add the decorator here  &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="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
  &lt;span class="na"&gt;play&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="nx"&gt;canvasElement&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;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;within&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Welcome to Bookmarks!/gi&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;h4&gt;
  
  
  Error: Couldn’t find a route object.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AN3fsp2NcQ1svggvJQRK0lQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AN3fsp2NcQ1svggvJQRK0lQ.png" alt="Error: Couldn’t find a route object."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This issue is similar to “Couldn’t find a navigation object”, it is also related to the library &lt;code&gt;@react-navigation/native&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It happens because my component is using the &lt;code&gt;useRoute&lt;/code&gt; hook and expecting certain routing parameters. I simply need to customize the mock &lt;code&gt;NavigationDecorator&lt;/code&gt; for my component. For example, below is a component that is expecting an id from the route parameters:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRoute&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RouteProp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can simply modify the mock &lt;code&gt;NavigationDecorator&lt;/code&gt; at &lt;code&gt;apps/cats/.storybook/mocks/navigation-decorator.tsx&lt;/code&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;NavigationContainer&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;@react-navigation/native&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createNativeStackNavigator&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;@react-navigation/native-stack&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;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;Stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNativeStackNavigator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NavigationContainer&lt;/span&gt; &lt;span class="nx"&gt;independent&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;&amp;gt;&lt;/span&gt;  
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Screen&lt;/span&gt;  
          &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyStorybookScreen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
          &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
          &lt;span class="nx"&gt;initialParams&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;  
        &lt;span class="sr"&gt;/&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Stack.Navigator&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/NavigationContainer&amp;gt; &lt;/span&gt;&lt;span class="err"&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;h4&gt;
  
  
  Error: No QueryClient set, use QueryClientProvider to set one
&lt;/h4&gt;

&lt;p&gt;This happens because I use the library @tanstack/react-query. I need to create a decorator for &lt;code&gt;QueryClientProvider&lt;/code&gt;. At &lt;code&gt;apps/cats/.storybook/mocks/query-client-decorator.tsx&lt;/code&gt;, I create this decorator:&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;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&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;@tanstack/react-query&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;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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="nf"&gt;story&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/QueryClientProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, my story at &lt;code&gt;apps/cats/src/app/facts/facts.stories.tsx&lt;/code&gt; will become:&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&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;@storybook/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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Facts&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;./facts&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;within&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;@storybook/testing-library&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&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;@storybook/jest&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&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;../../../.storybook/mocks/navigation-decorator&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&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;../../../.storybook/mocks/query-client-decorator&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;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Facts&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Facts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;decorators&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="nx"&gt;NavigationDecorator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;---- add the QueryClientDecorator here  &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="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Facts&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
  &lt;span class="na"&gt;play&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="nx"&gt;canvasElement&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;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;within&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Welcome to Facts!/gi&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;h4&gt;
  
  
  Error: Unable to load react-native-vector-icons.
&lt;/h4&gt;

&lt;p&gt;I got this error when I tried to compile the storybook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You may need an additional loader to handle the result of these loaders.  
|   
|       return (  
&amp;gt;         &amp;lt;Text selectable={false} {...props}&amp;gt;  
|           {glyph}  
|           {children}  
 @ ./node\_modules/react-native-vector-icons/MaterialCommunityIcons.js 6:0-50 9:16-29  
 @ ./node\_modules/react-native-paper/lib/module/components/MaterialCommunityIcon.js 8:27-94  
 @ ./node\_modules/react-native-paper/lib/module/core/PaperProvider.js 3:0-72 73:12-33  
 @ ./node\_modules/react-native-paper/lib/module/index.js 4:0-59 4:0-59 5:0-64 5:0-64  
 @ ./apps/cats/src/app/App.tsx 1:717-760 1:1882-1892  
 @ ./apps/cats/src/app/ lazy ^\\.\\/.\*$ namespace object ./App.tsx ./App  
 @ ./storybook-stories.js 1:383-427  
 @ ./storybook-config-entry.js 1:171-216 1:1789-1797 1:1871-1985 1:1926-1984 1:1972-1980
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because I use the library &lt;code&gt;react-native-paper&lt;/code&gt; which depends on &lt;code&gt;react-native-vector-icons&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In react-native-vector-icons, it &lt;code&gt;.js&lt;/code&gt; files contain &lt;code&gt;jsx&lt;/code&gt; code: &lt;code&gt;&amp;lt;Text selectable={false} {…props}&amp;gt;&lt;/code&gt;. To solve this, I need to load the &lt;code&gt;react-native-vector-icons&lt;/code&gt; library using babel-loader. In this example, I can add a rule to Storybook’s Webpack config:&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
          &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;js|jsx&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&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="sr"&gt;/react-native-vector-icons/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;automatic&lt;/span&gt;&lt;span class="dl"&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="err"&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;p&gt;Then I need to also load the font &lt;a href="https://github.com/oblador/react-native-vector-icons/blob/master/Fonts/MaterialCommunityIcons.ttf" rel="noopener noreferrer"&gt;MaterialCommunityIcons.ttf&lt;/a&gt; for Storybook:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Download the font from &lt;a href="https://github.com/oblador/react-native-vector-icons/blob/master/Fonts/MaterialCommunityIcons.ttf" rel="noopener noreferrer"&gt;https://github.com/oblador/react-native-vector-icons/blob/master/Fonts/MaterialCommunityIcons.ttf&lt;/a&gt; to &lt;code&gt;apps/cats/.storybook/public&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Add &lt;code&gt;staticDirs&lt;/code&gt; option to Storybook configuration at &lt;code&gt;apps/cats/.storybook/main.ts&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;staticDirs: \['./public'\],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Add the below style to &lt;code&gt;apps/cats/.storybook/preview-head.html&lt;/code&gt; to load the font:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'MaterialCommunityIcons'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('/MaterialCommunityIcons.ttf')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'truetype'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Storybook configuration at &lt;code&gt;apps/cats/.storybook/main.ts&lt;/code&gt; will become:&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&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;@storybook/react-webpack5&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;stories&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/app/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*.stories.@(js|jsx|ts|tsx|mdx)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;staticDirs&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;addons&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-essentials&lt;/span&gt;&lt;span class="dl"&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;@storybook/addon-interactions&lt;/span&gt;&lt;span class="dl"&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;@nx/react/plugins/storybook&lt;/span&gt;&lt;span class="dl"&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="na"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react-webpack5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;options&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="na"&gt;webpackFinal&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="nx"&gt;config&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;react-native$&lt;/span&gt;&lt;span class="dl"&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;react-native-web&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&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;.web.tsx&lt;/span&gt;&lt;span class="dl"&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;.web.ts&lt;/span&gt;&lt;span class="dl"&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;.web.jsx&lt;/span&gt;&lt;span class="dl"&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;.web.js&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="err"&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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;  
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
          &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;js|jsx&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&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="sr"&gt;/react-native-vector-icons/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;automatic&lt;/span&gt;&lt;span class="dl"&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="err"&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="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="c1"&gt;// To customize your webpack configuration you can use the webpackFinal field.  &lt;/span&gt;
&lt;span class="c1"&gt;// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config  &lt;/span&gt;
&lt;span class="c1"&gt;// and https://nx.dev/recipes/storybook/custom-builder-configs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can see react-native-vector-icons are being loaded correctly for the Storybook.&lt;/p&gt;

&lt;p&gt;Now I can run &lt;code&gt;npx nx run cats:storybook&lt;/code&gt; and it should render the storybook for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AfsIiNQYHderYggGQMmmZxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AfsIiNQYHderYggGQMmmZxg.png" alt="Storybook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, you have learned how to add &lt;a href="https://nx.dev/nx-api/cypress" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;, and &lt;a href="https://nx.dev/nx-api/storybook" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; to your Nx Expo app.&lt;/p&gt;

&lt;p&gt;With Nx, it will help you with your Expo development process.&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;

</description>
      <category>cypress</category>
      <category>playwright</category>
      <category>storybook</category>
      <category>expo</category>
    </item>
    <item>
      <title>Unit Testing Expo Apps With Jest</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Mon, 19 Feb 2024 19:11:00 +0000</pubDate>
      <link>https://dev.to/nx/unit-testing-expo-apps-with-jest-2c5a</link>
      <guid>https://dev.to/nx/unit-testing-expo-apps-with-jest-2c5a</guid>
      <description>&lt;p&gt;In my latest &lt;a href="https://dev.to/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17"&gt;blog&lt;/a&gt;, I successfully navigated through the steps of setting up an Expo Monorepo with &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx&lt;/a&gt;. The next challenge? Testing! This blog dives into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Crafting effective unit tests for Expo components utilizing Jest&lt;/li&gt;
&lt;li&gt;  Addressing common issues encountered during unit testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/xiongemi" rel="noopener noreferrer"&gt;
        xiongemi
      &lt;/a&gt; / &lt;a href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;
        nx-expo-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a repo showing 2 apps created by @nx/expo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NxExpoMonorepo&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This workspace is created using &lt;a href="https://nx.dev/packages/expo" rel="nofollow noopener noreferrer"&gt;@nx/expo&lt;/a&gt; (&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx&lt;/a&gt; and &lt;a href="https://expo.io/" rel="nofollow noopener noreferrer"&gt;Expo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fnrwl%2Fnx%2Fmaster%2Fimages%2Fnx-logo.png" width="45"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;This workspace has been generated by &lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx, a Smart, fast and extensible build system.&lt;/a&gt;&lt;/strong&gt; ✨&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Workspace structure&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;It contains 2 apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cats and its e2e (cypress/playwright)&lt;/li&gt;
&lt;li&gt;dogs and its e2e (cypress/playwright)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 libs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;queries: &lt;a href="https://react-query.tanstack.com/" rel="nofollow noopener noreferrer"&gt;tanstack react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;states: redux state management&lt;/li&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/cats.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fcats.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/dogs.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fdogs.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Commands&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx start cats&lt;/code&gt; to start the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx start dogs&lt;/code&gt; to start the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build cats&lt;/code&gt; to build the cats app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build dogs&lt;/code&gt; to build the dogs app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test cats&lt;/code&gt; to test the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test dogs&lt;/code&gt; to test the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint cats&lt;/code&gt; to lint the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint dogs&lt;/code&gt; to lint the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run deploy&lt;/code&gt; to deploy the cats app to github page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-cypress&lt;/code&gt; to run cypress e2e tests on cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-playwright&lt;/code&gt; to…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Stacks
&lt;/h2&gt;

&lt;p&gt;Here’s my setup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Testing framework: &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;jest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Testing library: &lt;a href="https://callstack.github.io/react-native-testing-library/" rel="noopener noreferrer"&gt;@testing-library/react-native&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Jest Preset: &lt;a href="https://www.npmjs.com/package/jest-expo" rel="noopener noreferrer"&gt;jest-expo&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Writing and Running Unit Tests
&lt;/h2&gt;

&lt;p&gt;When you use Nx, it not only configures and sets up Jest, but also creates a default unit test for every expo component that is being generated. Here’s what that looks 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;render&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;@testing-library/react-native&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;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;Loading&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;./loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render successfully&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="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;p&gt;To run all unit tests for a given project, use:&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; &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s the output of running this for my example app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A720%2Fformat%3Awebp%2F1%2AA-d1u9T8YhRwlP4ZLoACzA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A720%2Fformat%3Awebp%2F1%2AA-d1u9T8YhRwlP4ZLoACzA.png" alt="terminal output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to writing tests, the &lt;a href="https://callstack.github.io/react-native-testing-library/docs/api-queries" rel="noopener noreferrer"&gt;React Native Testing Library&lt;/a&gt; is a game-changer for writing cleaner unit tests in React Native applications. Its intuitive query API simplifies the process of selecting elements within your components, making it straightforward to write more maintainable and readable tests. You mark elements with a &lt;code&gt;testID&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Headline&lt;/span&gt; &lt;span class="na"&gt;testID=&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{film.title}&lt;span class="nt"&gt;&amp;lt;/Headline&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the test file, you can use the function &lt;code&gt;getByTestId&lt;/code&gt; to query &lt;code&gt;testID&lt;/code&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveTextContent&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 find more options for querying elements on the official React Native Testing Library docs: &lt;a href="https://callstack.github.io/react-native-testing-library/docs/api-queries" rel="noopener noreferrer"&gt;https://callstack.github.io/react-native-testing-library/docs/api-queries&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Common Issues When Writing Tests
&lt;/h2&gt;

&lt;p&gt;However, unit tests do not always pass. Here are some common errors I ran into and how to resolve them.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Error: AsyncStorage is null.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I am using the library &lt;code&gt;@react-native-async-storage/async-storage&lt;/code&gt;, and I got the below error when running unit testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; \[@RNC/AsyncStorage\]: NativeModule: AsyncStorage is null.  

    To fix this issue try these steps:  

      • Rebuild and restart the app.  

      • Run the packager with \`--reset-cache\` flag.  

      • If you are using CocoaPods on iOS, run \`pod install\` in the \`ios\` directory and then rebuild and re-run the app.  

      • If this happens while testing with Jest, check out docs how to integrate AsyncStorage with it: https://react-native-async-storage.github.io/async-storage/docs/advanced/jest  

    If none of these fix the issue, please open an issue on the Github repository: https://github.com/react-native-async-storage/async-storage/issues  

       5 | import { ReactQueryDevtools } from '@tanstack/react-query-devtools';  
       6 | import { Platform } from 'react-native';  
    &amp;gt;  7 | import AsyncStorage from '@react-native-async-storage/async-storage';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue is that &lt;code&gt;@react-native-async-storage/async-storage&lt;/code&gt; library can only be used in &lt;code&gt;NativeModule&lt;/code&gt;. Since unit testing with Jest only tests JS/TS file logic, I need to mock this library.&lt;/p&gt;

&lt;p&gt;In the app’s test-setup.ts file, add the below lines:&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="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-async-storage/async-storage&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="o"&gt;=&amp;gt;&lt;/span&gt;  
  &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-async-storage/async-storage/jest/async-storage-mock&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error: Could not find “store”
&lt;/h2&gt;

&lt;p&gt;I am using Redux for state management, and I got this error for my stateful components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not find "store" in the context of "Connect(Bookmarks)". Either wrap the root component in a &amp;lt;Provider&amp;gt;, or pass a custom React context provider to &amp;lt;Provider&amp;gt; and the corresponding React context consumer to Connect(Bookmarks) in connect options.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, the simple way is to mock a redux store. I need to install &lt;a href="https://github.com/reduxjs/redux-mock-store" rel="noopener noreferrer"&gt;redux-mock-store&lt;/a&gt; and its typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="se"&gt;\#&lt;/span&gt; npm  
npm &lt;span class="nb"&gt;install &lt;/span&gt;redux-mock-store @types/redux-mock-store &lt;span class="nt"&gt;--save-dev&lt;/span&gt;  

&lt;span class="se"&gt;\#&lt;/span&gt; yarn  
yarn add redux-mock-store @types/redux-mock-store &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I can create a mock store using this library like the below code:&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="nx"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&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;redux-mock-store&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;mockStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

  &lt;span class="nf"&gt;beforeEach&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="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockStore&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;  
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&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;For example, one of my stateful components’ unit test will become:&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="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;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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&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;@testing-library/react-native&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&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;react-redux&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;configureStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&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;redux-mock-store&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialRootState&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-expo-monorepo/states/cat&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;Bookmarks&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;./bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bookmarks&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="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;mockStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="o"&gt;&amp;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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

  &lt;span class="nf"&gt;beforeEach&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="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialRootState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render successfully&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="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Bookmarks&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;  
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Provider&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;p&gt;The above code will apply the initial redux state to my components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error: No QueryClient set
&lt;/h3&gt;

&lt;p&gt;Because I use &lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt; , when I run unit tests, I have this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No QueryClient set, use QueryClientProvider to set one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error occurred because I used &lt;code&gt;useQuery&lt;/code&gt; from &lt;code&gt;@tanstack/react-query&lt;/code&gt; in my component; however, in this unit test, the context of this hook is not provided.&lt;/p&gt;

&lt;p&gt;To solve this, I can just mock the &lt;code&gt;useQuery&lt;/code&gt; function:&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="err"&gt;\&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;ReactQuery&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;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReactQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useQuery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;isLoading&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="na"&gt;isSuccess&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;refetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
    &lt;span class="na"&gt;isFetching&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="na"&gt;isError&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Error: Couldn’t find a navigation object
&lt;/h3&gt;

&lt;p&gt;If you use &lt;code&gt;@react-navigation&lt;/code&gt; library for navigation, and inside your component, there are hooks from this library like &lt;code&gt;useNavigation&lt;/code&gt; and &lt;code&gt;useRoute&lt;/code&gt;, you are likely to get this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Couldn't find a navigation object. Is your component inside NavigationContainer?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix this, I need to mock the &lt;code&gt;@react-nativgation/native&lt;/code&gt; library. In the app’s test-setup.ts file, I need to add:&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="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-navigation/native&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;useNavigation&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
      &lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
      &lt;span class="na"&gt;setOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;}),&lt;/span&gt;  
    &lt;span class="na"&gt;useRoute&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&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="p"&gt;};&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SyntaxError: Unexpected token ‘export’
&lt;/h3&gt;

&lt;p&gt;I got this error when using a library with ECMAScript Module (ESM), such as &lt;code&gt;[udid](https://github.com/uuidjs/uuid)&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; /Users/emilyxiong/Code/nx-expo-monorepo/node\_modules/uuid/dist/esm-browser/index.js:1  
    ({"Object.&amp;lt;anonymous&amp;gt;":function(module,exports,require,\_\_dirname,\_\_filename,jest){export { default as v1 } from './v1.js';  
                                                                                      ^^^^^^  

    SyntaxError: Unexpected token 'export'  

       5 | import { connect } from 'react-redux';  
       6 | import 'react-native-get-random-values';  
    &amp;gt;  7 | import { v4 as uuidv4 } from 'uuid';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jest does not work with ESM out of the box. The simple solution is to map this library to the CommonJS version of this library.&lt;/p&gt;

&lt;p&gt;In the app’s &lt;code&gt;jest.config.ts&lt;/code&gt;, there should be an option called &lt;code&gt;moduleNameMapper&lt;/code&gt;. The library I used is called &lt;code&gt;uuid&lt;/code&gt;, so I need to add the map &lt;code&gt;uuid: require.resolve(‘uuid’)&lt;/code&gt; under &lt;code&gt;moduleNameMapper&lt;/code&gt;. So when the code encounters imports from &lt;code&gt;uuid&lt;/code&gt; library, it will resolve the CommonJS version of it:&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="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&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;p&gt;Alternatively, I can also mock this library in the test files:&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;v4&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;uuidv4&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;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&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;
  
  
  Error: Jest encountered an unexpected token
&lt;/h2&gt;

&lt;p&gt;I got this error when I was importing from a library such as &lt;a href="https://github.com/oblador/react-native-vector-icons" rel="noopener noreferrer"&gt;react-native-vector-icons&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; console.error  
      Jest encountered an unexpected token  

      Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.  

      Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.  

      By default "node\_modules" folder is ignored by transformers.  

      Here's what you can do:  
       • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.  
       • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript  
       • To have some of your "node\_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.  
       • If you need a custom transformation specify a "transform" option in your config.  
       • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.  

      You'll find more details and examples of these config options in the docs:  
      https://jestjs.io/docs/configuration  
      For information about custom transformations, see:  
      https://jestjs.io/docs/code-transformation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, add this library name to &lt;code&gt;transformIgnorePatterns&lt;/code&gt; in the app's jest.config.ts.&lt;/p&gt;

&lt;p&gt;What is &lt;code&gt;transformIgnorePatterns&lt;/code&gt;? The &lt;code&gt;transformIgnorePatterns&lt;/code&gt; allows developers to specify which files shall be transformed by Babel. &lt;code&gt;transformIgnorePatterns&lt;/code&gt; is an array of regexp pattern strings that should be matched against all source file paths before the transformation. If the file path matches any patterns, it will not be transformed by Babel.&lt;/p&gt;

&lt;p&gt;By default, Jest will ignore all the files under node_modules and only transform the files under the project’s src.&lt;/p&gt;

&lt;p&gt;However, some libraries such as &lt;code&gt;react-native-paper&lt;/code&gt; or &lt;code&gt;react-native-svg&lt;/code&gt;, the library files are in &lt;code&gt;.ts&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt;. These files are not compiled to &lt;code&gt;js&lt;/code&gt;. So I need to add these libraries' names to &lt;code&gt;transformIgnorePatterns&lt;/code&gt;, so these libraries will be transformed by Babel along with my project. source file. The default generated &lt;code&gt;jest.config.js&lt;/code&gt; already has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transformIgnorePatterns: \[  
    'node\_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.\*|@expo-google-fonts/.\*|react-navigation|@react-navigation/.\*|@unimodules/.\*|unimodules|sentry-expo|native-base|react-native-svg)',  
\]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I have an error related to a library with an unexpected token, I need to check whether they are compiled or not.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If this library source files are already transformed to &lt;code&gt;.js&lt;/code&gt;, then its name should match regex, so it would be ignored, so it will NOT be transformed.&lt;/li&gt;
&lt;li&gt;  If this library source files are NOT transformed to &lt;code&gt;.js&lt;/code&gt; (e.g. still in &lt;code&gt;.ts&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt;), then its name should NOT match regex, so it will be transformed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Here are some common errors that I will probably run into while doing unit testing. The solution to most problems is to find a way to mock a library that is not relevant to my component logic.&lt;/p&gt;

&lt;p&gt;With Nx, you do not need to explicitly install any testing library, so you can dive right in and focus on writing the tests rather than spending time on setup.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@emilyxiong/add-cypress-playwright-and-storybook-to-nx-expo-apps-1d3e409ce834" rel="noopener noreferrer"&gt;Add Cypress, Playwright, and Storybook to Nx Expo Apps&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/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>expo</category>
      <category>jest</category>
      <category>nx</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>State Management Nx React Native/Expo Apps with TanStack Query and Redux</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 16 Feb 2024 23:21:05 +0000</pubDate>
      <link>https://dev.to/nx/state-management-nx-react-nativeexpo-apps-with-tanstack-query-and-redux-397d</link>
      <guid>https://dev.to/nx/state-management-nx-react-nativeexpo-apps-with-tanstack-query-and-redux-397d</guid>
      <description>&lt;p&gt;There are currently countless numbers of state management libraries out there. This blog will show you how to use state management for React Native in Nx monorepo with &lt;a href="https://tanstack.com/query/latest"&gt;TanStack Query&lt;/a&gt; (which happens &lt;a href="https://cloud.nx.app/orgs/6412ca9d1c251d000efa21ba/workspaces/6412c827e6da5d7b4a0b1fe3/overview"&gt;to use Nx on their repo&lt;/a&gt;) and Redux.&lt;/p&gt;

&lt;p&gt;This blog will show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  How to set up these libraries and their dev tools&lt;/li&gt;
&lt;li&gt;  How to build the sample page below in React Native / Expo with state management&lt;/li&gt;
&lt;li&gt;  How to do unit testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will call an API and show a cat fact on the page, allowing users to like or dislike the data.&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%2Fxs31z7e954qjnjhvyjmm.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%2Fxs31z7e954qjnjhvyjmm.png" alt="Cats App" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/xiongemi"&gt;
        xiongemi
      &lt;/a&gt; / &lt;a href="https://github.com/xiongemi/nx-expo-monorepo"&gt;
        nx-expo-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a repo showing 2 apps created by @nx/expo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
NxExpoMonorepo&lt;/h1&gt;
&lt;p&gt;This workspace is created using &lt;a href="https://nx.dev/packages/expo" rel="nofollow"&gt;@nx/expo&lt;/a&gt; (&lt;a href="https://nx.dev" rel="nofollow"&gt;Nx&lt;/a&gt; and &lt;a href="https://expo.io/" rel="nofollow"&gt;Expo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RoBOQypH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;This workspace has been generated by &lt;a href="https://nx.dev" rel="nofollow"&gt;Nx, a Smart, fast and extensible build system.&lt;/a&gt;&lt;/strong&gt; ✨&lt;/p&gt;
&lt;h2&gt;
Workspace structure&lt;/h2&gt;
&lt;p&gt;It contains 2 apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cats and its e2e (cypress/playwright)&lt;/li&gt;
&lt;li&gt;dogs and its e2e (cypress/playwright)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 libs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;queries: &lt;a href="https://react-query.tanstack.com/" rel="nofollow"&gt;tanstack react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;states: redux state management&lt;/li&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/cats.png?raw=true"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QiOp2J1T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/xiongemi/nx-expo-monorepo/raw/main/screenshots/cats.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/dogs.png?raw=true"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7hT-VlL2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/xiongemi/nx-expo-monorepo/raw/main/screenshots/dogs.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Commands&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx start cats&lt;/code&gt; to start the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx start dogs&lt;/code&gt; to start the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build cats&lt;/code&gt; to build the cats app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build dogs&lt;/code&gt; to build the dogs app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test cats&lt;/code&gt; to test the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test dogs&lt;/code&gt; to test the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint cats&lt;/code&gt; to lint the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint dogs&lt;/code&gt; to lint the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run deploy&lt;/code&gt; to deploy the cats app to github page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-cypress&lt;/code&gt; to run cypress e2e tests on cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-playwright&lt;/code&gt; to…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/xiongemi/nx-expo-monorepo"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://tanstack.com/query/latest/docs/react/guides/does-this-replace-client-state"&gt;TanStack Query documentation&lt;/a&gt;, it says:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://tanstack.com/query/latest/docs/react/overview"&gt;TanStack Query&lt;/a&gt;  is a &lt;strong&gt;server-state&lt;/strong&gt; library.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; is a &lt;strong&gt;client-state&lt;/strong&gt; library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is the difference between the server state and the client state?&lt;/p&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Calling an API, dealing with asynchronous data-&amp;gt; server state&lt;/li&gt;
&lt;li&gt;  Everything else about UI, dealing with synchronous data -&amp;gt; client state&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;To use &lt;a href="https://tanstack.com/query/latest"&gt;&lt;strong&gt;TanStack Query&lt;/strong&gt; / &lt;strong&gt;React Query&lt;/strong&gt;&lt;/a&gt;  for the server state, I need to install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Library: &lt;a href="https://tanstack.com/query/latest"&gt;@tanstack/react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Dev tools: &lt;a href="https://tanstack.com/query/latest/docs/react/devtools"&gt;@tanstack/react-query-devtools&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will use &lt;strong&gt;Redux&lt;/strong&gt; for everything else.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Library: &lt;a href="https://github.com/reduxjs/redux"&gt;redux&lt;/a&gt;, react-redux, @reduxjs/toolkit&lt;/li&gt;
&lt;li&gt;  Dev tools: &lt;a href="https://github.com/zalmoxisus/redux-devtools-extension"&gt;@redux-devtools/extension&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Logger: &lt;a href="https://github.com/LogRocket/redux-logger"&gt;redux-logger&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/@types/redux-logger"&gt;@types/redux-logger&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Storage: &lt;a href="https://github.com/rt2zz/redux-persist"&gt;redux-persist&lt;/a&gt;, &lt;a href="https://github.com/react-native-async-storage/async-storage"&gt;@react-native-async-storage/async-storage&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install all the above packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#npm  &lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @tanstack/react-query @tanstack/react-query-devtools redux react-redux @reduxjs/toolkit @redux-devtools/extension redux-logger @types/redux-logger redux-persist @react-native-async-storage/async-storage &lt;span class="nt"&gt;--save-dev&lt;/span&gt;  

&lt;span class="c"&gt;#yarn  &lt;/span&gt;
yarn add @tanstack/react-query @tanstack/react-query-devtools redux react-redux @reduxjs/toolkit @redux-devtools/extension redux-logger @types/redux-logger redux-persist @react-native-async-storage/async-storage &lt;span class="nt"&gt;--dev&lt;/span&gt;  

&lt;span class="c"&gt;#pnpm  &lt;/span&gt;
pnpm add @tanstack/react-query @tanstack/react-query-devtools redux react-redux @reduxjs/toolkit @redux-devtools/extension redux-logger @types/redux-logger redux-persist @react-native-async-storage/async-storage &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Server State with React Query
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Setup Devtools
&lt;/h3&gt;

&lt;p&gt;First, you need to add React Query / TanStack Query in the &lt;code&gt;App.tsx&lt;/code&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="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;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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&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;@tanstack/react-query&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReactQueryDevtools&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;@tanstack/react-query-devtools&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Platform&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;react-native&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;App&lt;/span&gt; &lt;span class="o"&gt;=&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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="nx"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactQueryDevtools&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="p"&gt;...&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/QueryClientProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note: the &lt;a href="https://tanstack.com/query/latest/docs/react/devtools"&gt;React Query Devtools&lt;/a&gt; currently do not support react native, and it only works on the web, so there is a condition: &lt;code&gt;{ Platform.OS === ‘web’ &amp;amp;&amp;amp; &amp;lt;ReactQueryDevtools /&amp;gt;}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the react native apps, in order to use this tool, you need to use &lt;a href="https://necolas.github.io/react-native-web/"&gt;react-native-web&lt;/a&gt; to interpolate your native app to the web app first.&lt;/p&gt;

&lt;p&gt;If you open my Expo app on the web by running &lt;code&gt;nx start cats&lt;/code&gt; and choose the options &lt;code&gt;Press w │ open web&lt;/code&gt;, you should be able to use the dev tools and see the state of my react queries:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BdW9dxXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2ApwWnPsEymAZAaYTF3SjnmA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BdW9dxXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2ApwWnPsEymAZAaYTF3SjnmA.png" alt="React Query Devtools" width="800" height="1704"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a Query
&lt;/h3&gt;

&lt;p&gt;What is a query?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A query is a declarative dependency on an asynchronous source of data that is tied to a unique key. A query can be used with any Promise-based method (including GET and POST methods) to fetch data from a server.” (&lt;a href="https://tanstack.com/query/latest/docs/react/guides/queries"&gt;https://tanstack.com/query/v4/docs/react/guides/queries&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let’s add our first query. In this example, it will be added under&lt;code&gt;lib/queries&lt;/code&gt; folder. To create a query to fetch a new fact about cats, run the command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# expo workspace  &lt;/span&gt;
npx nx generate @nx/expo:lib use-cat-fact &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries  

&lt;span class="c"&gt;# react-native workspace  &lt;/span&gt;
npx nx generate @nx/react-native:lib use-cat-fact &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or use &lt;a href="https://nx.dev/recipes/nx-console"&gt;Nx Console&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TOKiTc6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2A6mZI98DHk9j-CZ0fjSlW7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TOKiTc6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2A6mZI98DHk9j-CZ0fjSlW7g.png" alt="Nx Console" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now notice under libs folder, &lt;code&gt;use-cat-fact&lt;/code&gt; folder got created under &lt;code&gt;libs/queries&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--24qvpQwv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/1%2A9gobKMSOOmOi3PYg93_LBQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--24qvpQwv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/1%2A9gobKMSOOmOi3PYg93_LBQ.png" alt="use-cat-fact" width="648" height="862"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use React Native CLI, just add a folder in your workspace root.&lt;/p&gt;

&lt;p&gt;For this app, let’s use this API: &lt;a href="https://catfact.ninja/"&gt;https://catfact.ninja/&lt;/a&gt;. At &lt;code&gt;libs/queries/use-cat-fact/src/lib/use-cat-fact.ts&lt;/code&gt;, add code to fetch the data from this API:&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;useQuery&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;@tanstack/react-query&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchCatFact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;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;response&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://catfact.ninja/fact&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;data&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCatFact&lt;/span&gt; &lt;span class="o"&gt;=&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="na"&gt;queryKey&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cat-fact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchCatFact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;enabled&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Essentially, you have created a custom hook that calls &lt;code&gt;useQuery&lt;/code&gt; function from the TanStack Query library.&lt;/p&gt;
&lt;h3&gt;
  
  
  Unit Testing
&lt;/h3&gt;

&lt;p&gt;If you render this hook directly and run the unit test with the command &lt;code&gt;npx nx test queries-use-cat-fact&lt;/code&gt;, this error will show up in the console:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:  
    1. You might have mismatching versions of React and the renderer (such as React DOM)  
    2. You might be breaking the Rules of Hooks  
    3. You might have more than one copy of React in the same app  
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To solve this, you need to wrap your component inside the &lt;code&gt;renderHook&lt;/code&gt; function from &lt;code&gt;@testing-library/react-native&lt;/code&gt; library:&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Install Library to Mock Fetch
&lt;/h4&gt;

&lt;p&gt;Depending on which library you use to make HTTP requests. (e.g. fetch, axios), you need to install a library to mock the response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you use &lt;code&gt;fetch&lt;/code&gt; to fetch data, you need to install &lt;code&gt;jest-fetch-mock&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you use &lt;code&gt;axios&lt;/code&gt; to fetch data, you need to install 
&lt;code&gt;axios-mock-adapter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, since it uses fetch, you need to install &lt;code&gt;jest-fetch-mock&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#npm  &lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;jest-fetch-mock &lt;span class="nt"&gt;--save-dev&lt;/span&gt;  

&lt;span class="c"&gt;#yarn  &lt;/span&gt;
yard add jest-fetch-mock &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You also need to mock &lt;code&gt;fetch&lt;/code&gt; library in &lt;code&gt;libs/queries/use-cat-fact/test-setup.ts&lt;/code&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="nx"&gt;fetchMock&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;jest-fetch-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  2. Create Mock Query Provider
&lt;/h4&gt;

&lt;p&gt;To test out &lt;code&gt;useQuery&lt;/code&gt; hook, you need to wrap it inside a mock &lt;code&gt;QueryClientProvider&lt;/code&gt;. Since this mock query provider is going to be used more than once, let’s create a library for this wrapper:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# expo library  &lt;/span&gt;
npx nx generate @nx/expo:library test-wrapper &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries  

&lt;span class="c"&gt;# react native library  &lt;/span&gt;
npx nx generate @nx/react-native:library test-wrapper &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then a component inside this library:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# expo library  &lt;/span&gt;
npx nx generate @nx/expo:component test-wrapper &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries-test-wrapper  

&lt;span class="c"&gt;# react native library  &lt;/span&gt;
npx nx generate @nx/react-native:component test-wrapper &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries-test-wrapper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Add the mock &lt;code&gt;QueryClientProvider&lt;/code&gt; in &lt;code&gt;libs/queries/test-wrapper/src/lib/test-wrapper/test-wrapper.tsx&lt;/code&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;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&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;@tanstack/react-query&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;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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TestWrapperProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapperProps&lt;/span&gt;&lt;span class="p"&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/QueryClientProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  3. Use Mock Responses in Unit Test
&lt;/h4&gt;

&lt;p&gt;Then this is what the unit test for my query would look 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;TestWrapper&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-expo-monorepo/queries/test-wrapper&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitFor&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;@testing-library/react-native&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCatFact&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;./use-cat-fact&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;fetchMock&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;jest-fetch-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useCatFact&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;afterEach&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="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetAllMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be success&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// simulating a server response  &lt;/span&gt;
    &lt;span class="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResponseOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
      &lt;span class="na"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query  &lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be error&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockRejectOnce&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;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query  &lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you use axios, your unit test would look like this:&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;TestWrapper&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-expo-monorepo/queries/test-wrapper&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitFor&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;@testing-library/react-native&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCatFact&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;./use-cat-fact&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;axios&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;axios&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;MockAdapter&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;axios-mock-adapter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This sets the mock adapter on the default instance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockAxios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MockAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useCatFact&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;afterEach&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="nx"&gt;mockAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be success&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// simulating a server response&lt;/span&gt;
    &lt;span class="nx"&gt;mockAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onGet&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replyOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be error&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;mockAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onGet&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replyOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice that this file imports &lt;code&gt;TestWrapper&lt;/code&gt; from &lt;code&gt;@nx-expo-monorepo/queries/test-wrapper&lt;/code&gt;, and it is added to &lt;code&gt;renderHook&lt;/code&gt; function with &lt;code&gt;{ wrapper: TestWrapper }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you run the test command &lt;code&gt;nx test queries-use-cat-fact&lt;/code&gt;, it should pass:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; PASS   queries-use-cat-fact  libs/queries/use-cat-fact/src/lib/use-cat-fact.spec.ts (5.158 s)  
  useCatFact  
    ✓ status should be success (44 ms)  
    ✓ status should be error (96 ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Integrate with Component
&lt;/h3&gt;

&lt;p&gt;Currently &lt;code&gt;userQuery&lt;/code&gt; returns the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;isLoading&lt;/code&gt; or &lt;code&gt;status === 'loading'&lt;/code&gt; - The query has no data yet&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;isError&lt;/code&gt; or &lt;code&gt;status === 'error'&lt;/code&gt; - The query encountered an error&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;isSuccess&lt;/code&gt; or &lt;code&gt;status === 'success'&lt;/code&gt; - The query was successful and data is available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now with components controlled by the server state, you can leverage the above properties and change your component to follow the below pattern:&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CarouselProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Carousel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;CarouselProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;  
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Carousel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then in the parent component, you can use the query created above:&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;useCatFact&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-expo-monorepo/queries/use-cat-fact&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Carousel&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-expo-monorepo/ui&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;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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Facts&lt;/span&gt;&lt;span class="p"&gt;()&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isFetching&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
    &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Carousel&lt;/span&gt;  
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isFetching&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;onReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;refetch&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="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;If you serve the app on the web and open the &lt;a href="https://tanstack.com/query/v4/docs/react/devtools"&gt;React Query Devtools&lt;/a&gt;, you should be able to see the query I created &lt;code&gt;cat-fact&lt;/code&gt; and data in the query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qb917ouQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AvGUQ_wHNfm2zqln-z0NE-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qb917ouQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AvGUQ_wHNfm2zqln-z0NE-Q.png" alt="React Query Devtools" width="800" height="860"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Redux
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Create a Library
&lt;/h3&gt;

&lt;p&gt;First, you need to create a library for redux:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# expo library  &lt;/span&gt;
npx nx generate @nx/expo:lib &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;states  

&lt;span class="c"&gt;# react native library  &lt;/span&gt;
npx nx generate @nx/react-native:lib &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;states
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This should create a folder under libs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9RDzr7K4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Ae5jaFK8syLNF1ndMFcEmPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9RDzr7K4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Ae5jaFK8syLNF1ndMFcEmPw.png" alt="cat folder under libs/states" width="416" height="736"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a State
&lt;/h3&gt;

&lt;p&gt;This app is going to track when users click the like button, so you need to create a state called &lt;code&gt;likes&lt;/code&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%2Fk5vfoiwekprk0m9no8zb.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%2Fk5vfoiwekprk0m9no8zb.png" alt="Cats like button" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://nx.dev/recipes/nx-console"&gt;Nx Console&lt;/a&gt; to create a redux slice:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kNKTidIJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AdJ5O8O4Eetpig6pu7lerGA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kNKTidIJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AdJ5O8O4Eetpig6pu7lerGA.png" alt="nx console slice" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or run this 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 generate @nx/react:redux likes &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;states-cat &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;likes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then update the redux slice at &lt;code&gt;libs/states/cat/src/lib/likes/likes.slice.ts&lt;/code&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;createEntityAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;,&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;@reduxjs/toolkit&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LIKES&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_FEATURE&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;likes&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;dateAdded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LikesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;EntityState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LikesEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createEntityAdapter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LikesEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialLikesState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LikesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LIKES&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_FEATURE&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialLikesState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;like&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAll&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="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\*&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Export&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;  
 &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="sr"&gt;/ &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&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;selectAll&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelectors&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;getlikesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ROOT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LikesState&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="nx"&gt;rootState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ROOT&lt;/span&gt;  
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;LikesState&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rootState&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;LIKES&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_FEATURE&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_KEY&lt;/span&gt;&lt;span class="err"&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;selectAllLikes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getlikesState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectAll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesSelectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;selectAllLikes&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;Every time the “like” button gets clicked, you want to store the content of what users liked. So you need to create an entity to store this information.&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;dateAdded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;This state has 3 actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  like: when users click like&lt;/li&gt;
&lt;li&gt;  remove: when users cancel the like&lt;/li&gt;
&lt;li&gt;  clear: when users clear all the likes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Root Store
&lt;/h3&gt;

&lt;p&gt;Then you have to add the root store and create a transform function to stringify the redux state:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Connect Redux State with UI
&lt;/h3&gt;

&lt;p&gt;Then in &lt;code&gt;apps/cats/src/app/App.tsx&lt;/code&gt;, you have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  wrap the app inside the &lt;code&gt;StoreProvider&lt;/code&gt; with the root store to connect with the Redux state.&lt;/li&gt;
&lt;li&gt;  wrap the app inside &lt;code&gt;PersistGate&lt;/code&gt; to persist the redux state in the storage
&lt;/li&gt;
&lt;/ul&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="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;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;AsyncStorage&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;@react-native-async-storage/async-storage&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PersistGate&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;redux-persist/integration/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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRootStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transformEntityStateToPersist&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-expo-monorepo/states/cat&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Loading&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-expo-monorepo/ui&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;StoreProvider&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;react-redux&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;App&lt;/span&gt; &lt;span class="o"&gt;=&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;persistConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;transforms&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="nx"&gt;transformEntityStateToPersist&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&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;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;persistor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRootStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;persistConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PersistGate&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;persistor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;persistor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StoreProvider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StoreProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/PersistGate&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your component where the like button is located, you need to dispatch the like action. I created a file at &lt;code&gt;apps/cats/src/app/facts/facts.props.ts&lt;/code&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;likesActions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RootState&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-expo-monorepo/states/cat&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AnyAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ThunkDispatch&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;@reduxjs/toolkit&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;mapDispatchToProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ThunkDispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AnyAction&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;likesActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="p"&gt;};&lt;/span&gt;  

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToPropsType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToProps&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;type&lt;/span&gt; &lt;span class="nx"&gt;FactsProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToPropsType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToProps&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FactsProps&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have passed the &lt;code&gt;like&lt;/code&gt; function to the props of the facts component. Now inside the facts component, you can call the like function from props to dispatch the like action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging
&lt;/h3&gt;

&lt;p&gt;To debug redux with Expo, I can simply open the Debugger Menu by entering “d” in the console or in the app, then choose the option “Open JS Debugger”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hWALlr87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Akp09e4iConN0-NF-LkMj7A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hWALlr87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Akp09e4iConN0-NF-LkMj7A.png" alt="JS Debugger" width="800" height="1734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you can view my redux logs in the JS Debugger console:&lt;/p&gt;

&lt;p&gt;You can see the redux logs in console now:&lt;br&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%2Fgq3pymwkk0z11naeh186.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%2Fgq3pymwkk0z11naeh186.png" alt="Redux Logs" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you can run &lt;code&gt;nx serve cats&lt;/code&gt; to launch the app in web view. Then you can use Redux Devtools and debug the native app like a web app:&lt;br&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%2Fjimbmg65n32lgwsvikwm.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%2Fjimbmg65n32lgwsvikwm.png" alt="Redux Devtools" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Here is a simple app that uses TanStack Query and Redux for state management. These 2 tools are pretty powerful and they manage both server and client state for you, which is easy to scale, test, and debug.&lt;/p&gt;

&lt;p&gt;Nx is a powerful monorepo tool. Together with Nx and these 2 state management tools, it will be very easy to scale up any app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  TanStack Query site: &lt;a href="https://tanstack.com/query/latest"&gt;https://tanstack.com/query/latest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Official @nx/expo plugin: &lt;a href="https://nx.dev/packages/expo"&gt;https://nx.dev/packages/expo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Official @nx/react-native plugin: &lt;a href="https://nx.dev/packages/react-native"&gt;https://nx.dev/packages/react-native&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/"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  👩‍💻 &lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  💬 &lt;a href="https://go.nrwl.io/community"&gt;Nx Community Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  📹 &lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🚀 &lt;a href="https://nx.app/"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tanstack</category>
      <category>reactnative</category>
      <category>expo</category>
      <category>redux</category>
    </item>
    <item>
      <title>Step-by-Step Guide to Creating an Expo Monorepo with Nx</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 16 Feb 2024 22:19:07 +0000</pubDate>
      <link>https://dev.to/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17</link>
      <guid>https://dev.to/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17</guid>
      <description>&lt;p&gt;This blog will show you how to create an Expo monorepo with Nx. In this example, you will be creating two Expo apps in a monorepo with @nx/expo: one shows random facts about cats, and the other shows random facts about dogs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fonnb7oaebj8bjdm7hhnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fonnb7oaebj8bjdm7hhnz.png" alt="Cats App Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fij4elkatpvxomkm81530.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fij4elkatpvxomkm81530.png" alt="Dogs App Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown in the above screenshots, these two apps have the same branding and reuse all components.&lt;/p&gt;

&lt;p&gt;This blog will go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to create a monorepo workspace with Nx&lt;/li&gt;
&lt;li&gt;How to share a React Native library&lt;/li&gt;
&lt;li&gt;How to build an Expo app&lt;/li&gt;
&lt;li&gt;How to submit an Expo app to the app store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Github repo: &lt;a href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;https://github.com/xiongemi/nx-expo-monorepo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating an Nx Workspace
&lt;/h2&gt;

&lt;p&gt;To create a new Nx workspace, run the command npx create-nx-workspace  in the terminal. In this example, let’s name it nx-expo-monorepo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔ Where would you like to create your workspace? · create-nx-monorepo
✔ Which stack do you want to use? · react
✔ What framework would you like to use? · expo
✔ Application name · cats
✔ Enable distributed caching to make your CI faster · No
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will create an &lt;a href="https://nx.dev/concepts/integrated-vs-package-based#integrated-repos" rel="noopener noreferrer"&gt;integrated repo&lt;/a&gt;. What is an integrated repo?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An integrated repo contains projects that depend on each other through standard import statements. There is typically a single version of every dependency defined at the root.&lt;br&gt;
&lt;a href="https://nx.dev/concepts/integrated-vs-package-based#integrated-repos" rel="noopener noreferrer"&gt;https://nx.dev/concepts/integrated-vs-package-based#integrated-repos&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, your Nx workspace should have cats and cats-e2e under the apps folder and an empty libs folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Frt234mh8n0kn9m16pb62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Frt234mh8n0kn9m16pb62.png" alt="Nx workspace with cats app"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Existing Nx Workspace
&lt;/h3&gt;

&lt;p&gt;If you already have an Nx workspace, you need to install the @nx/expo package:&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/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To create an Expo app, 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 generate @nx/expo:app cats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alternatively, if you use Visual Studio Code as your code editor, you can also create apps using &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Filktnkv9awxe5drqpj7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Filktnkv9awxe5drqpj7b.png" alt="nx console"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Tech Stacks
&lt;/h2&gt;

&lt;p&gt;Here are the tech stacks this example is going to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Material design library: &lt;a href="https://callstack.github.io/react-native-paper/" rel="noopener noreferrer"&gt;react-native-paper&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm  
npm install react-native-paper react-native-safe-area-context --save  

# yarn  
yarn add react-native-paper react-native-safe-area-context  

# pnpm  
pnpm add react-native-paper react-native-safe-area-context --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Routing: &lt;a href="https://reactnavigation.org/" rel="noopener noreferrer"&gt;@react-navigation/native&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm  
npm install react-native-paper react-native-screens @react-navigation/native-stack --save  

# yarn  
yarn add react-native-paper react-native-screens @react-navigation/native-stack  

# pnpm  
pnpm add react-native-paper react-native-screens @react-navigation/native-stack --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Create a Shareable UI Library
&lt;/h2&gt;

&lt;p&gt;With all the required libraries installed, you need to create a sharable UI library:&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 generate @nx/expo:lib ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now under the &lt;code&gt;libs&lt;/code&gt; folder, a &lt;code&gt;ui&lt;/code&gt; folder has been created:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fspgvugsru2q1hbvhghfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fspgvugsru2q1hbvhghfw.png" alt="ui folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a component in the &lt;code&gt;ui&lt;/code&gt; library, 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 generate @nx/expo:component carousel --project=ui --export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can see that a &lt;code&gt;carousel&lt;/code&gt; folder has been created in the &lt;code&gt;libs/ui/src/lib&lt;/code&gt; folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwyzjj5bxrv0jd0g1wi1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwyzjj5bxrv0jd0g1wi1l.png" alt="carousel folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, modify this component to display the content with props passed in:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now you can use this component in your app directly using an import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Carousel } from '@nx-expo-monorepo/ui';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Add Navigation
&lt;/h2&gt;

&lt;p&gt;This project is going to use the &lt;a href="https://reactnavigation.org/docs/stack-navigator" rel="noopener noreferrer"&gt;stack navigator&lt;/a&gt; from &lt;a href="https://reactnavigation.org/" rel="noopener noreferrer"&gt;@react-navigation/native&lt;/a&gt;. So the app needs to import from @react-navigation/stack. In &lt;code&gt;apps/cats/src/app/App.tsx&lt;/code&gt;, you can change the UI to have one screen displaying a carousel with mock data:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Run the app with &lt;code&gt;nx start cats&lt;/code&gt;, and you should be able to see the app on the simulator:&lt;/p&gt;

&lt;p&gt;Page on the simulator (left: iOS, right: Android)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhrqhgf7lh5uf684gaqzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhrqhgf7lh5uf684gaqzj.png" alt="Cats app screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Another App
&lt;/h2&gt;

&lt;p&gt;In this example, there is already a &lt;code&gt;Cats&lt;/code&gt; app. To create the &lt;code&gt;Dogs&lt;/code&gt; app, run the 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 generate @nx/expo:app dogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alternatively, if you use Visual Studio Code as your code editor, you can also create apps using &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2A8ut9KSAOn-UBBNxHJMtVXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2A8ut9KSAOn-UBBNxHJMtVXQ.png" alt="nx console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the apps folder, there should be &lt;code&gt;cats/&lt;/code&gt;, &lt;code&gt;dogs/&lt;/code&gt; and their e2es.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzxtra7hkk76srplz2ne3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzxtra7hkk76srplz2ne3.png" alt="apps folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can reuse the UI library in the Dogs app in &lt;code&gt;apps/dogs/src/app/App.tsx&lt;/code&gt; with the below code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Build Expo Apps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.expo.dev/build/introduction/" rel="noopener noreferrer"&gt;EAS Build&lt;/a&gt; is a hosted service for building app binaries for your Expo and React Native projects. To set up EAS locally:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install EAS CLI
&lt;/h3&gt;

&lt;p&gt;EAS CLI is the command-line app to interact with EAS services in the terminal. To install it, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g eas-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Login To EAS
&lt;/h3&gt;

&lt;p&gt;If you are not logged in, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eas login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Build the Apps
&lt;/h3&gt;

&lt;p&gt;After the EAS setup, you can build apps by running the 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 build cats  
npx nx build dogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are different options you can specify with the build command. For example, you can specify the platform you want to build:&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 build cats --platform=all  
npx nx build cats --platform=android  
npx nx build cats --platform=ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, if you want to create a build to run on a simulator/emulator, you can 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 build cats --profile=preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can view your build status at &lt;a href="https://expo.dev/" rel="noopener noreferrer"&gt;https://expo.dev/&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2ApQxTgypzL10_SmI71jaWVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2ApQxTgypzL10_SmI71jaWVQ.png" alt="expo.dev"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to create a build locally using your own infrastructure:&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 build cats --local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the complete list of flags for the build command: &lt;a href="https://nx.dev/packages/expo/executors/build" rel="noopener noreferrer"&gt;https://nx.dev/packages/expo/executors/build&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submit to the App Store
&lt;/h3&gt;

&lt;p&gt;Before you submit, you need to have paid developer accounts for iOS and Android.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  iOS: You need to create an Apple Developer account on the Apple &lt;a href="https://developer.apple.com/account/" rel="noopener noreferrer"&gt;Developer Portal&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Android: You need to create a Google Play Developer account on the &lt;a href="https://play.google.com/apps/publish/signup/" rel="noopener noreferrer"&gt;Google Play Console sign-up page&lt;/a&gt;. You also need to manually create an app on &lt;a href="https://play.google.com/apps/publish/" rel="noopener noreferrer"&gt;Google Play Console&lt;/a&gt; and upload your app for the first time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Run the production build
&lt;/h3&gt;

&lt;p&gt;To submit to the app store, you can build the app 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 build cats --profile=production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Submit the Build
&lt;/h3&gt;

&lt;p&gt;You can manually upload the build bundle binary to the app store, or you can submit it through EAS.&lt;/p&gt;

&lt;p&gt;First, in &lt;code&gt;app.json&lt;/code&gt; under the project &lt;code&gt;apps/cats/app.json&lt;/code&gt;, you need to make sure&lt;code&gt;ios.bundleIdentifier&lt;/code&gt; and &lt;code&gt;android.package&lt;/code&gt; keys are correct:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1400%2Fformat%3Awebp%2F1%2Aj9TAZZgqplZCcjD4hiWNpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1400%2Fformat%3Awebp%2F1%2Aj9TAZZgqplZCcjD4hiWNpg.png" alt="app.json"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To submit your app to the app stores, 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 submit cats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nx will prompt you to choose the platform to which you want to submit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2APcBvY1SJCHZyOnJI1hskAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2APcBvY1SJCHZyOnJI1hskAQ.png" alt="submit prompt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you can also specify the platform directly in the initial 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 submit cats --platform=all  
npx nx submit cats --platform=android  
npx nx submit cats --platform=ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will then ask you to choose which binary to submit from one of the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The latest finished Android build for the project on EAS servers.&lt;/li&gt;
&lt;li&gt;  Specific build ID. It can be found on the &lt;a href="https://expo.dev/builds" rel="noopener noreferrer"&gt;builds dashboard&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Path to an .apk or .aab or .ipa archive on your local filesystem.&lt;/li&gt;
&lt;li&gt;  URL to the app archive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatively, you can submit your app on the &lt;a href="https://expo.dev/" rel="noopener noreferrer"&gt;expo.dev&lt;/a&gt; site. Go to your build, under options, choose “Submit to an app store”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AyQlEmKOy3TXdWPCk9ILiZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2AyQlEmKOy3TXdWPCk9ILiZA.png" alt="submit to an app store"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, you have learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create multiple apps in a monorepo using @nx/expo&lt;/li&gt;
&lt;li&gt;  Create a shared library&lt;/li&gt;
&lt;li&gt;  Build your app using EAS&lt;/li&gt;
&lt;li&gt;  Submit your app to the App Store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Nx, it is easy to create and scale up an Expo app. Even though this app is currently a simple 2-page app, you can easily scale it up with more libraries and components. Furthermore, you can also reuse those libraries in the future if you decide to add another app to the repo.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://medium.com/unit-testing-expo-apps-with-jest-22a0309aa7bb" rel="noopener noreferrer"&gt;Unit Testing Expo Apps With Jest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@emilyxiong/add-cypress-playwright-and-storybook-to-nx-expo-apps-1d3e409ce834" rel="noopener noreferrer"&gt;Add Cypress, Playwright, and Storybook to Nx Expo Apps&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://nx.app/" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>monorepo</category>
      <category>expo</category>
      <category>nx</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Launch Nx Week Recap!!</title>
      <dc:creator>Zack DeRose</dc:creator>
      <pubDate>Thu, 15 Feb 2024 18:09:12 +0000</pubDate>
      <link>https://dev.to/nx/launch-nx-week-recap-51og</link>
      <guid>https://dev.to/nx/launch-nx-week-recap-51og</guid>
      <description>&lt;p&gt;We just finished wrapping up &lt;a href="https://nx.dev/launch-nx"&gt;Launch Nx Week&lt;/a&gt;, which ran from February 5-9, including a full conference on Thursday!&lt;/p&gt;

&lt;p&gt;In this article, we're going to recap all the things launched during Launch Nx Conf, as well as all the talks given during the conference! Here's a set of links so you can fast-forward to the stuff you're most interested in if you want!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Nx 18.0 &amp;amp;&amp;amp; Project Crystal

&lt;ul&gt;
&lt;li&gt;Project Crystal - By Juri Strumpflohner&lt;/li&gt;
&lt;li&gt;Project Crystal + .NET in Action - By Craigory Coppola&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;New Plugin: @nx/nuxt&lt;/li&gt;
&lt;li&gt;
Nx Agents

&lt;ul&gt;
&lt;li&gt;Nx Agents Walkthrough: Effortlessly Fast CI Built for Monorepos - By Rares Matei&lt;/li&gt;
&lt;li&gt;Solving E2E Tests - By Altan Stalker&lt;/li&gt;
&lt;/ul&gt;


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

&lt;ul&gt;
&lt;li&gt;Releasing Nx Release - By James Henry&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nx 18.0 &amp;amp;&amp;amp; Project Crystal&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Exciting news!! We've broken our standard release cadance of publishing a new major version every 6 months to release Nx 18, just 3 months after releasing Nx 17 in December 2024.&lt;/p&gt;

&lt;p&gt;Juri announced launched Project Crystal with this video:&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;The short version is: Nx project crystal means Nx plugins make your codebases work more seemlessly with less config.&lt;/p&gt;

&lt;p&gt;For the long version, checkout this &lt;a href="https://blog.nrwl.io/what-if-nx-plugins-were-more-like-vscode-extensions-dcdad140ae09"&gt;blog post&lt;/a&gt; by Juri where he describes how Nx plugins are now more like VsCode Extentions!&lt;/p&gt;

&lt;p&gt;And don't miss our two conference talks on this subject:&lt;/p&gt;

&lt;h3&gt;
  
  
  Conference Talk: Project Crystal&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/juristr"&gt;Juri Strumpflohner&lt;/a&gt; | &lt;a href="https://drive.google.com/file/d/1k-cGCJUMP4axcCWoeih8n3dvo1oO_i_X/view?usp=sharing"&gt;slides&lt;/a&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Conference Talk: Project Crystal + .NET in Action&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/enderagent"&gt;Craigory Coppola&lt;/a&gt; | &lt;a href="https://docs.google.com/presentation/d/1uveIe6HB7xwSkh7FBGZfF8Unh5YZzm5X/edit?usp=sharing&amp;amp;ouid=109667724870581513512&amp;amp;rtpof=true&amp;amp;sd=true"&gt;slides&lt;/a&gt; | &lt;a href="https://github.com/AgentEnder/nx-launch-conf-demos"&gt;example repo&lt;/a&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  New Plugin: @nx/nuxt&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;On Tuesday we launched our newest plugin, and our first plugin to be 💎crystalized💎 from it's very beginning: @nx/nuxt!&lt;/p&gt;

&lt;p&gt;Zack explains Nuxt and how to use the new plugin in this video:&lt;/p&gt;

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

&lt;p&gt;To add @nx/nuxt to your codebase, use 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="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nx add @nx/nuxt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Huge thanks to &lt;a href="https://twitter.com/psybercity"&gt;Katerina&lt;/a&gt; for her work on the plugin, and Nuxt maintainer, &lt;a href="https://twitter.com/danielcroe"&gt;Daniel Roe&lt;/a&gt;, for helping to guide the project!&lt;/p&gt;

&lt;p&gt;Zack, Katerina, and Daniel got together to live code a working tic-tac-toe app using the new Nuxt plugin and &lt;a href="https://www.partykit.io/"&gt;partykit&lt;/a&gt; in this livestream:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Nx Agents Launched&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Nx Agents are here!! We launched Nx Agents on Wednesday, and it climbed into the top 20 on &lt;a href="https://www.producthunt.com/posts/nx-agents"&gt;Product Hunt&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;We're very excited about Nx Agents because we think that in its current state, Continuous Integration/Deployment is broken, and we think that Nx paired with Nx Agents fixes Continuous Integration. Zack explains more in this video:&lt;/p&gt;

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

&lt;p&gt;Be sure to also checkout the &lt;a href="https://blog.nrwl.io/fast-effortless-ci-67812514ffb4"&gt;blog post&lt;/a&gt; from Isaac on the topic, including explanations of the Nx Agents exclusive features, like auto-detection and retrying for flaky tasks, and automatically splitting lengthy end-to-end tests!&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://nx.app/products/agents#content"&gt;signup for Nx Agents NOW&lt;/a&gt;, and &lt;a href="https://nx.dev/ci/features/distribute-task-execution"&gt;find out more of the details in our docs&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Rares and Altan are on the team building Nx Cloud, and during the conference, they dove deeper into some of these topics:&lt;/p&gt;

&lt;h3&gt;
  
  
  Conference Talk: Nx Agents Walkthrough: Effortlessly Fast CI Built for Monorepos&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/__rares"&gt;Rares Matei&lt;/a&gt; | &lt;a href="https://drive.google.com/file/d/1k-cGCJUMP4axcCWoeih8n3dvo1oO_i_X/view?usp=drive_link"&gt;slides&lt;/a&gt; | &lt;a href="https://github.com/rarmatei/shops-workflows/pulls"&gt;example repo&lt;/a&gt; | &lt;a href="https://cloud.nx.app/cipes/65b27cf6d3ef5934decad746?utm_source=pull-request&amp;amp;utm_medium=comment"&gt;failed runs example&lt;/a&gt; | &lt;a href="https://cloud.nx.app/cipes/65b38179d3ef5934dede74c2?utm_source=pull-request&amp;amp;utm_medium=comment"&gt;nx agents full run&lt;/a&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Conference Talk: Solving E2E Tests&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/StalkAltan"&gt;Altan Stalker&lt;/a&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Tusky&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Thursday, we had a surprise announcement for our newest product on Nx Cloud: Tusky.&lt;/p&gt;

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

&lt;p&gt;Tusky is an Artificial Intelligence for your codebase, and it will be available on Nx Cloud soon - starting in Spring of 2024.&lt;/p&gt;

&lt;p&gt;In the teaser video, you can see some ways Tusky will be integrated into Nx Cloud to provide explainations on failed tasks, or cache misses.&lt;/p&gt;

&lt;p&gt;The more exciting features of Tusky though includes the ability to perfectly optimize the number of agents used per PR - even spinning up and tearing down agents mid-pipeline! This is a huge optimization for task distribution, and will help optimize both walltime of your CI, as well as compute costs!&lt;/p&gt;

&lt;p&gt;Tusky will also be able to provide organizational-level insights to your codebase, including automatically detecting development groups (like lines of business) inside your codebase based on commit history, and providing statistical insights on their commit patterns. We're also excited about Tusky being able to make suggestions on things you can do to further optimize your codebase - like generating a PR to introduce &lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners"&gt;Codeowners&lt;/a&gt; to the repo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Release Is Stable&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Versioning and publishing packages is always a bit tricky. Mix in the added complexity of having multiple packages - sometimes with different versioning or publishing strategies - inside the same codebase, and things can get weird quick!&lt;/p&gt;

&lt;p&gt;For a long time, Nx has been purposefully versioning and publishing agnostic, but given our time spent as &lt;a href="https://blog.nrwl.io/lerna-is-dead-long-live-lerna-61259f97dbd9"&gt;stewards of Lerna&lt;/a&gt; (the OG Javascript monorepo tool), we've been able to take alot of that experience and finally feel confident creating our own versioning and publishing implementation.&lt;/p&gt;

&lt;p&gt;Therefore, we've been working on a new command to the Nx CLI: &lt;a href="https://nx.dev/recipes/nx-release/get-started-with-nx-release#get-started-with-nx-release"&gt;nx release&lt;/a&gt;. We launched this on Friday of our Launch Nx week!&lt;/p&gt;

&lt;p&gt;Juri goes into full details in this &lt;a href="https://blog.nrwl.io/versioning-and-releasing-packages-in-a-monorepo-45ee194378d1"&gt;blog post&lt;/a&gt;, and James Henry - our Director of Engineering and the primary engineer responsible for both maintaining Lerna and creating Nx Release - expands further in his conference talk:&lt;/p&gt;

&lt;h3&gt;
  
  
  Conference Talk: Releasing Nx Release&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Speaker:&lt;/strong&gt; &lt;a href="https://twitter.com/MrJamesHenry"&gt;James Henry&lt;/a&gt; | &lt;a href="https://github.com/JamesHenry/nx-release-cmd"&gt;example repo&lt;/a&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;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Juri, Zack, and Victor wrapped up the week with a livestream recapping the launches from the week - including answering your questions live:&lt;/p&gt;

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

&lt;p&gt;That’s all for now folks! We’re just starting up a new iteration of development on Nx, so be sure to subscribe to our &lt;a href="https://www.youtube.com/@nxdevtools"&gt;YouTube channel&lt;/a&gt; to get updates when new features land! Until next time, KEEP WORKING HARD!&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn more
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nx.dev/community"&gt;Nx Official Discord Server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nx</category>
      <category>monorepos</category>
      <category>javascript</category>
    </item>
    <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://dev.to/nx/versioning-and-releasing-packages-in-a-monorepo-31pk</link>
      <guid>https://dev.to/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>Introducing @nx/nuxt: Enhanced Nuxt.js Support in Nx</title>
      <dc:creator>Katerina Skroumpelou</dc:creator>
      <pubDate>Tue, 06 Feb 2024 16:35:05 +0000</pubDate>
      <link>https://dev.to/nx/introducing-nxnuxt-enhanced-nuxtjs-support-in-nx-ai7</link>
      <guid>https://dev.to/nx/introducing-nxnuxt-enhanced-nuxtjs-support-in-nx-ai7</guid>
      <description>&lt;p&gt;We're excited to introduce a new way to enhance your &lt;a href="https://nuxt.com/"&gt;Nuxt&lt;/a&gt; development workflow! After the Vue plugin, we're introducing our new Nx plugin for Nuxt, &lt;code&gt;@nx/nuxt&lt;/code&gt;. Designed for Nuxt developers and existing Nx users alike, this integration brings the best of both worlds into your development ecosystem, enabling you to leverage Nx's powerful capabilities seamlessly within your Nuxt projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Consider Nx for Your Nuxt Projects?
&lt;/h2&gt;

&lt;p&gt;Using Nx with your Nuxt.js projects presents the following advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monorepo Management&lt;/strong&gt;: Simplify the management of multiple projects within a single repository, facilitating code sharing and reducing overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Development&lt;/strong&gt;: Break down your Nuxt app into manageable, independent modules that can be developed, tested, and deployed in isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Caching&lt;/strong&gt;: Accelerate your development with Nx's intelligent caching, automatically configured for your Nuxt projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nx generators&lt;/strong&gt;: Nx provides generators for scaffolding new Nuxt applications, with support for Jest, Storybook, and e2e test generation with Cypress or Playwright.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated upgrades&lt;/strong&gt;: Nx offers a set of migrators that help you upgrade your projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started with Nx and Nuxt.js
&lt;/h2&gt;

&lt;p&gt;Whether you're initiating a new project or integrating into an existing one, &lt;code&gt;@nx/nuxt&lt;/code&gt; offers a straightforward setup process:&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting a New Nx Workspace with Nuxt
&lt;/h3&gt;

&lt;p&gt;Creating a new Nx workspace optimized for Nuxt is as simple 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 create-nx-workspace@latest --preset=nuxt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our setup wizard will guide you through the initial configuration, ensuring your workspace is tailored to your needs:&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

 &amp;gt;  NX   Let's create a new workspace [https://nx.dev/getting-started/intro]

✔ Where would you like to create your workspace? · my-org
✔ Which stack do you want to use? · vue
✔ What framework would you like to use? · nuxt
✔ Integrated monorepo, or standalone project? · integrated
✔ Application name · my-app
✔ Test runner to use for end to end (E2E) tests · playwright (also cypress)
✔ Default stylesheet format · scss (also css, less)
✔ Set up CI with caching, distribution and test deflaking · github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command will create a new Nx workspace with a single Nuxt application, complete with essential features and ready for development.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enhancing an Existing Nuxt Project with Nx
&lt;/h2&gt;

&lt;p&gt;Integrating Nx into an existing Nuxt.js project has never been easier, with the help of the &lt;code&gt;nx init&lt;/code&gt; command. This command will add Nx to your project without the need to disrupt your current setup.&lt;/p&gt;
&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;When you run &lt;code&gt;nx init&lt;/code&gt; in your existing Nuxt.js project, Nx does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Installs @nx/nuxt&lt;/strong&gt;: Adds the necessary Nx and @nx/nuxt dependencies to your project, enabling Nx's features while keeping your existing setup intact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understands Existing Configurations&lt;/strong&gt;: Nx automatically recognizes your nuxt.config.js or nuxt.config.ts file, ensuring that all your custom configurations, scripts, and commands are preserved and utilized.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal Configuration&lt;/strong&gt;: Only a minimal &lt;code&gt;nx.json&lt;/code&gt; file is added to your project. This file is used to configure the &lt;code&gt;@nx/nuxt&lt;/code&gt; plugin if needed, but in most cases, your existing Nuxt.js configurations will suffice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To begin the integration process, simply navigate to the root of your existing Nuxt.js project and 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 init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This approach offers several key benefits for teams looking to adopt Nx:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Disruption&lt;/strong&gt;: Your project will continue to use its existing configurations, and the existing configuration entrypoint files. There's no need to learn new configuration syntaxes or reconfigure your project to start using Nx.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immediate Value&lt;/strong&gt;: Instantly gain access to Nx's powerful developer tools and build system, without significant changes to your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future Flexibility&lt;/strong&gt;: As your project grows, Nx is ready to scale with you. You can gradually adopt more Nx features and plugins over time, at a pace that suits your team.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Using Nx to run your Nuxt app
&lt;/h2&gt;

&lt;p&gt;Nx scans your workspace to look for Nuxt configuration files (eg. &lt;code&gt;nuxt.config.ts&lt;/code&gt;). It uses these files to understand where your Nuxt projects live, and uses them to set up tasks that can be invoked through Nx, like &lt;code&gt;serve&lt;/code&gt; and &lt;code&gt;build&lt;/code&gt;. So, in your Nx workspace, you can then run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx serve my-nuxt-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx build my-nuxt-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and these commands will call the &lt;code&gt;nuxt&lt;/code&gt; CLI under the hood, enhanced with Nx's features.&lt;/p&gt;

&lt;p&gt;You can see a visual representation of your task dependencies 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 graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s2JDXfSA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/gLex9co.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s2JDXfSA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/gLex9co.png" alt="Task graph - build" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also see how Nx configures your tasks, 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 show project my-nuxt-app --web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qlebSKat--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/eA56wHy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qlebSKat--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/eA56wHy.png" alt="Project details" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XqBG8tIv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/RF7e2rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XqBG8tIv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/RF7e2rj.png" alt="Project details - individual task details" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Using Nx Console
&lt;/h3&gt;

&lt;p&gt;You get access to all these features through our VSCode and WebStorm &lt;a href="https://nx.dev/features/integrate-with-editors"&gt;Nx Console extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can use Nx Console to visualize tasks, and understand where each inferred task (like &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;serve&lt;/code&gt; in Nuxt's case) is coming from, with our codelens-like feature, as an alternative to the &lt;code&gt;--web&lt;/code&gt; flag on the &lt;code&gt;nx show project&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Nx Console is also very convenient for generating code and running tasks, since it offers a graphical user interface for all the amazing features of the Nx CLI.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Does Nx Bring to Your Nuxt Development?
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;@nx/nuxt&lt;/code&gt;, your Nuxt projects gain automatic recognition of &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;serve&lt;/code&gt; processes. There's no need to deal with unfamiliar configurations; Nx intuitively understands your Nuxt project structure and optimizes accordingly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Modularize and Scale with Ease
&lt;/h3&gt;

&lt;p&gt;One of the most compelling aspects of using Nx with Nuxt.js is the ability to modularize large applications into manageable libraries or components. This not only makes your codebase more organized and maintainable but also significantly enhances your development workflow and CI processes.&lt;/p&gt;
&lt;h4&gt;
  
  
  Breaking Down a Monolithic Nuxt App
&lt;/h4&gt;

&lt;p&gt;Large Nuxt applications can become challenging to maintain and scale over time. By adopting Nx, you can structure your Nuxt app as a collection of smaller, focused libraries. Each library can encapsulate specific functionalities or features, such as UI components, utilities, or business logic.&lt;/p&gt;
&lt;h4&gt;
  
  
  Independent Development and Testing
&lt;/h4&gt;

&lt;p&gt;This modular structure allows teams to work on different aspects of the application in parallel, reducing bottlenecks and improving collaboration. Furthermore, you can run tests, linters, and other checks independently for each library, making your development process more efficient and targeted.&lt;/p&gt;

&lt;p&gt;For instance, if you want to create a new Vue UI library, you can 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;nx generate @nx/vue:lib my-shared-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command creates a my-shared-ui library within your workspace, which can then be used across your Nuxt app and potentially other applications within the same workspace.&lt;/p&gt;
&lt;h4&gt;
  
  
  Enhancing CI with Modular Builds
&lt;/h4&gt;

&lt;p&gt;On the CI front, Nx's modular approach makes things much faster. You can configure your CI pipeline to build, test, and deploy only the affected libraries and applications, thanks to Nx's advanced dependency graph analysis. This results in faster CI runs and more efficient resource utilization.&lt;/p&gt;
&lt;h4&gt;
  
  
  Sharing Code Between Applications
&lt;/h4&gt;

&lt;p&gt;Nx's workspace model facilitates code sharing between projects, which is particularly useful in monorepos containing multiple front-end projects. With Nx, sharing UI components, utilities, or services between these applications becomes straightforward.&lt;br&gt;
To share code, simply import the library into your Nuxt and Vue applications as needed. Nx takes care of the rest, ensuring that dependencies are correctly managed and that your applications remain buildable and testable.&lt;/p&gt;

&lt;p&gt;Imagine a scenario where your workspace contains a Nuxt application for your public-facing website and a Vue application for an internal tool. You can create a shared library for common UI components, such as buttons, inputs, and modals, and use these components in both applications. This not only reduces duplication but also ensures consistency across your projects.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Importing a shared UI component in your Nuxt app
import { MyButton } from '@my-org/my-shared-ui';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Importing the same component in your Vue app
import { MyButton } from '@my-org/my-shared-ui';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Visualizing Your Project Structure
&lt;/h3&gt;

&lt;p&gt;Nx provides a clear overview of your project's structure and dependencies, making it easier to manage complex applications. The Nx Console extension for VSCode, for instance, offers a graphical interface to visualize and run tasks, enhancing your development experience.&lt;/p&gt;

&lt;p&gt;In your workspace, you can run&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and see the structure of your projects:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D2YCTaiV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/igflZRF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D2YCTaiV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/igflZRF.png" alt="A project graph" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Embracing Nx in Your Nuxt Journey
&lt;/h2&gt;

&lt;p&gt;Whether you're starting a new Nuxt project or looking to enhance an existing one, Nx offers a compelling set of tools and features to streamline your development process. From modularization to caching, the integration of Nx into your Nuxt projects promises a more efficient, scalable, and enjoyable development experience. By embracing Nx's capabilities in your Nuxt development, you're not just optimizing your current workflow; you're future-proofing your development process. As your projects grow and evolve, Nx's modular architecture and powerful tooling will continue to provide value, making your development experience more enjoyable and productive.&lt;/p&gt;


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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev"&gt;Nx Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/nxdevtools"&gt;X / Twitter&lt;/a&gt; - &lt;a href="https://www.linkedin.com/company/nrwl"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.nx.dev/community"&gt;Nx Community Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.app"&gt;Speed up your CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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>nuxt</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://dev.to/nx/what-if-nx-plugins-were-more-like-vscode-extensions-4oh0</link>
      <guid>https://dev.to/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://dev.to/nx/nx-highlights-of-2023-4a77</link>
      <guid>https://dev.to/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 17.2 Update!!</title>
      <dc:creator>Zack DeRose</dc:creator>
      <pubDate>Wed, 20 Dec 2023 17:02:39 +0000</pubDate>
      <link>https://dev.to/nx/nx-172-update-5ag8</link>
      <guid>https://dev.to/nx/nx-172-update-5ag8</guid>
      <description>&lt;p&gt;It's been a bit since we launched &lt;a href="https://blog.nrwl.io/nx-17-0-has-landed-1dad19176ff3"&gt;Nx 17&lt;/a&gt;! In this article, we'll go over some of the new developments and improvements that have landed in Nx 17.2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nx Closes In On 4 Million Weekly NPM Downloads!!&lt;/li&gt;
&lt;li&gt;New Simplified Project Configuration On the Way&lt;/li&gt;
&lt;li&gt;Rust for Speed, Typescript for extensibility&lt;/li&gt;
&lt;li&gt;Module Federation Updates&lt;/li&gt;
&lt;li&gt;Nx Release Updates&lt;/li&gt;
&lt;li&gt;Angular 17 (AND NgRx 17) Support&lt;/li&gt;
&lt;li&gt;Smart Monorepos - Fast CI&lt;/li&gt;
&lt;li&gt;New Canary Releases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nx Closes In On 4 Million Weekly NPM Downloads!!&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;2023 has been a great year for Nx! We worked with a lot of the teams out there building fantastic open source tools. And you can see the results: we made &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt; a first class citizen in many of our Nx plugins, we added support for &lt;a href="https://youtu.be/jGTE7xAcg24?si=gyFyW_uYjMq_5ELF"&gt;Rspack&lt;/a&gt;, streamlined our Node experience by adding an Nx team maintained &lt;a href="https://youtu.be/LHLW0b4fr2w?si=P5MPIiD_mxTpQStY"&gt;Fastify plugin&lt;/a&gt;, support for Storybook interaction testing, welcomed Playwright to the family and much more, continuing our missing to push developer productivity to the limits!&lt;/p&gt;

&lt;p&gt;And our downloads on NPM keep confirming this. We are about to cross 4 million downloads per week.&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%2Fsrlp1bucdu4qsjdwcipj.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%2Fsrlp1bucdu4qsjdwcipj.png" alt="Almost 4 million weekly downloads!" width="470" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this made you curious, keep an eye on &lt;a href="https://nx.dev/blog"&gt;our blog&lt;/a&gt; or &lt;a href="https://twitter.com/nxdevtools"&gt;X/Twitter&lt;/a&gt; as we're going to release a 2023 year recap blog post next week.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Simplified Project Configuration On the Way&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Adoption is crucial, and simplicity is the driver for adoption. Last year we heavily optimized how you can use Nx in an existing project. Just drop the &lt;code&gt;nx&lt;/code&gt; package (or run &lt;code&gt;nx init&lt;/code&gt;) and that's it. Nx understands your workspace and efficiently runs your &lt;code&gt;package.json&lt;/code&gt; scripts.&lt;/p&gt;

&lt;p&gt;Using Nx at that level is definitely useful as you get intelligent parallelization, task pipelines and caching. But it is just the tip of the iceberg of what Nx is actually capable of. Nx plugins provide much more, especially in terms of DX and developer productivity by taking away some of the burden of configuring your monorepo tooling. But many devs new to Nx found it harder to get started with them initially and incrementally migrating to Nx plugins wasn't as straightforward as we'd wanted it to be.&lt;/p&gt;

&lt;p&gt;This is something that's gonna change drastically in 2024. And we've layed the first cornerstone for that. Nx 17.2 includes what we codename "Nx project config v3". But it is behind a feature flag still as we're streamlining the last bits. The goal?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;going almost configuration-less (good defaults, you customize when you need to)&lt;/li&gt;
&lt;li&gt;allowing easy drop-in of Nx plugins into existing workspaces (provides immediate productivity gains, but stays out of your way)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This opens up a series of possibilities which we're already super excited about. You'll hear more about this in the new year ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust for Speed, Typescript for extensibility&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;At Nx, we've heavily embraced Typescript from the beginning, and we've been very happy with that decision.&lt;/p&gt;

&lt;p&gt;If you've been paying attention to previous release announcements though, you've probably noticed that we've been moving more and more of the computationally intensive and performance critical pieces of the core of Nx from Typescript to Rust.&lt;/p&gt;

&lt;p&gt;That trend continues in Nx 17.2 with Nx &lt;a href="https://github.com/nrwl/nx/pull/19617"&gt;using Rust for its task hashing by default&lt;/a&gt;. There's no adjustments needed for this change, and Nx will continue to behave the same way, just faster!&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;h2&gt;
  
  
  Module Federation Updates&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Module Federation has been a particularly hot topic lately, and 17.2 is coming in with some great enhancements to Nx's already best-in-class support for Module Federation!&lt;/p&gt;

&lt;p&gt;To start, we've greatly reduced the CPU and memory used for standing up your Module Federation "web" locally. These enhancements should be great news to larger workspaces using a Module Federation approach, where there were heavy CPU and memory costs to serving your entire federation locally.&lt;/p&gt;

&lt;p&gt;We accomplished these improvements by batching any applications that are not being watched for changes (listed with the &lt;code&gt;--devRemotes&lt;/code&gt; option) to a single server, rather than a unique server for each application. We also parallelized the builds of these static applications when you start up your serve! You can now use the &lt;code&gt;--parallel={number}&lt;/code&gt; option to specify how many builds you want going at any given time.&lt;/p&gt;

&lt;p&gt;In addition to performance improvements, we've brought the concept of dynamic federation to our React module federation support. Dynamic federation allows a host application to dynamically load remotes via the manifest file.&lt;/p&gt;

&lt;p&gt;You can generate your react module federation workspace now to use dyanmic federation via the &lt;code&gt;--dynamic&lt;/code&gt; flag:&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 generate @nx/react:host acme --remotes=nx --dynamic
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can use the utility itself by importing from &lt;code&gt;@nx/react/mf&lt;/code&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;loadRemoteModule&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/react/mf&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;Lastly, we have an &lt;a href="https://github.com/jaysoo/nx-react-vite-module-federation"&gt;example repo&lt;/a&gt; available now to illustrate how to create a plugin for Module Federation using Nx with Vite! This is something that we are monitoring and may provide an out-of-the-box solution to this in a future release!&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Release Updates&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Nx 17 launched with the new &lt;code&gt;nx release&lt;/code&gt; capability in the Nx CLI. Since then we've been streamlining the experience, accounting for various edge cases and release scenarios. (extensive docs are being worked on rn ;)&lt;/p&gt;

&lt;p&gt;To give you full flexibility, in 17.2, we've added a programmatic API, which will allow you to easily write custom release scripts:&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="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="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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minor&lt;/span&gt;&lt;span class="dl"&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="p"&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="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="mi"&gt;0&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;This script above demonstrates how you can use this API to create your own script for updating your workspace's version, then creating a changelog, and then publishing your package!&lt;/p&gt;

&lt;p&gt;We've also added first class support for independently released projects, meaning you can now target a specific project for release with the &lt;code&gt;--projects&lt;/code&gt; command. For example, you can create a new version for just one project in your workspace 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 release version patch --project=my-project
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Angular 17 (AND NgRx 17) Support&lt;a&gt;&lt;/a&gt;
&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%2Fy9jklw76upfhu8eef5q8.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%2Fy9jklw76upfhu8eef5q8.png" alt="Angular new" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.dev/"&gt;Angular&lt;/a&gt; is in the middle of &lt;a href="https://blog.angular.io/introducing-angular-v17-4d7033312e4b"&gt;a HUGE renaissance&lt;/a&gt;, between their new logo, new docs site, and introduction of some awesome features like Signals.&lt;/p&gt;

&lt;p&gt;Nx is here to support the transition! Nx has always been a great fit for Angular, and now supports Angular 17 as well as NgRx 17.&lt;/p&gt;

&lt;p&gt;To automatically migrate existing workspaces to Angular v17, run the commands:&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="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nx migrate latest
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nx migrate &lt;span class="nt"&gt;--run-migrations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use the &lt;code&gt;--interactive&lt;/code&gt; flag if you want to migrate your workspace to the latest version of Nx while staying on your current version of Angular:&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="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nx migrate latest &lt;span class="nt"&gt;--interactive&lt;/span&gt;
&lt;span class="go"&gt;✔ Do you want to update to TypeScript v5.2? (Y/n) · true
✔ Do you want to update the Angular version to v17? (Y/n) · false

&lt;/span&gt;&lt;span class="gp"&gt; &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;NX   The migrate &lt;span class="nb"&gt;command &lt;/span&gt;has run successfully.
&lt;span class="go"&gt;
   - package.json has been updated.
   - migrations.json has been generated.

&lt;/span&gt;&lt;span class="gp"&gt; &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;NX   Next steps:
&lt;span class="go"&gt;
   - Run 'nx migrate --run-migrations'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Smart Monorepos - Fast CI&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We just gave our &lt;a href="https://nx.dev"&gt;Nx homepage&lt;/a&gt; a small facelift, including a new tagline, subtagline and illustration to better reflect Nx's mission statement.&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%2Fcxsdzq77zhjj4skrme2v.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%2Fcxsdzq77zhjj4skrme2v.png" alt="New HomePage!" width="800" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you enter the monorepo space, having good local development experience and tooling to support you is one thing, scaling is the other. And scaling comes with multiple challenges, from scaling teams working on the monorepo to maintaining high throughput on CI.&lt;/p&gt;

&lt;p&gt;The latter is a common headache and we've seen companies struggle. With Nx we're moving into the direction of becoming your e2e solution for monorepos, where we don't just cover your local dev experience, but also provide robust and scalable solutions on CI.&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%2Fsnk6hlu5btscrx4052hz.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%2Fsnk6hlu5btscrx4052hz.png" alt="Effortless, Fast CI" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're super excited to have launched "Nx Agents" to Early Access. If you haven't seen Victor's video yet about how he reduced e2e tests from 90 minutes to 10, then make sure &lt;a href="https://nx.dev/ci/features/nx-agents"&gt;to check it out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Nx Agents"&lt;/strong&gt; are the next iteration of DTE, providing a more flexible, cost effective and more performant approach to distribution on CI. This includes things like being able to dynamically allocate machines based on the size of the PR and flaky task detection and re-running. Also, it can be configured with a single line:&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="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;Start CI run&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npx&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;nx-cloud&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;start-ci-run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--distributes-on="8&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;linux-medium-js"'&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run Nx Agents on any CI provider. If you're curious, &lt;a href="https://go.nx.dev/nx-agents-ea"&gt;sign up for early access&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  New Canary Releases&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We've added a new npm release tag: canary!&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%2Ftep342gapxheetlbye5m.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%2Ftep342gapxheetlbye5m.png" alt="New NPM Release Tag: Canary" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This canary release is created via a &lt;a href="https://github.com/nrwl/nx/blob/master/.github/workflows/publish.yml#L5C61-L5C61"&gt;cron job&lt;/a&gt; that will regularly publish the current contents of the master branch of Nx.&lt;/p&gt;

&lt;p&gt;You can give the canary version a try new for a new workspace using the command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This should be useful for previewing new not-yet released features!&lt;/p&gt;

&lt;h2&gt;
  
  
  Upcoming Release Livestream&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

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

&lt;p&gt;We're going live in January with the Nx team to go over these updates as well! Be sure to click the link to get notified when we go live! And feel free to come with your questions in the chat!&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatically Update Nx&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Updating Nx and its plugins is easy as we ship an &lt;a href="https://nx.dev/core-features/automate-updating-dependencies"&gt;automated migration command&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 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;
  
  
  Wrapping up&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;That’s all for now folks! We’re just starting up a new iteration of development on Nx, so be sure to subscribe to our &lt;a href="https://www.youtube.com/@nxdevtools"&gt;YouTube channel&lt;/a&gt; to get updates when new features land! Until next time, KEEP WORKING HARD!&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn more
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nx.dev/community"&gt;Nx Official Discord Server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  More Nx Release Notes:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-17-0-has-landed-1dad19176ff3"&gt;Nx 17&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-16-8-release-e38e3bb503b5"&gt;Nx 16.8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-16-5-release-7887a27cb5"&gt;Nx 16.5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-16-is-here-69584ec87053"&gt;Nx 16.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook-aa2b8585772e"&gt;Nx 15.8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-7-node-support-angular-lts-lockfile-pruning-46f067090711"&gt;Nx 15.7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more-77cbf6c9a711"&gt;Nx 15.4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-3-standalone-projects-vite-task-graph-and-more-3ed23f7827ed"&gt;Nx 15.3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nx</category>
      <category>javascript</category>
      <category>npm</category>
      <category>rust</category>
    </item>
    <item>
      <title>Nx 17.0 Has Landed!!!</title>
      <dc:creator>Zack DeRose</dc:creator>
      <pubDate>Tue, 24 Oct 2023 14:46:00 +0000</pubDate>
      <link>https://dev.to/nx/nx-170-has-landed-p60</link>
      <guid>https://dev.to/nx/nx-170-has-landed-p60</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1Z0iA9K1o8M"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We're excited to announce the release of Nx version 17!&lt;/p&gt;

&lt;p&gt;In this article, we'll cover the main things you need to know to get the most of Nx 17!&lt;/p&gt;

&lt;p&gt;Here's a Table of Contents so you can skip straight to the updates you care about the most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a Vue-tiful Day for Nx&lt;/li&gt;
&lt;li&gt;Enhancements to Module Federation Support&lt;/li&gt;
&lt;li&gt;More Consistent Generator Paths&lt;/li&gt;
&lt;li&gt;The NEW Nx AI Chatbot&lt;/li&gt;
&lt;li&gt;More Seamless Integration With Nx Cloud&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx.json&lt;/code&gt; Simplification&lt;/li&gt;
&lt;li&gt;Nx Repo Begins Dog-Fooding Nx Workflows&lt;/li&gt;
&lt;li&gt;Task Graphing Improvements&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@nx/linter&lt;/code&gt; Renamed to &lt;code&gt;@nx/eslint&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;New Experimental Feature: Nx Release&lt;/li&gt;
&lt;li&gt;Experimental: Nx Project Inference API v2&lt;/li&gt;
&lt;li&gt;20k Github Stars!!&lt;/li&gt;
&lt;li&gt;How to Update Nx&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  It's a Vue-tiful Day for Nx! &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Ever since we added Vite a first-class citizen to Nx workspaces (see &lt;code&gt;@nx/vite&lt;/code&gt;) we started falling in love with the Vue commmunity. The only logical next step: Nx now provides a brand new Vue plugin that is being maintained by the Nx team! (And we're already working on a &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt; plugin 🤫)&lt;/p&gt;

&lt;p&gt;The first place you might notice this new support 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/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrt53f1l4ebxsmnm5huq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Frrt53f1l4ebxsmnm5huq.png" alt="Vue in create-nx-workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selecting this option will create a brand new Nx workspace with a fresh new Vue application, all setup and ready to develop! To add new Vue projects to your existing Nx workspaces, just add our new &lt;code&gt;@nx/vue&lt;/code&gt; package as a dev dependency to your workspace, e.g.:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And you'll have access to Nx generators so that you can generate Vue applications, libraries, components, and more in your workspace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fl5v7m6p11ynhqssy4r2g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fl5v7m6p11ynhqssy4r2g.gif" alt="Accessing @nx/vue generators via Nx Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're very excited for this support to land and we're eager to get it into our user's hands and see what Nx can do to help Vue developers so we can continue to refine our support and make Vue with Nx an excellent developer experience.&lt;/p&gt;

&lt;p&gt;If you're eager to learn more, make sure to &lt;a href="https://nx.dev/getting-started/tutorials/vue-standalone-tutorial" rel="noopener noreferrer"&gt;check out our new Vue standalone tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhancements to Module Federation Support &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Nx already had really great support for Module Federation - Nx 17 improves on this support:&lt;/p&gt;

&lt;h3&gt;
  
  
  NEW: Typesafe Config
&lt;/h3&gt;

&lt;p&gt;Projects created with Nx's generators for module federation will now be created with a &lt;code&gt;module-federation.config.ts&lt;/code&gt; file (as opposed to a &lt;code&gt;.js&lt;/code&gt; file). A new &lt;code&gt;ModuleFederationConfig&lt;/code&gt; interface is now exported from the &lt;code&gt;@nx/webpack&lt;/code&gt; plugin as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Typesafety Across Modules
&lt;/h3&gt;

&lt;p&gt;Nx 17 improves typesafety across modules now so that proper typesafety is now supported across dynamic imports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FcUWkV4U.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FcUWkV4U.gif" alt="Federated Typesafety"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NEW GENERATOR: Federate ANYTHING.
&lt;/h3&gt;

&lt;p&gt;Both the &lt;code&gt;@nx/react&lt;/code&gt; and &lt;code&gt;@nx/angular&lt;/code&gt; now include a &lt;code&gt;federate-module&lt;/code&gt; generator. This will allow you to create a federated module out of any Nx project.&lt;/p&gt;

&lt;p&gt;To run this generator, use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; nx g federate-module &amp;lt;project name&amp;gt; --path=&amp;lt;path to module to be exposed&amp;gt; --remote=&amp;lt;name of remote exposing module&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new project that exposes the targeted project as a federated module.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Module Versions
&lt;/h3&gt;

&lt;p&gt;Nx now supports targeted versioning for federated modules.&lt;/p&gt;

&lt;p&gt;To create versions for a given project, you can use the &lt;code&gt;version&lt;/code&gt; property of that project's &lt;code&gt;package.json&lt;/code&gt; file, and then &lt;code&gt;build&lt;/code&gt; that project create the version locally.&lt;/p&gt;

&lt;p&gt;Then when consuming this library, you can use the &lt;code&gt;shared&lt;/code&gt; method of the &lt;code&gt;ModuleFederationConfig&lt;/code&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;ModuleFederationConfig&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/webpack&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModuleFederationConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-remote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;exposes&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;./Module&lt;/span&gt;&lt;span class="dl"&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;apps/my-remote/src/app/remote-entry/entry.module.ts&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;remotes&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;federated-is-odd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;libName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;configuration&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;libName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-odd&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;singleton&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;strictVersion&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;requiredVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.1&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;configuration&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config will make sure that version &lt;code&gt;0.0.1&lt;/code&gt; of the &lt;code&gt;is-odd&lt;/code&gt; is used.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Consistent Generator Paths &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://youtu.be/bw8pRh0iC4A?si=lLRSSHmQ0V7agGo8&amp;amp;t=14" rel="noopener noreferrer"&gt;Similar to the adjustments we made in 16.8&lt;/a&gt; for most of our project-creating generators, v17 brings updates to how component generators work. The goal of these updates is to give you more control over the name and file location of your components.&lt;/p&gt;

&lt;p&gt;Towards this end, we've added a new &lt;code&gt;--nameAndDirectoryFormat&lt;/code&gt; option, that you can set to either &lt;code&gt;as-provided&lt;/code&gt; or &lt;code&gt;derived&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When set to &lt;code&gt;as-provided&lt;/code&gt;, the generator will use the &lt;code&gt;name&lt;/code&gt; option for the name of your component, and the &lt;code&gt;directory&lt;/code&gt; option to determine where on your file system to add the component. &lt;code&gt;as-provided&lt;/code&gt; will be used by default if none is specified.&lt;/p&gt;

&lt;p&gt;When set to &lt;code&gt;derived&lt;/code&gt;, the generator will try to determine where to create your component based on the &lt;code&gt;project&lt;/code&gt; option - which will mostly operate how component generators do now.&lt;/p&gt;

&lt;p&gt;In addition, component generators now follow any given casing for component files. For example, let's say that we have an integrated monorepo with a react application called "my-app", and we want to add a "Home" component. With Nx 17, you can run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; nx g component Home &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;apps/my-app/src/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a &lt;code&gt;Home.tsx&lt;/code&gt; file will be added in the &lt;code&gt;apps/my-app/src/app&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;You can now also build your directory path right into generator command. For example, the same "Home" component would be created via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; nx g component apps/my-app/src/app/Home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, generators will now factory in your current working directory, so you can also create this "Home" component via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;apps/my-app/src/app
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; nx g component Home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The NEW Nx AI ChatBot &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We've added a new AI ChatBot to our docs site. You can access it now at &lt;a href="https://nx.dev/ai-chat" rel="noopener noreferrer"&gt;https://nx.dev/ai-chat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FdQMiJSo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FdQMiJSo.gif" alt="Demonstrating the Nx Ai Chatbot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature is still in beta, so please use the thumbs up/thumbs down buttons to provide feedback on whether the chat bot is accurate and helpful!&lt;/p&gt;

&lt;h2&gt;
  
  
  More Seamless Integration With Nx Cloud &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After running the &lt;code&gt;nx migrate&lt;/code&gt; command to upgrade to Nx 17 and using Nx Cloud, you may have observed the removal of &lt;code&gt;nx-cloud&lt;/code&gt; from your dev dependencies. Don't worry - Nx Cloud is not only still around but thriving. Instead of having a standalone package, we've integrated the Nx Cloud communication layer directly into the &lt;code&gt;nx&lt;/code&gt; package. This ensures a seamless connection whenever you opt-in and eliminates potential version misalignment concerns with our API endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;nx.json&lt;/code&gt; Simplification &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Our Nx Cloud updates come alongside some other configuration changes in your &lt;code&gt;nx.json&lt;/code&gt; file and project configuration as well.&lt;/p&gt;

&lt;p&gt;Specifically, we've added an optional &lt;code&gt;nxCloudAccessToken&lt;/code&gt; to the &lt;code&gt;nx.json&lt;/code&gt; file - as long as a token is provided here, we'll make sure that you take advantage of the currently deployed version of Nx Cloud when running commands with Nx.&lt;/p&gt;

&lt;p&gt;We've also removed the need to specify &lt;code&gt;cacheableOperations&lt;/code&gt; at the task-runner level. From now on, every &lt;code&gt;target&lt;/code&gt; configured in your &lt;code&gt;project.json&lt;/code&gt; can be specified as cacheable using the &lt;code&gt;cache&lt;/code&gt; property.&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="nl"&gt;"targetDefaults"&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;"cache"&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="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;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 used the &lt;code&gt;nx migrate&lt;/code&gt; command, all updates will be handled for you, using the &lt;code&gt;targetDefaults&lt;/code&gt; in your &lt;code&gt;nx.json&lt;/code&gt; file. More &lt;a href="https://nx.dev/core-features/cache-task-results" rel="noopener noreferrer"&gt;on the docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In general, we've been working hard at reducing and simplifying all the configuration that is required for your Nx workspaces. Checkout our latest guide on how to &lt;a href="https://nx.dev/recipes/running-tasks/reduce-repetitive-configuration" rel="noopener noreferrer"&gt;Reduce Repetitive Configuration&lt;/a&gt; for more, and stay tuned as we've got new efforts underway to make this simplification even more appealing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Repo Dog-Fooding Nx Workflows &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;At Nx Conf in New York City, we unvieled the next big step for Nx: &lt;strong&gt;Nx Workflows&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you missed it, Simon Critchley walks you through &lt;a href="https://dev.to/nx/nx-conf-2023-recap-53ep"&gt;in his Nx Conf talk&lt;/a&gt;:&lt;/p&gt;

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

&lt;p&gt;Put simply, Nx Workflows represents Nx entering the CI provider arena, where Nx can now provide you with Cloud Computation to run your CI tasks. This creates the foundation for a whole new class of Nx Cloud features that we're very excited to be working on in the coming cycles. &lt;/p&gt;

&lt;p&gt;The Nx repo itself is now "dog-fooding" this latest feature (dog-fooding refers to using our tool in our own projects, or "eating our own dog food"), and you can &lt;a href="https://staging.nx.app/orgs/62d013d4d26f260059f7765e/workspaces/62d013ea0852fe0a2df74438/overview" rel="noopener noreferrer"&gt;see how it's going now on our public Nx Cloud workspace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://staging.nx.app/orgs/62d013d4d26f260059f7765e/workspaces/62d013ea0852fe0a2df74438/overview" rel="noopener noreferrer"&gt;&lt;img src="https://media.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%2Fbb8gtivmfhm63rk6kr1e.png" alt="Public Nx Workflows For Nx Repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nx Workflows are still in the experimental phase, we're running pilots with our enterprise clients and we're excited to open this up for everyone soon!&lt;/p&gt;

&lt;h2&gt;
  
  
  Task Graphing Improvements &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Task Caching in Nx is based on a set of "input" files that are calculated for a given task. You can specify certain files or patterns of files in your &lt;code&gt;project.json&lt;/code&gt; for a specific task or in the &lt;code&gt;targetDefaults&lt;/code&gt; of your &lt;code&gt;nx.json&lt;/code&gt; to set the default file sets for your inputs.&lt;/p&gt;

&lt;p&gt;In the past, there's been some difficulties in determining specifically which files were included and which weren't for a given task. This is where our latest update to the task graph comes in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBygrZ7VG6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FBygrZ7VG6.png" alt="Task Graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can open this graph using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; nx graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then selecting "Task" from the "Project"/"Task" graph dropdown in the top left. Clicking on a specific task now allows you to see a comprehensive list of all files that were factored in as inputs for this task:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHyeH-XVf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackmd.io%2F_uploads%2FHyeH-XVf6.png" alt="Task Graph with Inputs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;@nx/linter&lt;/code&gt; Renamed to &lt;code&gt;@nx/eslint&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After running &lt;code&gt;nx migrate&lt;/code&gt;, you may have noticed that the &lt;code&gt;@nx/linter&lt;/code&gt; plugin was removed and replaced with &lt;a href="https://nx.dev/nx-api/eslint" rel="noopener noreferrer"&gt;&lt;code&gt;@nx/eslint&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Nx 17, we removed any remaining traces of &lt;code&gt;tslint&lt;/code&gt; from our linter package, so this is mainly a simple rename to more accurately describe the package (and to remove any confusion that this package is intended to support linting for other languages/platforms).&lt;/p&gt;

&lt;h2&gt;
  
  
  New Experimental Feature: Nx Release &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;nx release&lt;/code&gt; is a new top level command on the Nx CLI which is designed to help you with versioning, changelog generation, and publishing of your projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx release version&lt;/code&gt; - Determine and apply version updates to projects and their dependents&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx release changelog&lt;/code&gt; - Generate CHANGELOG.md files and optional Github releases based on git commits&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx release publish&lt;/code&gt; - Take the freshly versioned projects and publish them to a remote registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;nx release&lt;/code&gt; is still experiment and therefore subject to change, but the Nx repo itself is now using these commands to version itself, as well as generate changelogs, &lt;a href="https://github.com/nrwl/nx/releases" rel="noopener noreferrer"&gt;Github releases&lt;/a&gt;, and publish our packages to npm.&lt;/p&gt;

&lt;p&gt;As we solidify this command, we intend to bring robust support for various versioning and publishing strategies, as well as built-in support for publishing packages or modules to a variety of languages, registries, and platforms.&lt;/p&gt;

&lt;p&gt;For more &lt;a href="https://nx.dev/nx-api/nx/documents/release" rel="noopener noreferrer"&gt;checkout our API docs&lt;/a&gt;, and be sure to catch James Henry's announcement of this new command at &lt;a href="https://dev.to/nx/nx-conf-2023-recap-53ep"&gt;Nx Conf&lt;/a&gt;:&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;h2&gt;
  
  
  Experimental: Nx Project Inference API v2 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;At Nx, we're OBSESSED with building a better, more robust experience for our developers. Towards this end, we're now in &lt;a href="https://nx.dev/extending-nx/recipes/project-graph-plugins" rel="noopener noreferrer"&gt;v2 of our Project Inference API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This API is a way of extending the Nx project graph, which can be particularly helpful for extending Nx to support other languages, allowing Nx to determine where to find and draw boundaries around projects in your workspace. A great example is our very own &lt;a href="https://nx.dev/getting-started/tutorials/vue-standalone-tutorial" rel="noopener noreferrer"&gt;Vue plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Interestingly, v2 includes support for dynamic targets as well. This opens up exciting new doors to reducing configuration, and we hope to expand on this to better support our first-party plugins in the near future.&lt;/p&gt;

&lt;p&gt;For most developers, the main thing you need to know is that plugins may now add additional targets that you won't see in your &lt;code&gt;project.json&lt;/code&gt; file. To see your actual project configuration, you can now use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nx show project &amp;lt;project_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For plugin authors, check out the &lt;a href="https://nx.dev/extending-nx/recipes/project-graph-plugins" rel="noopener noreferrer"&gt;v2 documentation&lt;/a&gt; to see how you can take advantage of the new API to deliver a better experience to your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  20k Github Stars!! &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Nx is SOOO CLOSE to 20,000 stars on github! If Nx has been helpful to you, &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;please help us get there!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;&lt;img src="https://media.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%2Fl2lw01qq7sow5thbarn5.png" alt="Star us on Github!"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Nx is known to &lt;a href="https://nx.dev/core-features/automate-updating-dependencies" rel="noopener noreferrer"&gt;help you automatically migrate&lt;/a&gt; to the new version (including potentially breaking changes). To update simply 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 migrate latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will update your Nx workspace dependencies, configuration and code to the latest version. 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;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;That’s all for now folks! We’re just starting up a new iteration of development on Nx, so be sure to subscribe to our &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt; to get updates when new features land! Until next time, KEEP WORKING HARD!&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn more
&lt;/h3&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.nx.dev/community" rel="noopener noreferrer"&gt;Nx Official Discord Server&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;h3&gt;
  
  
  More Nx Release Notes:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-16-8-release-e38e3bb503b5" rel="noopener noreferrer"&gt;Nx 16.8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-16-5-release-7887a27cb5" rel="noopener noreferrer"&gt;Nx 16.5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-16-is-here-69584ec87053" rel="noopener noreferrer"&gt;Nx 16.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook-aa2b8585772e" rel="noopener noreferrer"&gt;Nx 15.8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&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;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more-77cbf6c9a711" rel="noopener noreferrer"&gt;Nx 15.4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/nx-15-3-standalone-projects-vite-task-graph-and-more-3ed23f7827ed" rel="noopener noreferrer"&gt;Nx 15.3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>nx</category>
      <category>eslint</category>
      <category>chatgpt</category>
    </item>
  </channel>
</rss>
