docs(nx-dev): migrate blog posts from 2023+ (#27946)

Migrating in blog posts from Medium and dev.to from 2023 onwards, along with any other post linked to from them
This commit is contained in:
Philip Fulcher 2024-10-03 09:37:07 -06:00 committed by GitHub
parent e3a304babf
commit a0a5740179
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
402 changed files with 12347 additions and 97 deletions

View File

@ -87,6 +87,7 @@ jobs:
NX_CI_EXECUTION_ENV: 'linux' NX_CI_EXECUTION_ENV: 'linux'
NX_CLOUD_DTE_V2: 'true' NX_CLOUD_DTE_V2: 'true'
NX_CLOUD_DTE_SUMMARY: 'true' NX_CLOUD_DTE_SUMMARY: 'true'
NX_CLOUD_NO_TIMEOUTS: 'true'
steps: steps:
- checkout - checkout
- nx/set-shas: - nx/set-shas:

View File

@ -0,0 +1,329 @@
---
title: 'Taming Code Organization with Module Boundaries in Nx'
slug: 'mastering-the-project-boundaries-in-nx'
authors: ['Miroslav Jonaš']
cover_image: '/blog/images/2021-12-17/1*PIUl1QGk7mOpSFdEwFQ8OA.png'
tags: [nx]
---
As your repository grows, it becomes more challenging to organize and name the applications and libraries. This organization, when done right, feels intuitive and allows team members to easily find projects and understand how they work together. When done poorly, it results in a mess we eventually end up calling “the legacy software”. This article will show you different ways how you can prevent your repo from descending into chaos.
Our book [Enterprise Angular Monorepo Patterns](https://go.nx.dev/angular-enterprise-monorepo-patterns-new-book) presents an in-depth guide to assist you with naming and organization. If you still havent read this book, we warmly recommend you do. Dont let the name fool you, though — the architecture guidelines explained in this book apply to any framework.
On large projects, you will most likely find multiple teams working on different parts of the solution. Those projects are usually split into logical domains, where each team focuses on a single domain. Each domain block can have a clear public API which other domains can use to consume the information.
But the code organization is just one piece of the puzzle. The physical organization does not prevent developers from consuming the domains or parts of those domains, that should otherwise be outside of their reach. Nx ships with `enforce-module-boundaries` ESLint rule that helps restrict that possibility.
## Understanding the default configuration
When you generate the first project in your workspace using one of our generators, one of the things you get for free is the full linter setup. The linter is preconfigured with a default ruleset that includes a set of best practices. Alongside the standard set of rules, the initial generated configuration includes a setup for `enforce-module-boundaries` rule.
```json5 {% fileName=".eslintrc.json" %}
{
// ... default ESLint config here
overrides: [
{
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
rules: {
'@nrwl/nx/enforce-module-boundaries': [
'error',
{
allow: [],
depConstraints: [
{
sourceTag: '*',
onlyDependOnLibsWithTags: ['*'],
},
],
enforceBuildableLibDependency: true,
},
],
},
},
// ... more ESLint overrides here
],
}
```
Lets dissect what each of these properties does.
The `allow` array acts as a whitelist listing the import definitions that should be omitted from further checks. You can read more about it in the **Overriding the overrides** section below.
The `depConstraints` section is the one you will be spending most time fine-tuning. It represents an array of constraints, each consisting of `sourceTag` and `onlyDependOnLibsWithTags` properties. The default configuration has a wildcard `*` set as a value for both of them, meaning that any project can import (depend on) any other project.
> Note, the wildcard only applies to libraries. Applications and E2E applications cannot be imported. It wouldnt make any sense. If you want to combine applications, you should use the [micro-frontends](/recipes/angular/dynamic-module-federation-with-angular) approach with the module federation.
The circular dependency chains such as `lib A -> lib B -> lib C -> lib A` are also not allowed. The self circular dependency (when lib imports from a named alias of itself), while not recommended, can be overridden by setting the flag `allowCircularSelfDependency` to true.
```json5 {% fileName=".eslintrc.json" %}
// ... more ESLint config here
"@nrwl/nx/enforce-module-boundaries": [
"error",
{
"allowCircularSelfDependency": true,
"depConstraints": [
// ...list of constraints
]
}
]
// ... more ESLint config here
```
Finally, the flag `enforceBuildableLibDependency` prevents us from importing a non-buildable library into a buildable one. You can read more on what buildable libraries are used for in [our docs](/concepts/buildable-and-publishable-libraries).
## Using tags to enforce boundaries
To best express the need for the boundaries and assist us through the explanation, we will be using the repository represented by the following graph:
![](/blog/images/2021-12-17/1*z3ap5kyCXG4p8bcBQXx9tA.avif)
_The graph representation of the repository_
Our repository consists of two applications — Store and Admin. Each of them is composed of several feature libraries — Products (for Store), Sales, and Invoices (for Admin). Also, both of these applications depend on the Core library, and every project in our repo depends on our Shared library. Using common sense, we would like to enforce certain boundaries:
- A shared or core library should not be able to depend on a feature library
- A feature library can depend on another feature library or a shared library
First, we will use the project configuration to annotate our projects with `tags`.
- Tags used to live in `nx.json` but were in the recent version moved closer to the project, so you can locate them now in your `project.json` or `workspace.json`
Lets define the types of projects. We will use the following tags:
- `type:app` for application
- `type:feature` for feature library
- `type:util` for utility library
Your changed project configuration should now have the tags section defined.
```json5 {% fileName="project.json" %}
{
// ... more project configuration here
tags: ['type:app'],
}
```
Your enhanced graph will now look similar to this:
![](/blog/images/2021-12-17/1*kTiRazA4qhZ7kD-lGgGyjg.avif)
_Graph with type tags set_
The above list of library types is not complete. You might add specific ones for E2E projects or UI component libraries. Using the naming format `type:*` is just a suggestion. Consider this being a hashtag on your favorite social app. You can use any prefix or format you feel fitting. The important thing is that it's readable and intuitive to all the members of your team.
Now, that we have marked all of our projects, we can continue to define the rules in the root `.eslintrc.json.`
```json5 {% fileName=".eslintrc.json" %}
{
// ... more ESLint config here
'@nrwl/nx/enforce-module-boundaries': [
'error',
{
// update depConstraints based on your tags
depConstraints: [
{
sourceTag: 'type:app',
onlyDependOnLibsWithTags: ['type:feature', 'type:util'],
},
{
sourceTag: 'type:feature',
onlyDependOnLibsWithTags: ['type:feature', 'type:util'],
},
{
sourceTag: 'type:util',
onlyDependOnLibsWithTags: ['type:util'],
},
],
},
],
// ... more ESLint config here
}
```
## Adding a second dimension
We said that a feature library can depend on any other feature library, but there is a small catch. Our two apps could be built with a different framework so mixing feature libraries would not be possible. To avoid any future impediments, we dont want to allow a feature library used in `Store` to depend on the feature library from `Admin` and vice versa. Additionally, only our apps should be able to load the `Core` library.
![](/blog/images/2021-12-17/1*mr_MbGgWVbBcfBhss0hNqA.avif)
_Project graph with type tags and technology badges_
Lets add another dimension to allow such restrictions. We will define the necessary scope tags:
- `scope:store` for store app-related projects
- `scope:admin` for admin app related projects
- `scope:shared` for shared projects
- `scope:core` for core projects
Our diagram should now look like this:
![](/blog/images/2021-12-17/1*KeO1ZnEkUtmS2uj8M2rqKA.avif)
_Full project graph with two-dimensional tags_
Let us now define our missing rules!
```json5 {% fileName=".eslintrc.json" %}
{
// ... more ESLint config here
'@nrwl/nx/enforce-module-boundaries': [
'error',
{
// update depConstraints based on your tags
depConstraints: [
// ...previous project type related rules
{
sourceTag: 'scope:store',
onlyDependOnLibsWithTags: [
'scope:store',
'scope:shared',
'scope:core',
],
},
{
sourceTag: 'scope:admin',
onlyDependOnLibsWithTags: [
'scope:admin',
'scope:shared',
'scope:core',
],
},
{
sourceTag: 'scope:core',
onlyDependOnLibsWithTags: ['scope:shared'],
},
{
sourceTag: 'scope:shared',
onlyDependOnLibsWithTags: ['scope:shared'],
},
],
},
],
// ... more ESLint config here
}
```
## Fine-grained external dependencies
You may want to constrain what external packages a project may import. In our example above, we want to make sure projects in the `scope:store` does not import any angular packages, and projects from the `scope:admin` do not import any react library. You can ban these imports using `bannedExternalImports` property in your dependency constraints configuration.
We can now enhance our rule configuration by providing additional information.
```json5 {% fileName=".eslintrc.json" %}
{
// ... more ESLint config here
'@nrwl/nx/enforce-module-boundaries': [
'error',
{
// update depConstraints based on your tags
depConstraints: [
// ...previous project type related rules
{
sourceTag: 'scope:store',
onlyDependOnLibsWithTags: [
'scope:store',
'scope:shared',
'scope:core',
],
// this covers all @angular pacakges
bannedExternalImports: ['@angular/*'],
},
{
sourceTag: 'scope:admin',
onlyDependOnLibsWithTags: [
'scope:admin',
'scope:shared',
'scope:core',
],
// this covers react, but also react-router-dom or react-helmet
bannedExternalImports: ['react*'],
},
{
sourceTag: 'scope:core',
onlyDependOnLibsWithTags: ['scope:shared'],
bannedExternalImports: ['@angular/*', 'react*'],
},
{
sourceTag: 'scope:shared',
onlyDependOnLibsWithTags: ['scope:shared'],
bannedExternalImports: ['@angular/*', 'react*'],
},
],
},
],
// ... more ESLint config here
}
```
Using the wildcard `*` to match multiple projects e.g. `react*` we can save ourselves the effort of manually specifying every single project we want to ban.
## Restricting transitive dependencies
Our solution doesnt contain only internal projects but also depends on various external NPM packages. These external dependencies are explicitly declared in our `package.json`. Unfortunately, a package is rarely an island. They often consist of a tree of transitive dependencies branching out leading to thousands of packages being installed in your `node_modules` folder. Although we have control over what version or which direct dependency we install, we have no control over what versions of what packages this dependency depends on. The transitive dependencies are often the source of our app's vulnerabilities. We can also never guarantee those dependencies will be there. Just by simply running `npm install` parent may get updated to a patch or minor version that would wipe out one of the transitive dependencies or replace it with one with breaking changes.
Therefore its wise not to allow developers to import transitive dependencies in their projects. Our ESLint plugin provides a simple flag to turn this restriction on.
```json5 {% fileName=".eslintrc.json" %}
{
// ... more ESLint config here
'@nrwl/nx/enforce-module-boundaries': [
'error',
{
// ... more rule config here
banTransitiveDependencies: true,
},
],
// ... more ESLint config here
}
```
If you now try to import a transitive dependency, your linter responds with an error. This flag is disabled by default for now, but we highly recommend you enable it.
## Overriding the overrides
Sometimes, we just need to override this configuration for a given project. The scenario for this might be testing or during the development, if we are unsure yet how a certain project will be tagged. While we strongly encourage you to plan your architecture carefully and never override the boundaries configuration, you still have an option to bale out and override it.
```json5 {% fileName=".eslintrc.json" %}
{
// ... default ESLint config here
overrides: [
{
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
rules: {
'@nrwl/nx/enforce-module-boundaries': [
'error',
{
// ignore any checks for these projects for now
allow: ['a-wip-project', 'this-one-is-broken-so-ignore-it'],
depConstraints: [
// ...dependency constraints here
],
},
],
},
},
// ... more ESLint overrides here
],
}
```
## Summary
Monorepos are often viewed only from the technical side, but they also bring a shift in human resources organization. Teams that were once isolated, now have to work together on the same solution.
Having a clean separation of concerns and well-defined cohesive units helps us scale our organization more easily and gives us more confidence in our architecture. not only does Nx provide tools to speed up the overall performance, but it provides tooling to enforce the organizational constraints in an automated way.
In this post, we listed several strategies which you can use to restrict your packages from being misused or use unplanned external resources. Use them thoroughly and on time, before things go out of hand.
> Prefer a visual presentation over text? Then check out this talk recording by Juri Strumpflohner: [https://www.youtube.com/watch?v=pER_Ak1yUaA&t=687s](https://www.youtube.com/watch?v=pER_Ak1yUaA&t=687s)

View File

@ -0,0 +1,97 @@
---
title: 'Single File Monorepo Config, Custom Workspace Presets, Improved Tailwind Support, and more in Nx 13.4!'
slug: 'single-file-monorepo-config-custom-workspace-presets-improved-tailwind-support-and-more-in-nx-13'
authors: ['Brandon Roberts']
cover_image: '/blog/images/2021-12-23/1*_4u3Fw49H5U-sqgyBoGsqw.png'
tags: [nx, release]
---
Nx is a smart, extensible build framework to help you architect, test, and build at any scale — integrating seamlessly with modern technologies and libraries while providing a robust CLI, computation caching, dependency management, and more.
## One Million Weekly Downloads 🎉
Nx reached a major milestone this week of one million weekly downloads. Nx has been working to push monorepos forward for a long time, and this milestone is a reflection of work between us and the Nx community to grow and expand in this space.
![](/blog/images/2021-12-23/1*WC4RQRZhTtOCsiATOL1cBg.avif)
_One million weekly downloads_
## Single File Monorepo Configuration ☝️
When operating with a monorepo, some level of configuration is needed to provide context about the tools and structure for inferring information about projects. Nx has traditionally done this with 2 files, the **nx.json** that contains global configuration for the Nx CLI, and the **workspace.json** that contains references to projects within your workspace.
With the latest release of Nx and add-nx-to-monorepo 2.0, there is only the **nx.json** configuration file added to your existing monorepo, with the project information done through analyzing your workspace for existing projects. This allows you to **incrementally adopt** Nx into your monorepo to run tasks, cache computations, and more.
```shell
npx add-nx-to-monorepo
```
> Victor Savkin demoed the flexibility of Nx by migrating Metas (Facebook) React repository: [video link](https://youtu.be/XLP2RAOwfLQ)
Learn more in our guide of [adding Nx to an existing workspace](/recipes/adopting-nx/adding-to-monorepo) and the config inside the [**nx.json**](/reference/project-configuration)**.**
## Custom Workspace Presets 🎨
Nx provides many presets by default to support many different ecosystems. Nx for monorepos is like VSCode, where plugins allow you to extend the functionality of your monorepo to fit your ecosystem or platform of choice. To make it easier for scaffolding a pre-defined setup, weve introduced the ability to use custom presets when creating Nx workspaces with a provided npm package.
```shell
npx create-nx-workspace --preset=your-npm-package-name
```
Nicholas Cunningham just joined Nrwl and already implemented this new Nx feature! In the following video, [Juri Strumpflohner](https://twitter.com/juristr) walks you through the process of creating a new Nx Plugin with a custom preset.
{% youtube src="https://www.youtube.com/watch?v=yGUrF0-uqaU" /%}
This allows you to enhance the initial experience for new workspaces directly for your organization, and allows the Nx Plugin community to offer more tailored experiences. Please try out the new feature and [let us know](https://github.com/nrwl/nx) how we can improve it!
## Dedicated TypeScript and JavaScript support with @nrwl/js
Nx has always shipped with great TypeScript support. In version 13.4 we improve it even further by releasing a brand new package: `@nrwl/js` .
This is particularly useful if you have framework-agnostic TS/JS packages within an existing Nx workspace but also for those scenarios where you want to build and publish a TS/JS-based library to some package registry. The setup is very lightweight, but still provides all benefits youd expect from an Nx-based setup such as Jest, ESLint, Prettier etc.
Read all the details on [our new TypeScript guide](/getting-started/intro) or check out the video walkthrough below.
{% youtube src="https://www.youtube.com/watch?v=-OmQ-PaSY5M" /%}
## Improved Tailwind support for Angular 💅
![](/blog/images/2021-12-23/0*1yacozydc1muZ74G.avif)
_Tailwind Logo_
Tailwind is a utility-first CSS framework packed with classes that can be composed to build any design, directly in your markup. If youve used Tailwind with Angular applications previously, it's supported out of the box with Nx. Were continually looking to improve the developer experience of using Tailwind in Angular applications and libraries. We already added support to the Angular plugin for Nx, and have added a new generator to configure Tailwind in **existing** apps and buildable/publishable libs, allowing you to set up and configure Tailwind without manual steps. The ability to configure new apps and libs is also supported, with support for Tailwind V2 and the latest V3 release.
```shell
nx g @nrwl/angular:app my-app --addTailwind
```
Read more about Angular and Tailwind in our [docs](/nx-api/angular/generators/setup-tailwind).
### Other Highlights 🗒
- Added SWC support for compiling JavaScript libraries and React apps/libs when building projects
- Added migration support Create React App version 5
- Updated the Angular framework to version 13.1
- Update support for Cypress to version 9
- Added additional SCAM generators for Angular for pipes and directives.
- Improved developer experience for using Module Federation with Angular v13
## How to Update Nx
Updating Nx is done with the following command, and will update your Nx workspace dependencies and code to the latest version:
```shell
nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
nx migrate --run-migrations
```
## Explore More
- Get our [free basic Nx workspaces course on YouTube](https://youtu.be/2mYLe9Kp9VM)!
- Purchase our premium video course on advanced practices for Nx workspaces: [here](https://nxplaybook.com/p/advanced-nx-workspaces)!
Follow us [on Twitter](https://twitter.com/NxDevTools), and subscribe to the [YouTube Channel](https://youtube.com/nrwl_io?sub_confirmation=1) for more information on [Angular](https://angular.io/), [React](https://reactjs.org/), Nx, and more!

View File

@ -0,0 +1,110 @@
---
title: 'New Terminal Output & Performance Improvements in Nx 13.5'
slug: 'new-terminal-output-performance-improvements-in-nx-13-5'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-01-25/1*PIUl1QGk7mOpSFdEwFQ8OA.png'
tags: [nx]
---
Nx is a smart, extensible build framework to help you architect, test, and build at any scale — integrating seamlessly with modern technologies and libraries while providing a robust CLI, computation caching, dependency management, and more.
### New Terminal Output 💅
Folks that have been following along in our journey for quite some time know already that at Nx we strive for the best possible DX. The current terminal output was always something we havent been super happy with, especially if you run some of the commands that trigger the execution of multiple tasks (e.g. affected commands, run-many etc). This is why were even more excited about this feature: the new dynamic Nx terminal output is now the default for everyone.
![](/blog/images/2022-01-25/1*81krRElSXV5w2T54DiCBAA.avif)
_New dynamic terminal output in Nx 13.5_
It clearly separates the terminal output into an upper part where all the completed tasks and their corresponding execution time are listed and a lower part where the currently running tasks show up. Of course, errors are always shown immediately and therefore easy to spot.
There are a few things to note here (and which kinda emphasize our love with details & dev ergonomics 😉)
- **Off in CI —** On CI youll still see the full output.
- **The full terminal output is still cached —** this is purely UI cosmetic. We still cache the entire terminal output. Hence, if you run the build of a single project that has previously been cached as part of a run-many command, you will see still the full output.
Thanks to [James Henry](https://twitter.com/mrjameshenry) for working on this feature!
### Nx keeps getting faster and faster 🚀
Performance is a feature, and we take it seriously with Nx. We landed a number of different performance improvements over the last couple of minor versions, ranging from optimizing how we store & restore our cache to improving the Nx workspace analysis and boot time. With v13.5 weve seen some Nx operations being
- 1.8x — 2.3x faster in the [Interstellar repo](https://github.com/vsavkin/interstellar)
- about 2x faster on some large client repositories
And we will not rest 😉.
### Performance Profiling with Nx 🧐
When running an Nx command there might potentially be many tasks running at different times, in parallel, and using different processes. Optimizing those runs or better understanding where things go wrong might be a hard and cumbersome process. Being able to visualize things usually helps.
Thats why we introduced the ability to profile and visualize Nx commands in the Chrome Devtools.
![](/blog/images/2022-01-25/1*7vk8AUWRGkDI0vcVX4Ql-g.avif)
Use the `NX_PROFILE=<filename>` environment variable attached to your Nx CLI command:
```shell
NX_PROFILE=profile.json nx build cart
```
Itll produce a JSON file which you can then open with Chromes devtools. [Read more about it on the Nx Docs](/troubleshooting/performance-profiling).
Thanks [Jason](https://twitter.com/FrozenPandaz) for working on this feature!
### React Native now supports Environment Variables
Whenever you set up React Native support within an Nx workspace, it should now automatically come with the [react-native-config](https://github.com/luggit/react-native-config) package installed. That allows you to have a `.env` file in the React Native app folder which can then be loaded from within your React Native application.
You can find all the details on the [Nx docs](/recipes/react/react-native).
Thanks [Emily Xiong](https://twitter.com/xiongemily) for implementing this!
### Improvements to the Project Graph Visualization
The project graph is always a nice feature to show off in videos, talks, and blog posts. But if done naively, it just remains that. We always wanted it to be more than that. As your workspace grows, your project graph visualization should become more useful, rather than a mess to look at. This is why we kept adding features for filtering, zooming, highlighting, focusing on specific nodes, incrementally expanding the view by using the proximity feature and more.
In v13.5 we now also store the current filter status in the URL. That makes it easy to pinpoint a certain view and share it with a co-worker. Actually, this could just be the beginning of some more interesting features when we think about CI and visualizations 🤔.
![](/blog/images/2022-01-25/1*RM9hDFIsgLn1X4EX5qsgGg.avif)
_Nx dep graph now stores filters in the URL_
Heres our deployed live example of the above screenshot: [https://nrwl-nx-examples-dep-graph.netlify.app/?focus=products-home-page](https://nrwl-nx-examples-dep-graph.netlify.app/?focus=products-home-page)
Thanks [Philip Fulcher](https://twitter.com/PhilipJFulcher) for adding this feature!
Theres one more thing: As developers, we like to be as efficient as possible. We wanted to help by saving you some keystrokes. The project graph visualization can now be launched with
```shell
nx graph
```
`nx dep-graph` is registered as an alias and will continue to work 🙂.
### New improvements to our Angular plugin
There have been a number of improvements to our Angular plugin ( `@nrwl/angular` ) :
- Option to skip the Angular Module creation when generating new libraries by passing `--skipModule`
- Support for multiple state slices when using the Nx Angular Data Persistence utilities. Thanks [David](https://medium.com/u/6e7f9350fcdf?source=post_page-----c407bb1c963a--------------------------------) for this community contribution !([#8216](https://github.com/nrwl/nx/pull/8216))
- New Angular Nx workspaces now use v2 of the workspace configuration (Nxs format of the `angular.json` )
- Lots of improvements to the Angular SCAM generator
## How to Update Nx
Updating Nx is done with the following command, and will update your Nx workspace dependencies and code to the latest version:
```shell
nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
nx migrate --run-migrations
```
## Explore More
- Get our [free basic Nx workspaces course on YouTube](https://youtu.be/2mYLe9Kp9VM)!
- Purchase our premium video course on advanced practices for Nx workspaces: [here](https://nxplaybook.com/p/advanced-nx-workspaces)!
Follow us [on Twitter](https://twitter.com/NxDevTools), and subscribe to the [YouTube Channel](https://youtube.com/nrwl_io?sub_confirmation=1) for more information on [Angular](https://angular.io/), [React](https://reactjs.org/), Nx, and more!

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,473 @@
---
title: 'Share code between React Web & React Native Mobile with Nx'
slug: 'share-code-between-react-web-react-native-mobile-with-nx'
authors: ['Emily Xiong']
cover_image: '/blog/images/2022-02-01/1*lL-fGNaIGYBC_eOBwSvdBw.png'
tags: [nx, tutorial]
---
**A problem I try to solve:** I got this awesome idea, not only do I want to create a web app, but I also want to create a mobile app for it. Usually creating web and mobile apps require totally different tech stacks, and it is pretty hard to share code. This article shows how I added a React web app and a React Native mobile app in the same monorepo using Nx, and how I optimized codeshare between the two.
I am mostly a web developer, so lets start with the web app first: [https://xiongemi.github.io/studio-ghibli-search-engine](https://xiongemi.github.io/studio-ghibli-search-engine). It is a search engine for movies and characters under Studio Ghibli:
![](/blog/images/2022-02-01/1*TILaEjwvKtDTODE8Zo7wFA.avif)
_Screenshot of web app_
Example Repo: [xiongemi/studio-ghibli-search-engine](https://github.com/xiongemi/studio-ghibli-search-engine)
Github page: [https://xiongemi.github.io/studio-ghibli-search-engine](https://github.com/xiongemi/studio-ghibli-search-engine)
Now lets create the corresponding mobile version of this app.
## Tech Stack
- Monorepo: Nx
- Web Frontend: [React](https://reactjs.org/)
- API: [https://ghibliapi.herokuapp.com/](https://ghibliapi.herokuapp.com/)
Currently, theres only a React web app within our Nx workspace. If I run `nx graph`, the dependency graph looks like the below:
![](/blog/images/2022-02-01/1*AkrRrJ1pbALScj64T8rc_g.avif)
_Dependency graph_
## React Native Setup
To get started we need to add React Native support to our Nx workspace:
```shell
# npm
npm install @nrwl/react-native --save-dev# yarn
yarn add @nrwl/react-native --dev
```
Next, we can generate a new React Native app by running:
```shell
npx nx generate @nrwl/react-native:app studio-ghibli-search-engine-mobile
```
> Note, if youre using VSCode you might want to try [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) for a more visual experience of running such commands.
As a result of running the above command, you should now have two new folders under the `apps` directory: `studio-ghibli-search-engine-mobile` and `studio-ghibli-search-engine-mobile-e2e`
![](/blog/images/2022-02-01/1*pKHufw-OEbTmDRyNcsAd4A.avif)
_studio-ghibli-search-engine-mobile created under apps_
If we now run `nx dep-graph` again, the dependency graph looks like this:
![](/blog/images/2022-02-01/1*UN-VoWFKTqExCCFzQeZkYA.avif)
_Dependency graph_
Note that there is no code shared between `studio-ghibli-search-engine-mobile` and `studio-ghibli-search-engine-web`. However, our goal is to reuse some of the functionality that we have previously written for the web version on our new React native version of the app.
## Code that Could NOT be Shared
Even though our goal is to share as much as possible between our React web app and the React Native app, there are parts that simply cannot be shared.
### UI
We have to rewrite all the UI components for the mobile app. Unlike [Cordova](https://cordova.apache.org/) or [Ionic](https://ionicframework.com/), React Native is NOT a webview. The JavaScript we wrote got interpreted and converted to mobile native elements. Hence we cannot simply reuse UI HTML elements written for the React web app.
Heres a quick list of libraries weve used for the React web app and a corresponding React Native counterpart library we can use.
**Routing**
- [react-router-dom](https://reactrouter.com/docs/en/v6/getting-started/overview) for web
- [@react-navigation/native](https://reactnavigation.org/) for mobile
**Material Design Library**
- [@mui/material](https://mui.com/) for web
- [react-native-paper](https://callstack.github.io/react-native-paper/) for mobile
Besides the above React Native libraries, there are some core utility libraries that need to be installed:
- react-native-reanimated
- react-native-gesture-handler
- react-native-screens
- react-native-safe-area-context
- @react-native-community/masked-view
- react-native-vector-icons
The corresponding install command would be:
```shell
# npm
npm install @react-navigation/native @react-navigation/native-stack react-native-paper react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view --save# yarn
yarn add @react-navigation/native @react-navigation/native-stack react-native-paper react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
```
### Storage
For the React Web app, we use [redux-persist](https://github.com/rt2zz/redux-persist), which persists the redux store in [`localstorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). However, `localstorage` is not supported by React Native.
For the web, the variable `persistConfig` passed to persistStore from redux-persist is:
```typescript
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage: storage,
whitelist: ['search', 'films', 'people'],
transforms: [transformEntityStateToPersist],
};
```
However, for the mobile, we need to install the library [`@react-native-async-storage/async-storage`](https://github.com/react-native-async-storage/async-storage):
```shell
# npm
npm install @react-native-async-storage/async-storage --save-dev# yarn
yarn add @react-native-async-storage/async-storage --dev
```
As a result, the `persistConfig` passed to persistStore from redux-persist becomes:
```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
whitelist: ['search', 'films', 'people'],
transforms: [transformEntityStateToPersist],
};
```
### History
On the React web app, we use [connected-react-router](https://github.com/supasate/connected-react-router) to put the router state into the Redux store. However, the [History API (windows.history)](https://developer.mozilla.org/en-US/docs/Web/API/History_API) is not supported by React Native. As an alternative, we can use `createMemoryHistory`.
For the web app, the history is:
```typescript
import { createHashHistory, History } from 'history';
const history: History = createHashHistory();
```
For the mobile app, the history is:
```typescript
import { createMemoryHistory, History } from 'history';
const history: History = createMemoryHistory();
```
To make our code more re-usable we could slightly refactor the creation of the root reducer with [connected-react-router](https://github.com/supasate/connected-react-router), such that it takes the `history` object as an argument:
```typescript
import { combineReducers } from '@reduxjs/toolkit';
import { connectRouter } from 'connected-react-router';
import { History } from 'history';
import { filmsSlice } from '../films/films.slice';
import { peopleSlice } from '../people/people.slice';
import { searchSlice } from '../search/search.slice';
import { RootState } from './root-state.interface';
export const createRootReducer = (history: History) =>
combineReducers<RootState>({
films: filmsSlice.reducer,
router: connectRouter(history) as any,
search: searchSlice.reducer,
people: peopleSlice.reducer,
});
```
### Query Parameters
When you develop on the web, the easiest way to pass ahead state or information, in general, is to leverage the URL query parameters. In our search app example, we can simply have something like `?search=searchText`.
We can use [react-router-dom](https://v5.reactrouter.com/web/guides/quick-start) to push a new history entry.
```typescript
import { useHistory } from 'react-router-dom';
const history = useHistory();
const submitSearchForm = (text: string) => {
history.push(`${AppRoutes.results}?search=${text}`);
};
```
To read and parse the current query parameter `search`:
```typescript
import { useLocation } from 'react-router-dom';
const params = new URLSearchParams(useLocation().search);
const searchParam = params.get('search');
```
Although the mobile app URLs are not visible, we can still pass parameters. Note that we have to use a different package `@react-navigation/native` though.
```typescript
import { useNavigation } from '@react-navigation/native';
const navigation = useNavigation();
const submitSearchForm = () => {
navigation.navigate(AppRoutes.results, { search: text });
};
```
To read and parse the parameter:
```typescript
import { RouteProp, useRoute } from '@react-navigation/native';
const route = useRoute<RouteProp<{ params: { search: string } }>>();
const searchParam = route.params?.search;
```
To type checking with typescript for react-navigation, we need to create a type `RootStackParamList` for mappings of route name to the params of the route:
```typescript
export type RootStackParamList = {
[AppRoutes.search]: undefined;
[AppRoutes.results]: { search: string };
};
```
We also need to specify a global type for your root navigator:
```typescript
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace ReactNavigation {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface RootParamList extends RootStackParamList {}
}
}
```
So we create the stack navigator, we need to pass the above `RootStackParamList` type:
```typescript
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator<**RootStackParamList**>();
```
### Environment Variables
Nx comes with a set of different options for [handling environment variables](/reference/environment-variables). In our workspace, we have a simple `.env` file at the workspace root:
```text
NX_REQUEST_BASE_URL=://ghibliapi.herokuapp.com
```
This works nicely for our React web build, but it doesnt for our React Native application. This is because React Native and React apps use different Javascript bundlers. React Native uses [Metro](https://facebook.github.io/metro/) and React uses [Webpack](https://webpack.js.org/). Therefore, when we try to access `process.env.NX_REQUEST_BASE_URL`, we get `undefined`.
To solve this, we can use the [react-native-config](https://github.com/luggit/react-native-config) library
```shell
# npm
npm install react-native-config --save-dev# yarn
yarn add react-native-config --dev
```
Heres an example of how to set up [react-native-config](https://github.com/luggit/react-native-config): [https://github.com/luggit/react-native-config#setup](https://github.com/luggit/react-native-config#setup).
After that, we can have a simple utility function to retrieve the environment variables in our app.
```typescript
import Config from 'react-native-config';
export function getEnv(envName: string) {
return process.env[envName] || Config[envName];
}
```
To access the environment variable `NX_REQUEST_BASE_URL`, we can then simply use the above function:`getEnv(NX_REQUEST_BASE_URL)`.
### Fetch With HTTP
On the web, you most probably lean on the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to make network requests. On iOS, however, youll get an error saying: `TypeError: Network request failed`.
It turns out that React Native does not allow HTTP requests by default: [https://stackoverflow.com/questions/38418998/react-native-fetch-network-request-failed](https://stackoverflow.com/questions/38418998/react-native-fetch-network-request-failed).
To fix this, for iOS, open `apps/studio-ghibli-search-engine-mobile/ios/StudioGhibliSearchEngineApp/Info.plist` and add the request URL to `NSExceptionDomains` under `NSAppTransportSecurity`:
```xml
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>ghibliapi.herokuapp.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
```
Similarly, for Android, open `apps/studio-ghibli-search-engine-mobile/android/app/src/main/res/xml/network_security_config.xml`, and add the request URL to this config file:
```xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">herokuapp.com</domain>
</domain-config>
</network-security-config>
```
This should get rid of the network error.
It seems like there are quite a few customizations that need to be done for React Native apps. However, the majority of non-UI code could be reused.
## Code that Could be Shared
All the business logic code that is not UI could be shared. For this example, I got 3 libraries in my monorepo and all of them could be shared:
- models: types and interface definitions
- services: services that interact with API
- store: redux store
With Nx, it requires zero configuration to share the above library code. Even though when I created these libraries for a web app, I used commands like `nx generate @nrwl/react:lib store`, I could still use them directly in my react native mobile app.
For example, I need to create a film page to display film details with film id passed in as a parameter:
![](/blog/images/2022-02-01/1*zD_5omXSG-hIVHbgpCb-bA.avif)
_Screenshot of Film Page on Mobile (left: iOS, right: Android)_
I would do import from the store library directly:
```typescript
import {
filmsActions,
filmsSelectors,
RootState,
} from '@studio-ghibli-search-engine/store';
```
The film component would become:
```typescript {% fileName="film.props.ts" %}
import { AnyAction, ThunkDispatch } from '@reduxjs/toolkit';
import {
filmsActions,
filmsSelectors,
RootState,
} from '@studio-ghibli-search-engine/store';
const mapStateToProps = (state: RootState) => {
return {
getFilm: (id: string) => filmsSelectors.selectFilmById(id)(state),
};
};
const mapDispatchToProps = (
dispatch: ThunkDispatch<RootState, void, AnyAction>
) => {
return {
fetchFilms() {
dispatch(filmsActions.fetchFilms());
},
};
};
type mapStateToPropsType = ReturnType<typeof mapStateToProps>;
type mapDispatchToPropsType = ReturnType<typeof mapDispatchToProps>;
type FilmProps = mapStateToPropsType & mapDispatchToPropsType;
export { mapStateToProps, mapDispatchToProps };
export type { FilmProps };
```
```tsx {% fileName="film.tsx" %}
import { RouteProp, useRoute } from '@react-navigation/native';
import { FilmEntity } from '@studio-ghibli-search-engine/models';
import { getEnv } from '@studio-ghibli-search-engine/services';
import React, { useEffect, useState } from 'react';
import { SafeAreaView, ScrollView, Image, View } from 'react-native';
import {
Button,
Divider,
Headline,
Paragraph,
Subheading,
Title,
} from 'react-native-paper';
import { styles } from 'react-native-style-tachyons';
import { connect } from 'react-redux';
import Loading from '../shared/loading/loading';
import { useLink } from '../shared/open-link/open-link';
import { FilmProps, mapDispatchToProps, mapStateToProps } from './film.props';
export function Film({ getFilm, fetchFilms }: FilmProps) {
const [film, setFilm] = useState<FilmEntity>();
const route = useRoute<RouteProp<{ params: { id: string } }>>();
const id = route.params?.id;
const openHboMax = useLink(getEnv('NX_HBO_STREAMING_URL'), 'HBO Max');
const openNetflix = useLink(getEnv('NX_NETFLIX_STREAMING_URL'), 'Netflix');
useEffect(() => {
fetchFilms();
}, [fetchFilms]);
useEffect(() => {
setFilm(getFilm(id));
}, [id, getFilm]);
return film ? (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={[styles.pa3]}>
<Image
style={{ height: 200, width: '100%', resizeMode: 'contain' }}
source={{ uri: film.movieBanner }}
/>
<Headline>{film.title}</Headline>
<Subheading>
{film.originalTitle} / {film.originalTitleRomanised}
</Subheading>
<Paragraph>Release: {film.releaseDate}</Paragraph>
<Paragraph>Director: {film.director}</Paragraph>
<Paragraph>Producer: {film.producer}</Paragraph>
<Paragraph>Running Time: {film.runningTime} minutes</Paragraph>
<Paragraph>Rotten Tomatoes Score: {film.rtScore}</Paragraph>
<Divider />
<Title>Plot</Title>
<Paragraph>{film.description}</Paragraph>
<Divider />
<Button onPress={openHboMax}>Watch on HBO Max</Button>
<Button onPress={openNetflix}>Watch on Netflix</Button>
</View>
</ScrollView>
</SafeAreaView>
) : (
<Loading />
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Film);
```
Note I could import from `@studio-ghibli-search-engine/models`, `@studio-ghibli-search-engine/services` and `@studio-ghibli-search-engine/store` directly.
Now when I run `nx dep-graph`, it shows the dependency graph below where all these 3 libraries are shared between web and mobile:
![](/blog/images/2022-02-01/1*697qjtaGr4mTSnuRq6vpPw.avif)
_Dependency graph_
For this example project, to create the mobile app, it took me some time to rewrite the entire UI. However, I do not need to make any changes to the above libraries.
![](/blog/images/2022-02-01/1*Ldob3R4V50WG4gP-UzKAOg.avif)
_Screenshots of Mobile App (left: iOS, right: Android)_
## Conclusion
In this article, we ended up building both, a React-based web application and a corresponding React Native app in the same repository using Nx.
Nxs architecture promotes the separation of concerns, splitting things into `apps` (which are technology-specific) and `libs` which can be technology-specific or technology-independent. That allows us to easily have our common business logic in a technology-independent library which in turn (thanks to Nxs setup) be easily linked to both, our React web and React Native mobile app.
Although there are UI-specific differences we need to account for, that simply comes with one being a web tech stack and the other being a native app, we were still able to share big chunks of the technology-independent business logic of our application. That ultimately helps with maintenance and having feature parity across different platforms.
_(Note, the repository with the code for this article is linked at the very top)_

View File

@ -0,0 +1,307 @@
---
title: 'Introducing Expo Support for Nx'
slug: 'introducing-expo-support-for-nx'
authors: ['Emily Xiong']
cover_image: '/blog/images/2022-03-23/1*yYc8g4ifk9RApSjAhQysag.png'
tags: [nx, release]
---
We are very excited to announce our support for Expo with our new package `@nrwl/expo`. In addition to the React Native support, with this release of `@nrwl/expo`, you will be able to easily develop mobile apps in the monorepo. If you use Expo in a monorepo then Nx is the tool for you.
This blog will show you how to create a one-page app to display a poem:
![](/blog/images/2022-03-23/1*vDAGnOKsuXDhMDDtw7Swcg.avif)
_Page Screenshot (left: Android, right: iOS)_
Github Repo: [xiongemi/nx-expo-poetry](https://github.com/xiongemi/nx-expo-poetry)
## Before We Start
When I just started to try out Expo, the first questions came to my mind were “what is the difference between Expo and React Native” and “when to choose Expo and when to choose React Native”? In short, Expo is a set of tools built on top of React Native. You can read it more at [https://stackoverflow.com/questions/39170622/what-is-the-difference-between-expo-and-react-native](https://stackoverflow.com/questions/39170622/what-is-the-difference-between-expo-and-react-native).
Now I have created an app with Expo, to me, the most significant differences are developer experience and the build process.
![](/blog/images/2022-03-23/1*JqkWuBAXkfVVDZbQ7Kzffg.avif)
_Left: managed Expo project folder, right: React Native project folder_
For a managed Expo project, notice that it only has a `src` folder; whereas for a React Native project, besides the `src` folder, it also contains the `android` and `ios` folder. For a managed Expo project, developers do not need to worry about maintaining code for iOS and Android. However, you can still write customized native code for Expo, you can use Expo with [bare workflow](https://docs.expo.dev/introduction/managed-vs-bare/#bare-workflow) after running the command `expo eject`.
Moreover, Expo provides [Expo Application Services(EAS)](https://docs.expo.dev/eas/) to build and distribute your app. React Native developers can bundle and build locally using Android Studio or Xcode. However, with EAS Build, it will build on a hosted service. Of course, there is potentially a fee involved: [https://expo.dev/pricing](https://expo.dev/pricing).
**Something to note:** [@nrwl/expo](https://www.npmjs.com/package/@nrwl/expo) and [@nrwl/react-native](https://www.npmjs.com/package/@nrwl/react-native) cannot exist in the same monorepo due to dependency version conflicts. Expo usually tails the latest React Native by a few versions, whereas [@nrwl/react-native](https://www.npmjs.com/package/@nrwl/react-native) tries to align with the latest React Native version.
## Setup
First, lets create an Nx workspace:
```shell
npx create-nx-workspace nx-expo-poetry --preset=empty
```
Then you need to install @nrwl/expo package:
```shell
cd nx-expo-poetry
# npm
npm install @nrwl/expo --save-dev
# yarn
yarn add @nrwl/expo --dev
```
Then you need to generate an expo app:
```shell
nx generate @nrwl/expo:app poetry-app
```
Now you should notice that under the apps folder, there are 2 folders generated: `peotry-app` and `poetry-app-e2e:`
![](/blog/images/2022-03-23/1*xLRdddGDLfGSD5wJLOpzuQ.avif)
_apps folder_
Now run the command to serve up the Expo Development Server:
```shell
nx start poetry-app
```
You should see the starter app in the simulator:
![](/blog/images/2022-03-23/1*QTtTs_ggIHyzv0b4vSGX3w.avif)
_Expo Development Server_
## Create First Page
Now we got the app running, lets create our first page. In this example, we are going to use the [React Native Paper](https://callstack.github.io/react-native-paper/) as the material design library. To install:
```shell
# npm
npm install react-native-paper --save
# yarn
yarn add react-native-paper
```
Then, lets create our first component. This component simply displays a poem on the page.
First, to add a component file under the app, run the below command:
```shell
nx g @nrwl/expo:component poem-of-the-day --directory=components
```
Now you should see the components under apps/components:
![](/blog/images/2022-03-23/1*HZUqQJbNUqBfPns7qqvN5w.avif)
Then paste the below code to the `App.tsx` and `poem-of-the-day.tsx`:
```tsx {% fileName="App.tsx" %}
import React from 'react';
import { SafeAreaView, ScrollView } from 'react-native';
import { Provider as PaperProvider } from 'react-native-paper';
import PoemOfTheDay from '../components/poem-of-the-day/poem-of-the-day';
const App = () => {
return (
<PaperProvider>
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<PoemOfTheDay></PoemOfTheDay>
</ScrollView>
</SafeAreaView>
</PaperProvider>
);
};
export default App;
```
```tsx {% fileName="poem-of-the-day.tsx" %}
import React from 'react';
import { Card, Title, Paragraph, Subheading } from 'react-native-paper';
/* eslint-disable-next-line */
export interface PoemOfTheDayProps {}
export function PoemOfTheDay(props: PoemOfTheDayProps) {
return (
<Card>
<Card.Cover source={{ uri: `https://picsum.photos/300/200` }} />
<Card.Content>
<Title>Ozymandias</Title>
<Subheading>Percy Bysshe Shelley</Subheading>
<Paragraph>
I met a traveller from an antique land {'\n'}
Who said: Two vast and trunkless legs of stone {'\n'}
Stand in the desert...Near them, on the sand, {'\n'}
Half sunk, a shattered visage lies, whose frown,{'\n'}
And wrinkled lip, and sneer of cold command, {'\n'}
Tell that its sculptor well those passions read {'\n'}
Which yet survive, stamped on these lifeless things, {'\n'}
The hand that mocked them, and the heart that fed: {'\n'}
And on the pedestal these words appear: {'\n'}
'My name is Ozymandias, king of kings: {'\n'}
Look on my works, ye Mighty, and despair!' {'\n'}
Nothing beside remains. Round the decay{'\n'}
Of that colossal wreck, boundless and bare{'\n'}
The lone and level sands stretch far away.
</Paragraph>
</Card.Content>
</Card>
);
}
export default PoemOfTheDay;
```
Now, if you run command `nx start poetry-app` and then run the app on the simulator, you should see:
![](/blog/images/2022-03-23/1*563FtEWPwo4m93qOvFmk1Q.avif)
_Page Screenshot (left: Android, right: iOS)_
To see it in the real device, run `nx publish poetry-app`.
Awesome! Now you have built your first page. However, notice this page only displays a static poem. The next step is to integrate with the API. In this example. We are going to use PoetryDB: [https://github.com/thundercomb/poetrydb](https://github.com/thundercomb/poetrydb).
## Create a Workspace Library
To create a library that gets a random poem from the API, run the command:
```shell
nx generate @nrwl/expo:library services
```
This should generate a services folder under libs:
![](/blog/images/2022-03-23/1*7jNkHVOQpfZ6XAoWnDFc8A.avif)
Create a `poetry.service.ts` file to call the PoetryDB API and get a random poem:
```typescript {% fileName="poem-response.interfacve.ts %}
// at libs/services/src/models/poem-response.interface.ts
export interface PoemResponse {
title: string;
author: string;
lines: string[];
linecount: string;
}
```
```typescript {% fileName="poetry.service.ts" %}
// at libs/services/src/poetry/poetry.service.ts
import { PoemResponse } from '../models/poem-response.interface';
const POETRY_BASE_URL = 'https://poetrydb.org/';
export async function getPoemOfTheDay(): Promise<PoemResponse[]> {
const response: Response = await fetch(POETRY_BASE_URL + 'random', {
method: 'GET',
});
if (response.ok) {
return await response.json();
}
throw response;
}
export const poetryService = { getPoemOfTheDay };
```
For the service we created above, we can import it in the app directly like:
```shell
import { PoemResponse, poetryService } from '@nx-expo-poetry/services';
```
Then the `apps/poetry-app/src/components/poem-of-the-day/poem-of-the-day.tsx` would become:
If you now run the app using `nx start poetry-app`, you should see the poem loaded from API:
![](/blog/images/2022-03-23/1*ytjIE4sXlqWHG10ltVw-Dw.avif)
_Page Screenshot (left: Android, right: iOS)_
## Using Expo Build
Now you want to build and possibly publish your app. To build the standalone app, you can use the Expo build. First, you need to create an Expo account. You can do it at [https://expo.dev/signup](https://expo.dev/signup) or using the command line:
```shell
npx expo login
```
Then you can run the build command:
```shell
# iOS
nx build-ios poetry-app
# Android
nx build-android poetry-app
```
You can monitor your builds after logging in at [https://expo.dev/](https://expo.dev/):
![](/blog/images/2022-03-23/1*MlV6Ph6KEeA6L-kMpL8FEQ.avif)
_Builds page at https://expo.dev/_
You can read more at [https://docs.expo.dev/classic/building-standalone-apps/](https://docs.expo.dev/classic/building-standalone-apps/) to debug.
## Using EAS Build
Before you start to use EAS build, you need to install EAS CLI:
```shell
npm install -g eas-cli
```
Then, you can sign up and log in to your Expo:
```shell
npx expo login
```
Then go to the app folder using `cd apps/poetry-app` and simply run:
```shell
eas build
```
You can monitor your builds after logging in at [https://expo.dev/](https://expo.dev/):
![](/blog/images/2022-03-23/1*84j3XYXVDVlvSXbX2xR29Q.avif)
_Builds page at https://expo.dev/_
To submit to the app store, run:
```shell
eas submit
```
## Conclusion
In this article, we have:
- successfully built an expo app using Nx
- add UI in the app
- create a separate library to handle services
- use EAS to build the app
With Nx, we can create as many libraries as we want to handle different concerns. It would be very handy to share and reuse libraries or have multiple apps in the same monorepo.
I hope you found this useful, and we look forward to hearing your [feedback](https://github.com/nrwl/nx-labs/issues).
If youre new to Nx and want to learn more, visit [our docs](/getting-started/intro)**.**
_(Note, the repository with the code for this article is linked at the very top.)_
This app is also available in the app store, just search “Poem of the Day”:
Android:
[Poem of the Day](https://play.google.com/store/apps/details?id=com.exiong.poetryapp)
iOS:
![](/blog/images/2022-03-23/1*VnB0y4EDRPFExB9E8KRf1A.avif)
_Screenshot in iOS app store_

View File

@ -0,0 +1,453 @@
---
title: 'The React CLI you always wanted but didnt know about'
slug: 'the-react-cli-you-always-wanted-but-didnt-know-about'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-03-29/1*YR6QUEZel3nlNcTo6Pdlwg.png'
tags: [nx]
---
_In this article, Id like to specifically talk about developer tooling, why it is so massively important and how you might have missed out on Nx as your main React CLI for kickstarting new awesome projects._
It is awesome to be a JavaScript developer nowadays. The JavaScript ecosystem has evolved a lot in recent years. For the better! Speed has become a major focus, both from the framework perspective of running the app in production, as well as the speed of developing, testing, and building JavaScript/TypeScript from a developer tooling point of view. Frameworks and libraries such as Next.js, Astro, Qwik and Remix (just to name a few) have brought some great innovations to push the web even further.
While speed is of major importance, developer ergonomics shouldnt be left behind. Both of them greatly contribute to the overall productivity and also developer happiness 🙂. Lets see how Nx can help with that.
**Prefer the video version?**
{% youtube src="https://www.youtube.com/watch?v=QghilgRe-pw" /%}
## Update (Aug 2023): Want a non-monorepo setup?
This article walks you through how to setup a new Nx monorepo workspace with React. If you rather prefer starting with a single-project setup (also named “standalone”) then you might want to have a look at this tutorial (including video):
[/getting-started/tutorials/react-standalone-tutorial](/getting-started/tutorials/react-standalone-tutorial)
## Why use a devtool CLI?
Regardless of whether youre a seasoned developer or someone new just getting started with React: the last thing you want to have to deal with is to manually set up all the tooling to actually get started and be productive. You want to be able to focus on the actual task, like learning React or kicking off that new shiny project.
Still, we definitely want to **have good defaults set up for us**. Things like the latest build tooling, tooling for writing unit tests as well as e2e tests, code quality tools like linters, and we definitely also dont want to argue about tabs vs spaces or spend time formatting our code: Prettier can help with that.
Taking the time to set up a starter kit or template would work. But it is time-consuming, requires a lot of knowledge, and especially needs maintenance to update the tools over time. That rarely works out well in the long run, unless this is your job.
## Nx — from a birds eye view
What you usually want is a CLI, a command-line interface that helps you develop and deal with the underlying build infrastructure, something that sets you up with modern up-to-date tooling and also keeps those updated!
Nx comes with such a CLI, it is widely adopted by the Angular, React and Node community currently being downloaded more than 1.3 million times a week. Nx is [fully open source](https://github.com/nrwl/nx) (MIT licensed), baked by [Nrwl](/company) and the [community](https://go.nx.dev/community).
From a birds eye view, Nx comes with
- Code generators to generate new projects, configuration but also components, Redux setup, routes…
- Out of the box support for modern tools such as TypeScript, Webpack, Babel, SWC, Jest, Cypress, ESLint, Prettier, Storybook and more
- It keeps tooling up to date via dedicated migration commands
- Speed! Nx uses local computation caching that can be extended with Nx Cloud (which is basically free) to remote caching and DTE (Distributed Task Execution).
But lets have a deeper look at how Nx works exactly.
## Using Nx
Let me give you an overview of the most used functionality that Nx gives you such that you get a good understanding of whether it might suit your needs.
## Creating a new Nx React project
Open your favorite terminal window and type:
```shell
npx create-nx-workspace@latest myorg
```
> _Note, Im using_ `_npx_` _to not have to install the Nx CLI globally. If you want to, you totally can:_ `_npm i nx -g_`
`myorg` is the scope of your Nx workspace. Think of it as your NPM scope in case youd publish an npm package. In the case you create libraries in this new Nx workspace (more about that later), it would be used to import those, like
```typescript
import { someFunc } from '@myorg/somelib';
```
What youll get is a setup wizard that guides you through creating your application. We would most likely choose “React” in this case.
![](/blog/images/2022-03-29/1*zLwqiNgVNDrLJMir1BV5TA.avif)
_Nx CLI guides through the setup process_
As part of this process, youll be asked to pick an “Application name”. This is simply the application Nx is going to generate for us to get started: `happynrwl` would be a nice name 🙂.
You should end up with a new Nx workspace and our `happynrwl` React app in the `apps/` folder.
![](/blog/images/2022-03-29/1*3OToVs1mu94M0Bt4WHvYMg.avif)
_Layout of a Nx workspace in VSCode_
## Serving our React app
To serve our React app, run
```shell
npx nx serve happynrwl
```
> _Note I prefix the commands with_ `_npx_`_, which is just a way to use the local_ `_nx_` _binary from the_ `_node_modules_` _folder of our workspace. Also, this way we dont have to install Nx globally. If you prefer doing that, run_ `_npm install -g nx_`_._
Going to [http://localhost:4200](http://localhost:4200/) should show the running React app located in `apps/happynrwl`.
![](/blog/images/2022-03-29/1*TCZXh6HHJ7t9mEl3WzACrg.avif)
_Welcome screen when launching the React application with Nx_
## Build our React app
Similarly, to build our React application, run
```shell
npx nx build happynrwl
```
This should build the app into `dist/apps/happynrwl`, which we can then take and deploy to wherever we want to deploy it.
![](/blog/images/2022-03-29/1*JvmIPkyEijF7akQwgr201w.avif)
_Output folder assets when building the React app_
Nx has another nice feature that basically comes for free: [computation caching](/concepts/how-caching-works). For every command Nx runs, it computes a unique hash that contains information about the involved source code, environment variables and the command itself. Next time the same conditions are met, the command is not executed again, but rather pulled out of a cache. As you can imagine, this drammatically speeds up things.
If youre curious and want to learn more, check out the docs page on [computation caching](/concepts/how-caching-works) and how to leverage [Nx Cloud](/nx-cloud) to store the cache remotely for sharing it with your team members. Also, Nx Cloud pricing recently changed, which makes it basically free for everyone.
## Code Generators!
One of the core parts of Nx is code generators. As the name already suggests, code generators generate source code and configuration. That can range from a single React component file to an entire project with all that is needed. You basically already saw them in action when you created the initial project setup. But theres more to explore! Every Nx plugin (e.g. `@nrwl/react`, `@nrwl/next`,...) come with their own set of generators. All of them are invoked with the `npx nx generate` or short `npx nx g` command.
Lets for instance generate a new component for our React application:
```shell
npx nx generate @nrwl/react:component HelloWorld
```
This generates a new component in our `happynrwl` application
![](/blog/images/2022-03-29/1*LSrJe2d93wPWzKwZ-gGzXw.avif)
_Example of a React component generated by Nx_
> _Note, you can also use_ `_nx g @nrwl/react..._` _as a shorthand for_ `_generate_`_. Also, if you attach_ `_--dry-run_` _to the end of the command it will just simulate the run without touching the file system._
Many of these generators come with a rich set of flags. For example, passing `--routing` to our component generator from before, generates a component with routes already set up, adds `react-router-dom` to the `package.json` and executes a `npm install`.
**How do we find all these generators though?** There are different options:
- **Nx documentation** — use the search function there or just navigate the docs. All the reference pages are structured like `nx.dev/packages/<packagename>`. As an example for React that would look like: [/nx-api/react](/nx-api/react).
- `npx nx list` - lists a set of installed plugins as well as other available plugins that can be installed. To get a list of generators for a specific plugin - say for the `@nrwl/react` plugin - run `npx nx list @nrwl/react`. Similarly, you can then run `npx nx g @nrwl/react:lib --help` to get help for a particular generator
However, the absolute easiest way to explore the potential and even use Nx if you are not the “terminal type of person” is [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)! Ill go a bit deeper into that in a later section.
## State of the Art Tooling Preconfigured
When setting up a new React project (that also holds for Angular, Node, Next.js,…), you do not only get the React project, but also a set of tools preconfigured that help you stay productive and produce higher quality code. These are
- TypeScript
- ESLint
- Jest
- Cypress
- Prettier
The Nx core team closely collaborates with these open source projects to not only make sure they integrate seamlessly with the React setup but also to keep them updated over time as those tools evolve. In fact, by using [automated code migrations](https://egghead.io/lessons/javascript-update-your-nx-workspace-with-nx-migrations) updating your Nx workspace will automatically also update those tools and the corresponding config files for you.
Lets have a closer look.
## TypeScript as a first-class citizen!
The Nx core team strongly believes in the benefits of TypeScript (in fact, check out the [new Nx and TypeScript setup](/getting-started/intro)). As such, by default every project is automatically set up and configured to use TypeScript, making sure builds, as well as IDEs, are able to properly pick up TypeScript definitions. All without you having to worry about it.
Now, if you really want to use pure JavaScript you totally can. Just pass the `--js` when running a generator. Read [more on the docs](/recipes/tips-n-tricks/js-and-ts).
## ESLint preconfigured!
Every new Nx workspace comes with [ESLint](https://eslint.org/) already preconfigured. Having proper linting in place is a great way to help contribute to overall better code quality by statically analyzing your source code and finding potential issues early in the process.
Every project generated by Nx comes with a `.eslintrc.json` file. That configuration extends from an ESLint plugin `@nrwl/nx/react` , containing a set of best practices rules, and at the same time allows you to add further rules that are specific to your needs.
![](/blog/images/2022-03-29/1*dK6mtSHmsgiMDWF1XotMEA.avif)
_ESLint configuration in an Nx workspace_
Linting can be run similarly to the other commands:
```shell
npx nx lint happynrwl
```
## Jest preconfigured!
Similar to the linting setup, every project in an Nx workspace has a test runner preconfigured already. By default, Nx comes with [Jest](https://jestjs.io/).
At the root of every project, theres a `jest.config.js` which already comes with proper transformers to support TypeScript and TSX/JSX. If you need to further customize how Jest should behave for this project, this is the place to do that.
![](/blog/images/2022-03-29/1*JyIIbncCwSqDMg3gWzUPBw.avif)
_Jest configuration in an Nx workspace_
Running Jest tests is as easy as
```shell
npx nx test happynrwl
```
Obviously, you can pass parameters to customize the Jest run, like
- `--watch` for interactive mode
- `--t` to execute tests that match a given pattern
- `--testFile="apps/happynrwl/src/app/hello-world/hello-world.spec.tsx”` to run a specific file
- …
If you happen to use [VSCode](https://code.visualstudio.com/), the easiest way however is to install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) and leverage its code lens feature to run and debug Jest tests:
![](/blog/images/2022-03-29/1*11HC8HeQER_YIbyd9RpdNA.avif)
_Using VSCode extensions to run Jest tests directly via Code Lens support_
## Cypress preconfigured!
[Cypress](https://www.cypress.io/) has revolutionized e2e testing by making it more developer-friendly. Who likes to write tests after all. That just gets even worse if the DX sucks. Cypress successfully tackled that by listening and addressing the pain of existing e2e testing solutions.
Whenever you generate a new project in an Nx workspace, you have the option to automatically also create a Cypress-based e2e project alongside it. In our case, it is called `happynrwl-e2e`.
![](/blog/images/2022-03-29/1*OA1d-lV54ylpNFd9ayJ07Q.avif)
_Cypress e2e app generated by Nx along-side the main React app_
The awesome part of this is that you dont have to configure anything at all. No need to
- make sure TypeScript runs smoothly with Cypress
- set up linting for our e2e project (yes writing good quality test code is just as important)
- spinning up our development server manually first that serves our React app such that we are able to load it in our Cypress tests environment
Just execute
```shell
npx e2e happynrwl-e2e
```
You can also pass `--watch` to run it interactively with the Cypress test runner such that the tests get re-executed whenever we change our source.
## Dont argue over code formatting — use Prettier!
Are you a `tabs` or `spaces` person? Use semicolons or not? What about trailing commas? We all know that we devs can have some strong opinions on this 😅. But honestly, there are probably more important things to focus on. Luckily [Prettier](https://prettier.io/) can help a ton with these issues. It is opinionated with just very few configuration options and just takes away the burden of formatting the code.
When you set up a new Nx workspace, it has Prettier already preconfigured. The best way is to integrate it with your code editor such that formatting is run on every save of a file. Alternatively, you can also run
```shell
npx nx format
```
## Nx Console — A dedicated VSCode extension for Nx
![](/blog/images/2022-03-29/1*1gRcDUmEkjOn6DR8vO9MHA.avif)
Nx really is an advanced CLI based development tool. But regardless of whether you are a command line person or not, if you happen to use [VSCode](https://code.visualstudio.com/) make sure you install the [Nx Console extension](/getting-started/editor-setup) from the [marketplace](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console).
> _For_ [_Webstorm_](https://www.jetbrains.com/webstorm/) _there are two community extensions that can be used:_ [_nx-webstorm_](https://plugins.jetbrains.com/plugin/15000-nx-webstorm) _and_ [_Nx Console Idea_](https://plugins.jetbrains.com/plugin/15101-nx-console-idea)_._
Once you have the extension installed, you can click its icon in the VSCode Activity Bar (1) which reveals the Nx Console UI.
![](/blog/images/2022-03-29/1*GPrI7Pta18FuEljgm9h4pQ.avif)
_Nx Console VSCode extension_
A couple of things:
- (2) is the panel where you see a fixed command “Generate” to invoke the Nx generator for creating new projects, libraries etc as we mentioned before. In addition you see a list of available commands to run.
- (3) shows additional commands that are commonly used in an Nx workspace. Feel free to click and explore them.
- (4) shows a list of projects in your workspace. We really just have our React app and Cypress e2e application, but potentially you could add more. See [Nx applications and libraries](/concepts/decisions/project-size) for more.
Lets take the example of generating a new React component, just as we did before, but this time using Nx Console. This is how youd do that:
![](/blog/images/2022-03-29/1*wJ4ZldDh_Glvxwl_0SDxHA.avif)
_Actions to generate a new React component with Nx Console_
Once you click the entry in the dropdown list, the Nx Console generate form opens, showing all the options the Nx generator supports:
![](/blog/images/2022-03-29/1*0F8baQFGgATjnQn30CqVeg.avif)
_Detail form shown by Nx Console to generate a new React component_
Whenever you change something in the form (1), youll automatically see a dry-run in the console that opens below (2). That shows what would happen if you run the command and is equivalent of adding the `--dry-run` flag whenever youd run the command on the terminal. Once youre ready, hit the “Run” button (3), or click the copy symbol (4) to copy the full command into your clipboard s.t. you can then paste it into your terminal.
As you can see this approach is also really powerful for exploring different commands and their corresponding options.
Besides running generators, Nx Console also adds [VSCode Code Lens](https://code.visualstudio.com/blogs/2017/02/12/code-lens-roundup) abilities to the configuration files that help you navigate more quickly across the workspace. This is particularly useful if you happen to add more [apps and libraries](/concepts/decisions/project-size) to the workspace at some point.
![](/blog/images/2022-03-29/1*WIbxp7um-f4CK2-N-zRing.avif)
_Nx Console Code Lens support to navigate easily among config files_
## Evergreen Workspace Setup
One of the advantages of using Nx over — say CRA or a custom starter template — is that your **Nx workspace is evergreen**. What do I mean by that: by now we all know how fast the frontend space is moving, and so are the corresponding devtools. Today you might be using [Rollup](https://rollupjs.org/) to build your libraries, tomorrow you use [swc](https://swc.rs/), [vite](https://vitejs.dev/) or [esbuild](https://esbuild.github.io/). Same with [Webpack](https://webpack.js.org/). Webpack 5 has been around for a while already, and still, a lot of projects are stuck at v4.
Just to mention an example: when upgrading Nx to v13, all Nx users automatically got migrated to Webpack 5.
This is possible with Nxs [migrate command](/nx-api/nx/documents/migrate) that allows you to keep up to date with your framework in a mostly automated fashion. Whenever you upgrade Nx, you run
```shell
npx nx migrate latest
```
Running this command, Nx
- analyzes the current packages
- fetches the latest Nx packages and plugins (or whatever version was specified in the migration command)
- creates a `migrations.json` file containing all migration scripts that need to be executed
- updates the `package.json` to the new package versions
The `migrations.json` file can be inspected and potentially modified. Once it is ready, running the following command executes the migration:
```shell
npx nx migrate --run-migrations=migrations.json
```
These migrations not only update the `package.json` version. They also update corresponding configuration files and even source code by leveraging ASTs to query and manipulate files.
It is not even only about upgrading the frameworks such as React or Angular themselves, though. A common pain point is their integration with other tools, such as Jest, Storybook, ESLint etc. The Nx core team closely collaborates with these communities to make sure that a particular combination of versions works and is tested before migrating your workspace.
{% youtube src="https://www.youtube.com/watch?v=Ss6MfcXi0jE" /%}
## Common Questions
Here are some common questions developers have. Have some more? Feel free to ping me on Twitter ([@juristr](https://twitter.com/juristr)), the official Nx account ([@NxDevtools](https://twitter.com/nxdevtools)) or in the [Nx community Discord](https://go.nx.dev/community).
## Q: How can I customize how my project is built and served?
Every Nx project comes with a `project.json` which contains the basic setup of targets (example: `build`, `serve`, `test`, `lint`,..) that can be run against the project.
Heres the `project.json` for our `happynrwl` React application. I clipped out the non-relevant parts here:
```json5
{
...
"targets": {
"build": {
"executor": "@nrwl/web:webpack",
...
"options": {
"compiler": "babel",
"outputPath": "dist/apps/happynrwl",
"index": "apps/happynrwl/src/index.html",
"baseHref": "/",
"main": "apps/happynrwl/src/main.tsx",
"polyfills": "apps/happynrwl/src/polyfills.ts",
"tsConfig": "apps/happynrwl/tsconfig.app.json",
"assets": [
"apps/happynrwl/src/favicon.ico",
"apps/happynrwl/src/assets"
],
"styles": ["apps/happynrwl/src/styles.css"],
"scripts": [],
"webpackConfig": "@nrwl/react/plugins/webpack"
},
"configurations": {
"production": {
...
}
}
},
"serve": {
...
},
...
},
"tags": []
}
```
As you can see, all these “targets” (`build`, `serve`,...) have a so-called `options` property that allows you to configure how the target behaves. The actual configuration is abstracted behind the “[Nx Executor](/concepts/executors-and-configurations)”, in our case `@nrwl/web:webpack`. You can find the details of how to configure that on the Nx docs in the CLI reference for the `@nrwl/web` package: [/nx-api/webpack/executors/webpack](/nx-api/webpack/executors/webpack).
To read more about how the `project.json`, its executors, and configuration options are structured, check out the official docs: [/reference/project-configuration](/reference/project-configuration).
> _Note, Nx is also able to just pick up NPM scripts registered in the_ `_package.json_` _of your project root. This scenario is most useful if youre adding Nx to an existing monorepo (see_ [_add-nx-to-monorepo_](https://www.npmjs.com/package/add-nx-to-monorepo)_). Read more here:_ [_/reference/project-configuration_](/reference/project-configuration)
Nxs extensibility and customizability have really no limits, allowing it to really adapt to your needs. Here are some resources to learn more if you need some advanced features.
- [Custom workspace executors](/extending-nx/recipes/local-executors)
- [Custom workspace generators](/extending-nx/recipes/local-generators)
- [Create Nx plugins](/nx-api/plugin)
- Control the entire workspace setup with [custom presets](/nx-api/plugin)
## Q: Can I customize my Webpack config used to build my React app?
As mentioned previously, the underlying build machinery is usually hidden by a so-called [Nx Executor](/concepts/executors-and-configurations). As we have seen you can customize its behavior via the corresponding `options` property. By abstracting the underlying build tool, Nx is able to fulfill its evergreen promise as mentioned previously and allows to seamlessly upgrade workspaces to the latest versions of the build tooling that is being used.
If the available `options` are not enough, you can further customize the Webpack configuration using the `webpackConfig` property:
```json5
{
...
"targets": {
"build": {
"executor": "@nrwl/web:webpack",
...
"options": {
...
"webpackConfig": "@nrwl/react/plugins/webpack"
},
...
},
...
},
"tags": []
}
```
By default it links to `@nrwl/react/plugins/webpack`, but you can point to your own custom file in the Nx workspace. The file needs to look like the following:
```javascript {% fileName="apps/my-app/webpack.config.js" %}
const fromNrwlReact = require('@nrwl/react/plugins/webpack');
function getWebpackConfig(config) {
// invoke the Nrwl specific config to preserve the original
// behavior
config = fromNrwlReact(config); // add your own customizations HERE return config;
}
module.exports = getWebpackConfig;
```
Notice how the default Nrwl provided Webpack configuration is invoked first to not lose the default behavior, followed by your own customizations.
## Q: Why is there an “apps” folder? Can I change it?
Sure! Nx allows to host multiple applications and libraries in a single workspace: a monorepo scenario basically. In fact, even in our simple setup we have two applications: `happynrwl` and the corresponding e2e application, `happynrwl-e2e`.
In a default setup Nx generates an `apps` folder for hosting applications, and `libs` folder for hosting libraries. Read more about [“Apps and Libs” on the Nx docs](/concepts/decisions/project-size).
You can change this setup in `nx.json` by adjustijng the `workspaceLayout` property which has an `appsDir` and `libsDir` configuration.
```json5
{
...
"workspaceLayout": {
"appsDir": "apps",
"libsDir": "libs"
},
...
}
```
## Q: Is there a way to migrate from CRA?
Absolutely. Check out this guide on the Nx docs that has all the details (including a video walkthrough): [/recipes/adopting-nx/adding-to-existing-project](/recipes/adopting-nx/adding-to-existing-project)
## Q: This looks like a lot 🤯. Do I really need it from the get go?
Agreed. Luckily Nx is plugin based, so you can start with the bare minimum (see using [Nx without plugins](/getting-started/intro)) and then slowly add them as you need them. Similarly you can add Nx to an existing workspace (say a Yarn workspace) by using the [add-nx-to-monorepo](https://www.npmjs.com/package/add-nx-to-monorepo) package.
From my own experience, what usually happens is that teams start light and then over time end up with a similar stack, but hand-woven and therefore loosing out on a lot of the benefits Nx comes with.
## Q: Isnt Nx just for monorepos?
Nx has been designed to support monorepo scenarios, and it really shines at scale. However, a lot of the features Ive been mentioning in this article, such as generators, out of the box setup of best practices development tools, automated migrations and more make it an excellent choice, even if your intention is not to create a monorepo.
From my experience, Ive often seen teams start with a single application, which then over time gets company by other apps, in the form of React applications, also Node based backends or even a React Native application. Mainly because adding new applications is easy and the possibility to [share functionality (even across platforms)](/blog/share-code-between-react-web-react-native-mobile-with-nx) is appealing.
> _If youre interested in monorepos or want to learn more about it, check out_ [_https://monorepo.tools_](https://monorepo.tools/)_._
## Q: Isnt Nx just for Angular projects?
This is a common but understandable misconception. Although Nx was heavily inspired by the Angular CLI initially, it is now a completely independent build system and CLI with first-class support for Angular, React, Node, Next.js, TypeScript and more. And with tons of [community plugins](/community) that extend Nx beyond that.
## Conclusion
Congrats, you made it to the end of this article. By now you should have gotten a pretty good overview of what Nx is about, its strengths and how it can be useful in your next React project. If you still got questions or are hesitant to adopt Nx, [reach out to me on Twitter](https://twitter.com/juristr)!
Where to go from here?
- [Nx Official Discord Server](https://go.nx.dev/community)
- [follow me on Twitter](https://twitter.com/juristr)
- [follow Nx on Twitter](https://twitter.com/nxdevtools)
- subscribe on the [Nx Youtube channel](https://youtube.com/c/Nrwl_io)
- join more than 200+ developers and [take the free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038) on how to scale React development with Nx.

View File

@ -0,0 +1,270 @@
---
title: 'What is new in Nx 13.10?'
slug: 'what-is-new-in-nx-13-10'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-04-08/1*PJ3SRAadq0DxGiC9mCIWsA.png'
tags: [nx, release]
---
It has been a while since our last release blog post [which was on Nx 13.5](/blog/new-terminal-output-performance-improvements-in-nx-13-5). A lot has happened since then. So here we go!
## Housekeeping and “core” cleanup
We keep optimizing the Nx core. This round we started doing some housekeeping and cleanup that will allow us to move more quickly in the future and add new features more easily. In particular we now have a single package `nx` that contains all the core and CLI related functionality that have previously been in `@nrwl/cli` and `@nrwl/tao`. This also results in a reduce number of packages you need to install in any Nx workspace. In fact, if you run `add-nx-to-monorepo` - our easy migration command for [adding Nx to Yarn/NPM workspaces](/recipes/adopting-nx/adding-to-monorepo) - you should now see a single `nx` package and not have any `@nrwl/*` packages at all.
## Nx Daemon on by default
One of the core features of Nx is the calculation of the project graph. It is the basis for most other features in Nx like the [affected commands](/ci/features/affected), computation caching and calculation and topological sorting of parallelizing tasks [during DTE](/ci/features/distribute-task-execution). This is a I/O heavy operation. Whenever you change a file, the project graph needs to be re-calculated which involves reading the source files, analyze imports from other packages source files and external libraries.
Such a crucial and central feature like the project graph need to be as fast as possible. Thats the reason why we introduced the Nx Daemon, which is started automatically and runs in the background, watching for file changes and asynchronously recomputes and caches the project graph. As a result, whenever Nx runs an operation that requires the project graph, it is already there and ready to be used, without adding any additional delay to the operation that needs to be executed.
Read more on the docs: [/guides/nx-daemon](/concepts/nx-daemon)
## Nx Cloud opt-in now points to “Yes” by default
When you set up a new Nx workspace with `create-nx-workspace` the question about opting into Nx Cloud will be pointed on “Yes” by default now.
![](/blog/images/2022-04-08/1*2N8T5oP1MUgmBTF_Q0bF-A.avif)
_Nx Cloud opt-in when setting up a new Nx workspace_
## Build and run Nx Plugins locally in your Nx workspace
Nx can be used in a wide range of scenarios, from small open source projects, startup environments to massive enterprise monorepos. This is thanks to its modular plugin based architecture consisting of
- Nx core which provides the fundamental features such as the dependency graph calculation, computation caching and task execution
- `@nrwl/*` plugins which are those actively maintained by the Nx core team
- [Community plugins](/community)
This illustration should give you a rough idea. obviously some of the plugins may be built on top of others, leveraging common functionality. An example is the [@nrwl/js](/nx-api/js) plugin which not only can be used as a standalone plugin but also builds the basis for of many others by providing core JavaScript/TypeScript features.
![](/blog/images/2022-04-08/1*iMPg692nMj5ty709M7tTQQ.avif)
You can just use the [Nx core without any plugins](/getting-started/intro) to get started and later decide to add more plugins such as `@nrwl/react` or `@nrwl/js` etc depending on your specific use case.
As you can see, plugins are at the very core and for quite some time now weve had a [fully featured Devkit and Nx Plugin package](/extending-nx/intro/getting-started) to create your own. And the community followed: have a look at [all the community Nx plugins that are available out there](/community).
And we keep improving. Starting with Nx 13.10 you can now use Nx plugins to automate your local workspace. Install `@nrwl/nx-plugin` into your Nx workspace and generate a new plugin:
```shell
npx nx generate @nrwl/nx-plugin:plugin --name=workspace-extensions
```
This creates a new library with a pre-configured setup to develop a Nx plugin. Similarly to other libraries you can now use those in your local Nx target configurations.
```json5
{
root: 'apps/demo',
sourceRoot: 'apps/demo/src',
projectType: 'application',
targets: {
mybuild: {
executor: '@myorg/workspace-extensions:build',
outputs: ['{options.outputPath}'],
options: {
outputPath: 'dist/apps/someoutput',
},
},
},
}
```
Note the `executor` definition of the `mybuild` target. It was never easier to create custom workspace executors.
And it doesnt stop at the executors level. The local plugin setup comes with a generator setup too, which can be invoked just like
```shell
npx nx g @myorg/workspace-extensions:<generator-name>
```
where `@myorg` is your Nx workspace name you defined and `workspace-extensions` the plugin library name weve chosen. You are free to choose whatever suits you best. This new setup opens up a wide range of new possibilities including defining default workspace generators.
[Subscribe to our Youtube Channel](https://youtube.com/nrwl_io) for some upcoming tutorials and walkthroughs around this topic.
## Project Graph Visualization
We keep improving our project graph and make it more and more useful for visually exploring your Nx workspace. You can now click on an edge and list the files that cause it which can be extremely valuable during debugging.
![](/blog/images/2022-04-08/1*a2bXoE4fGcDmqPTrxDyEFg.avif)
_Improved Project Graph visualization showing information about the edges that connect nodes_
And this is just a sneak peak of whats coming in Nx v14, so stay tuned!
## New “notDependOnLibsWithTags” Linter option
Having a decent monorepo setup is not always just about speed but also to have features in place that help you keep your code-base healthy and maintainable in the long run. The Nx module boundary lint rules are an example for that.
![](/blog/images/2022-04-08/1*ceWCqFUBimFNl8VOONDFsQ.avif)
_Tagging Nx projects_
By assigning tags to your projects you can then configure which relationships among libraries and applications are allowed, and which are forbidden.
```json5
{
// ... more ESLint config here "@nrwl/nx/enforce-module-boundaries": [
"error",
{
// update depConstraints based on your tags
"depConstraints": [
{
"sourceTag": "type:app",
"onlyDependOnLibsWithTags": ["type:feature", "type:util"]
},
{
"sourceTag": "type:feature",
"onlyDependOnLibsWithTags": ["type:feature", "type:util"]
},
{
"sourceTag": "type:util",
"onlyDependOnLibsWithTags": ["type:util"]
}
]
}
] // ... more ESLint config here
}
```
Read more about it in this article: [blog/mastering-the-project-boundaries-in-nx)
So far you have only been able to specify which tags a library is allowed to depend on using the `onlyDepndOnLibsWithTags` property. This made it cumbersome to define in some situations. Now you have a brand new property `notDependOnLibsWithTags`
```json5
{
// ... more ESLint config here "@nrwl/nx/enforce-module-boundaries": [
"error",
{
// update depConstraints based on your tags
"depConstraints": [
{
"sourceTag": "type:util",
"notDependOnLibsWithTags": ["type:feature"]
}
]
}
] // ... more ESLint config here
}
```
More on Miroslavs tweet:
{% tweet url="https://x.com/meeroslav/status/1505844090713292808" /%}
## Automatic Lint rule fixes for self circular dependencies and wrong imports across library boundaries
Whether by accident or by letting your IDE auto-add the import. It often happens that the path that is being used is via the librarys TS path mapping through the `index.ts` entry point. This leads to a circular dependency when also `tslib-c-another.ts` is exported via the `index.ts`. Nxs module boundary lint rule correctly highlights this as can be seen in this screenshot.
![](/blog/images/2022-04-08/1*Nh5uHJxDvqxppHF5kJJjZw.avif)
_Self circular dependency issue within a Nx based library_
Adjusting these circular self references is easy, but can be cumbersome to find the correct imports and time consuming if you have hundreds of libs that might be affected by this. In the latest version of Nx we shipped a fix implementation for these lint rules, such that you can now conveniently add `--fix` to auto-adjust the imports:
```shell
npx nx lint tslib-c --fix
```
This will analyze your imports, find the correct file and adjust them accordingly:
![](/blog/images/2022-04-08/1*y81cryDv1j2uug38EgQsNg.avif)
_Automatic adjustment of circular self references when running the lint rule fix_
Similarly if you have relative or absolute imports across library boundaries rather than using the NPM scope, youll get a linting error.
![](/blog/images/2022-04-08/1*S69zum8bULwD_EXOT3xT6g.avif)
_Lint error about relative import across library boundaries_
Such imports will also be adjusted by applying the `--fix` to your linting command:
![](/blog/images/2022-04-08/1*tKX2DSDSKhR8UEN04_ckQg.avif)
_Automatic fixes for cross-library imports_
## React 18 support
Nx 13.10 introduces support for the latest React v18 release such that users can benefit from the latest features React has to offer. Check out our latest blog post on [“The React CLI you always wanted but didnt know about”](/blog/the-react-cli-you-always-wanted-but-didnt-know-about) to learn more how to use Nx for React development.
## React Native gets Storybook support
Weve drastically improved our support for React Native within Nx workspaces. Check out our latest blog posts on
- [Share code between React Web & React Native Mobile with Nx](/blog/share-code-between-react-web-react-native-mobile-with-nx)
- [Introducing Expo Support for Nx](/blog/introducing-expo-support-for-nx)
We are happy to announce that in addition to the before mentioned improvements, the React Native integration in Nx now also supports Storybook. Just use
```shell
npx nx generate @nrwl/react-native:storybook-configuration
```
or use Nx Console to get some more help in generating the Storybook setup.
## Ability to show all prompts when creating a new Nx workspace
By default when you create a new Nx workspace with `create-nx-workspace` you will see a couple of questions that help you find the correct setup for your needs. However, we just show a couple of the possible options, to not overwhelm you.
If however youre curious, you can now append `--allPrompts` to get all possible questions asked 🙂
```shell
npx create-nx-workspace@next myorg --allPrompts
```
Alternatively you can browse the [API docs on the Nx website](/nx-api/nx/documents/create-nx-workspace) to find out more.
## Deliver the best possible TypeScript experience with `@nrwl/js`
You might have noticed our new `@nrwl/js` package we released a couple of months ago.
[We have big plans with this one](https://github.com/nrwl/nx/discussions/9716), not only making it the foundation for many of our other packages that need TypeScript compilation and support, but also the goto package for the best possible TypeScript experience.
## Nx Console Improvements
Here are some of the highlights in the latest Nx Console release.
## Nx Targets of VSCode Command Menu
You can now open the VSCode Command menu (Cmd + Shift + P or Win + Shift + P) and enter “Nx: Run Target” to invoke the Run Target menu which allows to choose the target to run as well as the project to execute the target on.
![](/blog/images/2022-04-08/1*PuzwriM96qHohP28-_q3jA.avif)
_Commands can be invoked from the VSCode Command menu_
## Run Target View now in sync with workspace commands
While initially the “Generate and Run Target” panel was a static list of the usual Nx targets, it is now a dynamically generated list based on your actual workspace commands. Hence, also your custom defined targets will automatically show up.
![](/blog/images/2022-04-08/1*qILNK9-yQOtbgwE9uFMMiw.avif)
_Nx Console dynamically reads Nx targets from your Nx workspace now_
## Prompts for Angular CLI users
Nx Console has out of the box support to also be used on plain Angular CLI projects. With the latest version of Nx Console, Angular CLI users will receive a prompt about decorating their CLI setup with Nx to benefit from the improved performance brought by computation caching and Nx Cloud.
Learn more in this short video walkthrough:
{% youtube src="https://www.youtube.com/watch?v=vRj9SNVYKrE" /%}
## Our docs keep getting more and more awesome
Besides delivering awesome features, we keep improving our docs. They are essential to help discover new features and better understand existing ones. In the last weeks weve improved the navigation support, allowing you to navigate to a specific package with `/packages/<package-name>` such as [/nx-api/react](/nx-api/react) listing executors and generators that come with that Nx package, also improving the API docs of the individual executor options including a live embedded editor playground to experiment with different configuration setup.
Check out Benjamin Cabanes tweet with some short videos:
{% tweet url="https://x.com/bencabanes/status/1509641445086535687" /%}
## How to Update Nx
Updating Nx is done with the following command, and will update your Nx workspace dependencies and code to the latest version:
```shell
npx nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
npx nx migrate --run-migrations
```
## Exciting?
Then wait for Nx v14 to land 😉.
- Check out the [release changelog](https://github.com/nrwl/nx/releases/tag/13.10.0)
- Follow us [on Twitter](https://twitter.com/NxDevTools), and
- subscribe to the [YouTube Channel](https://youtube.com/nrwl_io?sub_confirmation=1) for more information on [Angular](https://angular.io/), [React](https://reactjs.org/), Nx, and more!

View File

@ -0,0 +1,309 @@
---
title: 'Use Storybook with Nx React Native'
slug: 'use-storybook-with-nx-react-native'
authors: ['Emily Xiong']
cover_image: '/blog/images/2022-04-25/1*64nWVfUBihlYTLGWOvnc1g.png'
tags: [nx, release]
---
In my previous [blogs](/blog/share-code-between-react-web-react-native-mobile-with-nx) _(see links at the end)_, I wrote about how to develop Nx React Native applications. However, as developers, we are constantly searching for ways to make the developer experience better.
This blog will show how to add Storybook to Nx React Native applications. With Nx, you dont need to go through [this long guideline](https://storybook.js.org/tutorials/intro-to-storybook/react-native/en/get-started/) to set up the Storybook, you can quickly get it running.
Example Repo: [xiongemi/studio-ghibli-search-engine](https://github.com/xiongemi/studio-ghibli-search-engine)
Storybook:
![](/blog/images/2022-04-25/1*bDKKjnrt2D6XIBDnWN1z2Q.avif)
_Storybook View (left: Android, right: iOS)_
## Setup
First, you need to add `@nrwl/storybook` to your existing Nx React Native workspace:
```shell
# npm
npm install @nrwl/storybook --save-dev
# yarn
yarn add --dev @nrwl/storybook
```
Then you need to generate the storybook configuration for your app or lib:
```shell
nx g @nrwl/react-native:storybook-configuration **<your app or lib>**
```
As shown in the example below, 3 folders got generated:
- `.storybook` at workspace root
- `.storybook` in your app or lib
- `storybook` in your app (Note: this folder is for creating the Storybook UI component. It will only be created for the app, you will not see this for lib.)
![](/blog/images/2022-04-25/1*q1sX4VQKdRzQpye6Qcs2Ow.avif)
If you choose to automatically generate `*.stories` file, you should see the default story looks like below:
```tsx {% fileName="loading.stories.tsx" %}
import { storiesOf } from '@storybook/react-native';
import React from 'react';
import { Loading } from './loading';
const props = {};
storiesOf('Loading', module).add('Primary', () => <Loading {...props} />);
```
To gather the stories you created, run the command:
```shell
nx storybook **<your app or lib>**
```
You should see in the terminal saying:
```shell
Writing to <your workspace>/.storybook/story-loader.js
```
In your `<your workspace>/.storybook/story-loader.js`, it should list your stories created under your app or lib similar to the below example:
```javascript {% fileName="story-loader.js" %}
// Auto-generated file created by react-native-storybook-loader
// Do not edit.
//
// https://github.com/elderfo/react-native-storybook-loader.git
function loadStories() {
require('../apps/studio-ghibli-search-engine-mobile/src/app/App.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/film/film.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/results/film-list-item/film-list-item.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/results/people-list-item/people-list-item.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/results/result-list-item/result-list-item.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/search/search.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/shared/film-card/film-card.stories');
require('../apps/studio-ghibli-search-engine-mobile/src/app/shared/loading/loading.stories');
}
const stories = [
'../apps/studio-ghibli-search-engine-mobile/src/app/App.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/film/film.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/results/film-list-item/film-list-item.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/results/people-list-item/people-list-item.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/results/result-list-item/result-list-item.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/search/search.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/shared/film-card/film-card.stories',
'../apps/studio-ghibli-search-engine-mobile/src/app/shared/loading/loading.stories',
];
module.exports = {
loadStories,
stories,
};
```
Also, notice that in your apps main file, the import of the App changed to `storybook/toggle-storybook`:
```typescript
import App from './storybook/toggle-storybook';
```
### View Storybook for App
To view the storybook on the simulator/emulator/device, start the app like you usually do:
```shell
# iOS
nx run-ios <your app>
# Android
nx run-android <your app>
```
In your simulator/emulator/device, open the Debug Menu by entering `d` in terminal. You should see the menu option Toggle Storybook in the Debug Menu:
![](/blog/images/2022-04-25/1*aziO6KSwVhtXWwfyADGbAA.avif)
_Screenshot of Debug menu (left: Android, right: iOS)_
When switching on the toggle, you should see the list of your component stories:
![](/blog/images/2022-04-25/1*KYn3sPUpBU_ewRh2zJ7niQ.avif)
_Storybook View (left: Android, right: iOS)_
### View Storybook for Lib
Note: the storybook can only be viewed inside an app. To view the storybook for lib in the workspace, you need to first set up the storybook for an app in the workspace.
Then run the command:
```shell
nx storybook **<your lib>**
```
This should update the `.storybook/story-loader.js` with stories in your lib.
Then just run the command to start your app, you should see the storybook for your lib.
## Troubleshooting
### Error: Couldnt find a navigation object
If you are using the library `@react-navigation/native` and you are using hooks like `useNavigtion` and `useRoute` inside your component, you are likely to get the below error:
![](/blog/images/2022-04-25/1*oKNqqay19gpvIRgW1QGbkA.avif)
_Render Error for Couldnt find a navigation object_
The easiest way is just to mock this library and create a [decorator](https://storybook.js.org/docs/react/writing-stories/decorators) for it:
```typescript {% fileName="src/storybook/mocks/navigation.tsx" %}
import { NavigationContainer } from '@react-navigation/native';
import React from 'react';
export const NavigationDecorator = (story) => {
return (
<NavigationContainer independent={true}>{story()}</NavigationContainer>
);
};
```
_Mock Navigation Decorator_
Then in your story, you just need to add the above `NavigationDecorator`:
```tsx
import { storiesOf } from '@storybook/react-native';
import { mockFilmEntity } from '@studio-ghibli-search-engine/models';
import React from 'react';
import { NavigationDecorator } from '../../../storybook/mocks/navigation';
import FilmListItem from './film-list-item';
storiesOf('FilmListItem', module)
.addDecorator(NavigationDecorator)
.add('Primary', () => <FilmListItem film={mockFilmEntity} />);
```
_Add NavigationDecoration to the story_
Now, this error should go away and you should see your component in your storybook.
If your component is using the `useRoute` hook and expecting certain routing parameters, then you need to customize the mock `NavigationDecorator` for your component. For example, below is a component that is expecting an id from the route parameters:
```typescript
const route = useRoute<RouteProp<{ params: { id: string } }>>();
const id = route.params?.id;
```
The mock `NavigationDecorator` will become:
```tsx
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import React from 'react';
const NavigationDecorator = (story) => {
const Stack = createNativeStackNavigator();
return (
<NavigationContainer independent={true}>
<Stack.Navigator>
<Stack.Screen
name="MyStorybookScreen"
component={story}
initialParams={{ id: 123 }}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
```
### Error: Could not find “store”
If you are using Redux store and your component is stateful and connected to the store, you are likely to get the below error:
![](/blog/images/2022-04-25/1*T-Lj4PjuAlb_TbpSU5_1PQ.avif)
_Render Error for Could not find “store”_
The simple solution is to mock the store. First, you need to install the library [redux-mock-store](https://github.com/reduxjs/redux-mock-store) and its typing:
```shell
# npm
npm install redux-mock-store @types/redux-mock-store --save-dev# yarn
yarn add redux-mock-store @types/redux-mock-store --dev
```
Similarly, like how you mock up the navigation, you need to mock up the store. The below example mocks the store with the initial root state:
```typescript {% fileName="src/storybook/mocks/store.tsx" %}
import {
initialRootState,
RootState,
} from '@studio-ghibli-search-engine/store';
import React from 'react';
import { Provider as StoreProvider } from 'react-redux';
import configureStore from 'redux-mock-store';
export const StoreDecorator = (story) => {
const mockStore = configureStore<RootState>([]);
const store = mockStore(initialRootState);
return <StoreProvider store={store}>{story()}</StoreProvider>;
};
```
You can add this store decorator to your story:
```tsx {% fileName="people-list-item.stories.tsx" %}
import { storiesOf } from '@storybook/react-native';
import { mockPeopleEntity } from '@studio-ghibli-search-engine/models';
import React from 'react';
import { NavigationDecorator, StoreDecorator } from '../../../storybook/mocks';
import PeopleListItem from './people-list-item';
storiesOf('PeopleListItem', module)
.addDecorator(StoreDecorator)
.addDecorator(NavigationDecorator)
.add('Primary', () => <PeopleListItem people={mockPeopleEntity} />);
```
### Error: Actions must be plain objects
If you use an async action (for example, an action created using `createAsyncThunk` from `@reduxjs/toolkit`), you would likely run into the below error: Actions must be plain objects.
![](/blog/images/2022-04-25/1*sJXG_eFpItyPt7ilyF19fw.avif)
_Render Error for Actions must be plain objects_
Now to resolve this, add thunk to mock store middleware:
```tsx {% fileName="store.tsx" %}
import {
initialRootState,
RootState,
} from '@studio-ghibli-search-engine/store';
import React from 'react';
import { Provider as StoreProvider } from 'react-redux';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
export const StoreDecorator = (story) => {
const mockStore = configureStore<RootState>([thunk]);
const store = mockStore({ ...initialRootState });
return <StoreProvider store={store}>{story()}</StoreProvider>;
};
```
## Conclusion
Here are how to use Storybook with Nx React Native and some common errors you may run into. With Nx React Native, you can quickly view Storybook with a toggle option in Debug Menu. It allows developers to interact and test with components during development.
### Where to go from here?
- [Step by Step Guide on Creating a Monorepo for React Native Apps using Nx](/blog/step-by-step-guide-on-creating-a-monorepo-for-react-native-apps-using-nx)
- [Share code between React Web & React Native Mobile with Nx](/blog/share-code-between-react-web-react-native-mobile-with-nx)
- [join the Nx Official Discord Server](https://go.nx.dev/community)
- [follow Nx on Twitter](https://twitter.com/nxdevtools)
- subscribe to the [Nx Youtube channel](https://youtube.com/c/Nrwl_io)

View File

@ -0,0 +1,307 @@
---
title: 'Nx v14 is out — Here is all you need to know!'
slug: 'nx-v14-is-out-here-is-all-you-need-to-know'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-05-02/1*UAN1p_RMt38_IvB3CRpYTA.png'
tags: [nx, release]
---
A lot happened since we released Nx version 13 back in October 2021. Nx has roughly a 6-month major release cycle and so that time has come again: Im happy to announce the **release of Nx v14**.
Those last 6 months have been incredible and Nx probably got the biggest boost ever in terms of simplicity, features, and speed. We even made Nx more beautiful. Join me to explore some of the biggest highlights and what makes v14 so incredible.
> _Nx is open source, so feel free to browse the_ [_repo_](https://github.com/nrwl/nx) _and_ [_changelog_](https://github.com/nrwl/nx/releases/tag/14.0.0) _by yourself 🙂_
**💡Did you have a chance to watch Nx Conf Lite 2022 last Friday?** Many of the new features have been discussed there, and more. You can watch the [entire stream on Youtube](https://youtu.be/iIZOfV0GFmU). All the single talk videos will be released over the next weeks too, so make sure you subscribe and switch on notifications 🙂: [https://youtube.com/nrwl_io](https://youtube.com/nrwl_io)
## Over 1.6 Million Downloads per week 🎉
We hit a major milestone with Nx v13 when we reached 1 million weekly downloads back in December 2021. Only 3 months later, were already over 1.6 million per week and growing fast!
{% tweet url="https://x.com/victorsavkin/status/1504465520640278533" /%}
Nx also outgrew Lerna in February in weekly downloads. Up until that point, [Lerna](https://lerna.js.org/) was considered the go-to choice when it comes to JS-based monorepos. But just recently, they made it [even more evident](https://github.com/lerna/lerna/pull/3092) that Lerna has been and is [largely unmaintained](https://github.com/lerna/lerna/issues/2703).
![](/blog/images/2022-05-02/0*mPx5PywQEPHBayAO.avif)
We saw that coming and made it easy for people to migrate to Nx.
```shell
npx add-nx-to-monorepo
```
Theres a detailed guide helping with some of the doubts and misconceptions which commonly come up with Lerna users: [https://lerna.js.org/](https://lerna.js.org/)
The future for monorepo tools looks bright as the awareness of monorepos, especially in the JS ecosystem, has grown a lot in recent months. Nx is doing great compared to those tools. But this movement excites us and we are more than ever committed to keep pushing forward and making Nx even better.
![](/blog/images/2022-05-02/0*3nUxgDpXZ82yx6r8.avif)
## Nx Console reaches 1 million installs
While were talking numbers. We just hit another milestone 🎉
{% tweet url="https://x.com/NxDevTools/status/1518620884570820608" /%}
## Nx Core
We made a lot of improvements in Nx core since v13 that can roughly be categorized into: making Nx faster, simpler and improved dev ergonomics. Lets explore some of the highlights there
## Making Nx even faster!
Being as fast as possible is a key design principle in Nx. Back in December we [tweeted about our speed benchmarks](https://twitter.com/victorsavkin/status/1471582667212738562?s=20&t=fZQ82vUXMztNXFRMmuYQTw) and we keep running them against our releases to see how we compare.
Turns out the latest Nx v14 release is considerably faster than Nx v13:
- Nx v13: 1.587 seconds
- Nx v14: 0.259 seconds
You can check and run the benchmarks by yourself: [https://github.com/vsavkin/large-monorepo](https://github.com/vsavkin/large-monorepo)
How can Nx be so fast? One thing we did introduce after v13 and [recently enabled by default](/blog/what-is-new-in-nx-13-10) is the **Nx Daemon**. There is a fixed amount of computation that needs to happen in every workspace and which increases as the workspace grows. In order to still keep operations fast, we can now use the Nx Daemon to precompute a lot of the operations in the background. Then whenever some Nx operation is triggered, they can directly benefit from that.
> **_Running into a performance issue?_** _Try to debug it by using_ `_NX_PERF_LOGGING=true_` _in combination with your Nx command:_ `_NX_PERF_LOGGING=true nx build crew_`_. Alternatively, you can also have Nx generate a_ `_profile.json_` _and import it into Chrome Devtools._ [_Read more about that here_](/troubleshooting/performance-profiling)_._
While a lot of the above improvements help with local development, one of the biggest pain points of having a large monorepo can be CI times. This is where **distributed task execution (DTE)** makes all the difference\*_._\* Nx Clouds DTE understands which commands your CI is running, how many agents are typically being used, and how long a given task typically takes. It leverages that information along with task dependencies to create an execution plan that prioritizes builds of shared libraries first to unblock upstream builds. This results in a more even utilization of CI agents, optimizing the overall running time of your CI.
![](/blog/images/2022-05-02/0*k4ayjIt_OMEedxn-.avif)
Over time, Nx Clouds DTE learns about your workspace, keeping metrics about running times to allow the best possible distribution of a given task with the given amount of agents. This comes with Nx Cloud.
> _Note, if you are a large enterprise, you might want to look into the_ [_Nx Private Cloud_](/enterprise) _offering which allows to self-host Nx Cloud within your own infrastructure._
Also see this example repository with some more information: [https://github.com/vsavkin/interstellar](https://github.com/vsavkin/interstellar)
## Simplifying Nx
Nx follows a modular plugin architecture. There is the core part of Nx which has the main logic around managing the project graph, computation caching, hashing and more. On top of that we have a series of Nx provided plugins for some of the most common frameworks and libraries out there, like [TypeScript/Javascript](/nx-api/js), [Angular](/nx-api/angular), [React](/nx-api/react) & [React Native](/nx-api/react-native), [Next.js](/nx-api/next), [Nest.js](/nx-api/nest), [Node](/nx-api/node) and many more, not to forget about [all the community plugins](/community). We also have a [labs project section](https://github.com/nrwl/nx-labs) which is our incubator for potentially new, natively supported Nx plugins.
This modular structure allows you to just use [Nx core without plugins](/getting-started/intro). An ideal approach if you want to add Nx to an [existing Lerna/Yarn/NPM/PNPM workspace](/recipes/adopting-nx/adding-to-monorepo). With v14 we made it even simpler s.t. now you only have a single `nx` package in your dependencies with the core setup.
From there you can go ahead and add new plugins as you need them, thus gradually enhancing the capabilities of your Nx workspace.
Nx is also able now to directly pick up your `package.json` scripts which are common in NPM/Yarn workspaces. Read more here: [/reference/project-configuration](/reference/project-configuration)
## Terminal Output
Developer experience is highly important to us. And that doesnt stop at the terminal output which is something we developers constantly interact with throughout our entire workday. We, therefore, put a lot of love for the details into how we present our terminal output, improving it in a way to show all completed tasks towards the top, while information about the current progress is shown below
_(here executed by skipping the cache to show some progress running_ 🙂*)*
![](/blog/images/2022-05-02/0*Sodlw6nDI6l9LgsB.avif)
We now even filter out the build of dependent projects. Say you build the `react` project in your workspace which depends on 11 other projects. Nx needs to first incrementally build those 11 dependent projects, which it does now in a very subtle way by just reporting the overall progress at the top of the terminal output, while the main `react` project build output is printed just as normal.
![](/blog/images/2022-05-02/0*jXaiowGZpPMC6PlJ.avif)
Obviously, all errors would be reported properly, and on CI this behavior is disabled by default. If you want to disable it, you can always set `NX_TASKS_RUNNER_DYNAMIC_OUTPUT` to false.
## “Local Plugins” for your Nx Workspace
[Check out our previous release post](/blog/what-is-new-in-nx-13-10) where we went into some of the details on how local plugins work. But in a nutshell, you can now generate a plugin into an existing Nx workspace:
```shell
npx nx generate @nrwl/nx-plugin:plugin --name=workspace-extensions
```
Now normally you would develop it there, and then publish it to npm s.t. others can install it into their Nx workspaces. Since one of our recent versions of Nx, we now also allow you to directly use them in the same Nx workspace, without the need to pre-compile or publish your plugin.
```json
{
"root": "apps/demo",
"sourceRoot": "apps/demo/src",
"projectType": "application",
"targets": {
"mybuild": {
"executor": "@myorg/workspace-extensions:build",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/someoutput"
}
}
}
}
```
This can be a game changer for automating your Nx workspace.
## Automating CI Setup
Ever struggled with setting up CI? Especially in a large monorepo? We got your back now, with the new `--ci` generator that we introduced in Nx v14.
```shell
npx nx generate @nrwl/workspace:ci-workflow --ci=github
```
Or just use [Nx Console](/getting-started/editor-setup), as always.
![](/blog/images/2022-05-02/0*XFXDdGUWc3dF9ZMC.avif)
This sets you up with an automated CI workflow that properly uses the Nx affected command together with the power of [Nx Clouds distributed task execution](/ci/features/distribute-task-execution).
You can also use the `--all` flag when generating a new workspace, for seeing all the available options, including to setup CI.
## nx-cloud record
The [Nx Cloud GitHub app](https://github.com/apps/nx-cloud) is so useful for not having to go to your CircleCI logs and try to find the entry youre searching for. Instead all the executed targets nicely show up as a comment in your PR.
![](/blog/images/2022-05-02/0*4zTea6s4BTMyDToD.avif)
Once you click them, you get a nicely formatted and structured page within Nx Cloud.
![](/blog/images/2022-05-02/0*WnsKJB1ceufeHGPZ.avif)
Until now, you had to have a task that is being executed through Nx Cloud. But what about those workspace utility scripts, like checking the commit format etc. You can now use `nx-cloud record` for those, like
```shell
npx nx-cloud record -- npx nx format:check
```
and they will automatically show up in the Nx Cloud viewer. 🤫 you dont even have to have Nx Cloud installed in the workspace.
## Module Federation for Faster Builds
For many workspaces it is enough to leverage [Nx affected commands](/ci/features/affected), [computation caching](/concepts/how-caching-works) and [distributed task execution](/ci/features/distribute-task-execution).
However, if you have a huge monorepo, this might not be enough. You can add incremental builds and benefit from caching, but still, you might run into the issue of the final linking process taking a long time, which can hardly be optimized further. Unless you can split up your app into smaller pieces. No, were not talking about micro frontends necessarily (more on that in the next section). Rather we can leverage Webpacks Module Federation support.
We added dedicated generators to create a new module federation setup for Angular and React:
```shell
# React
nx g @nrwl/react:host shell --remotes=shop,cart,about
#a Angular
nx g @nrwl/angular:host shell --remotes=shop,cart,about
```
By specifying the `implicitDependencies` in Nx ([see docs](/reference/project-configuration)) Nx knows what the relation between the various apps is, even though there are not direct imports
![](/blog/images/2022-05-02/0*1VDr0oYKNn4j4gWm.avif)
Combining this with the power of Nx Cloud distributed caching, you can now serve your shell project
```shell
npx nx serve shell
```
and all the other remotes are statically served from the cache. Your entire infrastructure is working, without you having to worry about building and serving all of the separate remotes. As you can imagine this speeds up local serve times by an order of magnitude.
If you want to work on one of the remotes, simply explicitly pass their name using `--devRemotes` flag and it will be served just normally with the Webpack dev server, with all the features youre used to.
```shell
npx nx serve shell --devRemotes=cart,shop
```
This can be a game-changer when building huge apps. Stay tuned for more content around this as were really just getting started.
We recommend this approach if you want to speed up local serve and build times, but you still deploy the application as a whole.
Read more on our docs: [/concepts/module-federation/faster-builds-with-module-federation](/concepts/module-federation/faster-builds-with-module-federation)
## Micro Frontend Architecture with Nx
As mentioned in the previous section, Nx v14 comes with out-of-the-box for Webpack Module Federation. The Micro Frontend architecture builds on top of that and adds the ability for independent deployability. While Module Federation enables faster builds by vertically slicing your application into smaller ones, the MFE architecture layers _independent deployments_
on top of federation. Teams should only choose MFEs if they want to deploy their host and remotes on different cadences.
Read more on our docs: [/concepts/module-federation/micro-frontend-architecture](/concepts/module-federation/micro-frontend-architecture)
## Dark mode for Project Graph as well as path tracking
You asked for it, the community responded. [Luís Carvalho](https://github.com/Lcarv20) - a first time contributor - worked together with Nx core team members Philip and Ben to deliver dark mode for the project graph visualization!!
![](/blog/images/2022-05-02/0*TzVbTnDmzgInCw6H.avif)
Also, have you ever wondered whether in your gigantic graph theres a connection between two nodes?
![](/blog/images/2022-05-02/0*eMk2cAwrdHmaK07h.avif)
Now you can easily find out! Just click on a node and hit the “Start” button.
![](/blog/images/2022-05-02/0*gDnkyfnnAHy2P0Z8.avif)
Then click the target node youre interested in and hit “End”.
![](/blog/images/2022-05-02/0*BMoc7FuUD94GzOXO.avif)
The project graph now renders the path between those nodes.
![](/blog/images/2022-05-02/0*I2E5CvnLb-C8z95L.avif)
And by clicking on the edges you can even get a more detailed output of why the connection exists in the first place 🤯
![](/blog/images/2022-05-02/0*EnPbSRFUD3KeOH4w.avif)
Oh wait, you didnt want the shortest path? Theres a button for showing all possible paths too 😉
![](/blog/images/2022-05-02/0*OlhUXFMhEwshLoTV.avif)
## JavaScript & TypeScript library support
In version 13.4 we released a brand new dedicated package for developing pure JavaScript/TypeScript packages: `@nrwl/js`
We kept improving it, adding SWC support (including an easy migration between TSC → SWC using an Nx generator) and were currently looking into automated publishing support.
Read all the details on our docs: [/getting-started/intro](/getting-started/intro)
## React
Nx v14 ships with React 18 support for React DOM and React Native. The latter has seen some drastic improvements since Nx v13, adding [guides on how to create a monorepo for React Native](/blog/step-by-step-guide-on-creating-a-monorepo-for-react-native-apps-using-nx) apps with Nx as well as how to [share code between a React Web and React Native app](/blog/share-code-between-react-web-react-native-mobile-with-nx). We also added Storybook support to React Native. Read all about that in [our recent blog post](/blog/use-storybook-with-nx-react-native).
In addition to that, Expo and Expo Application Service support has been added which has lead already to some drastic speed improvements with some of our clients.
Finally, it is the first version which ships the built-in module federation support for React as weve mentioned a couple of sections above. Check out the React package docs page and search for the `host` and `remote` generator: [/nx-api/react](/nx-api/react)
## Angular
There have been a lot of highlights for the Nx Angular plugin since v13. Here are some:
- Support and migrations for Angular 13 (Angular v14 coming soon. We will release that as a minor upgrade in Nx once the Angular team releases v14)
- Tailwind CSS support (generators, added support to library executors). Read [our blog detailed post](/blog/set-up-tailwind-css-with-angular-in-an-nx-workspace).
- Single Component Application Modules (SCAM) generators for components, directives and pipes ([see our docs](/nx-api/angular))
- Improved Angular CLI to Nx migration support. We invested quite some time refactoring our current migration support from the Angular CLI which not only will allow us to implement more migration scenarios in the future but it also provides better error messages and hints during the migration process. This also allowed us to add support for multi-project Angular CLI workspaces which can now be seamlessly migrated. Multi-application Angular CLI workspace support will be added soon.
Finally, similar to React also Angular gets built-in support for Webpack Module federation and hence also Microfrontends within Nx. See the sections about Module Federation and Microservices for more info and links to the docs.
## Improved docs
Docs are hard! But we keep investing and a lot of work has gone into making docs more organized and even more interactive.
{% tweet url="https://twitter.com/bencabanes/status/1509641445086535687" /%}
## Theres more
Check out our previous release blog posts for all the details:
- [Single File Monorepo Config, Custom Workspace Presets, Improved Tailwind Support, and more in Nx 13.4!](/blog/single-file-monorepo-config-custom-workspace-presets-improved-tailwind-support-and-more-in-nx-13)
- [New Terminal Output & Performance Improvements in v13.5](/blog/new-terminal-output-performance-improvements-in-nx-13-5)
- [Whats new in Nx v13.10?](/blog/what-is-new-in-nx-13-10)
## How to Update Nx
Updating Nx is done with the following command, and will update your Nx workspace dependencies and code to the latest version:
```shell
npx nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
npx nx migrate --run-migrations
```
## Exciting?
We already started working on v15. You can [find the roadmap on our GitHub repository](https://github.com/nrwl/nx/discussions/9716). There are some exciting things coming up, like
- “Negative” Configuration
- React Server Side Rendering and Server Components support
- React Native + Detox
- Cypress v10 migration and Cypess Component Testing
- ...
Make sure you dont miss anything by
- Following us [on Twitter](https://twitter.com/NxDevTools), and
- Subscribe to the [YouTube Channel](https://youtube.com/nrwl_io?sub_confirmation=1) for more information on [Angular](https://angular.io/), [React](https://reactjs.org/), Nx, and more!
- Subscribing to [our newsletter](https://go.nx.dev/nx-newsletter)!

View File

@ -0,0 +1,56 @@
---
title: 'Lerna is dead — Long Live Lerna'
slug: 'lerna-is-dead-long-live-lerna'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-05-11/1*__gtsrJ-tMDZf9bvDLVSjQ.png'
tags: [nx]
---
If youre in a hurry, heres the **TL;DR:**
> _We,_ [_Nrwl_](/company)_, the company behind Nx, are taking over the stewardship of Lerna.js, the popular JS monorepo tool._ [_Heres the official announcement on the Lerna repo_](https://github.com/lerna/lerna/issues/3121)_. We are thrilled and committed to helping the Lerna community move forward!_
## Who is Nrwl?
We (Nrwl) are the company behind Nx ([GitHub](https://github.com/nrwl/nx)) and we have been founded by two ex-Googlers and Angular core team members [Jeff Cross](https://twitter.com/jeffbcross) and [Victor Savkin](https://twitter.com/victorsavkin). Experiencing a large-scale monorepo in action at Google, gave them a lot of insights into the advantages and productivity gains for software teams as well as the features and tooling support that is required to make monorepos work, especially at a large scale. When they left Google, they decided to bring such a tool to the masses, but with a clear goal of
- building it in the open as an open-source product and
- making it approachable and easy to use by focusing on great DX
This is when Nx started.
We think we are the best fit for helping the Lerna community continue and thrive because we have a good combination of real-world experience with open source community work. As part of Nrwl, we work with some of the worlds biggest companies, helping them improve productivity and ship great quality software through monorepos. In addition, Jeff and Victor have a lot of knowledge of managing a big open source project such as Angular when they were at Google and obviously at Nrwl from managing Nx as an open-source project with its quickly growing community.
Long story short, Nrwl ❤️ open source and community work, and we are thrilled to work with the Lerna community!
## Whats the story about Lerna being dead?
_(Spoiler: It is not dead, we took over stewardship_ 😀*. But apart from that, heres the whole story)*
- August 2020 — Issue is being opened [mentioning that Lerna is largely unmaintained](https://github.com/lerna/lerna/issues/2703)
- April 2022 — A [PR gets merged](https://github.com/lerna/lerna/pull/3092) that properly highlights the fact of Lerna being unmaintained at the very top of the repository README. This made the “Lerna is dead” discussions flare up again.
- May 2022 — Lerna got resurrected: Nrwl takes over
While that last PR didnt really change the fact that Lerna has been in that state for the past years already, it just made it more apparent and also how many still rely on Lerna today.
And this is not to blame its contributors at all. They did an amazing job. However, Open Source can be a tough place, especially if it is not backed by a large community and/or company that helps make the work sustainable in the long run. Taking the weight of maintaining such a widely used tool, and then mostly for free, is a huge one. Burnout is real folks, so take care. And weve had lots of such open-source examples in the past years.
## Nrwl is taking over: now what?
Lerna has definitely pioneered the JS monorepo space, however, the tooling space has progressed a lot in recent years. Some of its features are now baked into NPM, YARN, PNPM, and Lerna [lacks many other important monorepo features](https://monorepo.tools/#tools-review) such as computation caching to mention one example.
Nx can fill in many of these gaps. When the first discussions about Lerna being unmaintained came up in 2020, we implemented a set of features, allowing for easy migration from [Lerna/NPM/Yarn/PNPM workspaces to Nx](/recipes/adopting-nx/adding-to-monorepo). In addition, some recent [improvements in Nx](/blog/nx-v14-is-out-here-is-all-you-need-to-know) make this even easier, allowing it to basically co-exist in any of these workspaces. This can be done for instance by leveraging [Nxs powerful task scheduling capabilities](/getting-started/intro) while still continuing on relying on Lernas publishing process. Maintaining now both projects, Lerna & Nx, puts us in the unique position of allowing us to work on some seamless integration between the two.
With Nx, we are known to have a clear roadmap shared with the community of what our next 6 months focus will be (heres an [example of our roadmap for v15](https://github.com/nrwl/nx/discussions/9716)). As we get our hands dirty on Lernas codebase in the coming weeks, we are going to define a set of action items, prioritize them and elaborate a proper roadmap as well, which we will share with the community as soon as we have a more concrete plan. Since we know many organizations still depend on Lerna or may not be able to migrate away soon, some of our immediate to mid-term actions will be to **provide critical bug fixes and security updates to the project** and regularly release those to NPM.
## Stay tuned for more!
We think Lernas and Nxs future is bright and we are excited to help move the monorepo space forward, more than ever before!
Make sure you dont miss anything by
- Following us [on Twitter](https://twitter.com/NxDevTools)
- Subscribing to our [YouTube Channel](https://youtube.com/nrwl_io?sub_confirmation=1)
- Subscribing to [our newsletter](https://go.nx.dev/nx-newsletter)!
✌️

View File

@ -0,0 +1,101 @@
---
title: 'How Lerna just got 10x faster!'
slug: 'lerna-used-to-walk-now-it-can-fly'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-05-25/1*WPGHapKqT3IguWjeN5UgWg.png'
tags: [nx]
---
**_TL;DR:_** _We released a new beta version of Lerna and it happens that it is now 5.3 times faster than Turbo 👀…by turning on a flag. Keep reading to learn more._
> _ICYMI: A couple of weeks ago we (Nrwl) announced that we take over stewardship of Lerna. Read all about it in our_ [_recent blog post_](/blog/lerna-is-dead-long-live-lerna)_.
> We also just released Lerna v5 as a first maintenance release:_ [_Read more here_](https://github.com/lerna/lerna/releases/tag/v5.0.0)_._
For folks that want to migrate to Nx, we always had a dedicated [Nx and Lerna](/recipes/adopting-nx) docs page that shows you how you can easily integrate the two. However, we felt we could do better and allow you to get all the speed benefits that come from Nxs task scheduling abilities, without needing to change nearly anything in your Lerna workspace.
And it got fast, like really fast!!
## Want the video walkthrough of Lerna 5?
Here you go
{% youtube src="https://www.youtube.com/watch?v=WgO5iG57jeQ" /%}
## How fast is it?
We just published Lerna v5.1 which introduces a `useNx` flag. Adding that makes Lerna to be on par with Nx in terms of speed, and is significantly faster than other tools.
Comparing Lerna with and without the flag isnt really an apples-to-apples comparison because one comes with caching abilities, while before, Lerna didnt have that at all. But just to give you an idea: enabling Nx on your existing Lerna workspace can **speed it up in the range of 210 times**, depending on the repo setup.
But lets do some more real “apples-to-apples” comparison of Lernas speed with `useNx` enabled. For benchmarking Nx we have set up a repo in the past which we regularly use to measure the speed of new Nx releases with other similar tools on the market such as [Lage](https://microsoft.github.io/lage/) and [Turborepo](https://turborepo.org/): [https://github.com/vsavkin/large-monorepo](https://github.com/vsavkin/large-monorepo). We now added Lerna+Nx (Lerna with `useNx` enabled) to that repo to measure the impact.
Heres a gif of running the benchmark of Lerna+Nx and Turborepo:
![](/blog/images/2022-05-25/1*MrhEU4wPZlwp4dbKsj876g.avif)
**Lerna+Nx is 5.3 times faster** than Turborepo 🚀.
As always, you can reproduce the benchmark by yourself by going to the [benchmark repo](https://github.com/vsavkin/large-monorepo). The readme includes all the details on how to run it on your own machine. We verified it in detail, but if for some reason we got something wrong, please reach out!
## What do I need to do to upgrade?
First of all, upgrade to Lerna v5.1. That release comes with the ability to delegate task running to Nx. Next you need to add Nx as a dependency: `npm i nx --save-dev`
Finally, add the following to your `lerna.json`.
```json5 {% fileName="lerna.json" %}
{
...
"useNx": true
}
```
Thats mostly it. You can continue using the usual Lerna commands, but at this point Lerna would delegate its operations to Nx underneath.
To get more out of it, you might want to create a small `nx.json` file (or run `npx nx init` to generate one) for going into some more details on configuring the cacheable operations:
```json5 {% fileName="nx.json" %}
{
extends: 'nx/presets/npm.json',
tasksRunnerOptions: {
default: {
runner: 'nx/tasks-runners/default',
options: {
cacheableOperations: ['build'],
},
},
},
}
```
Note that `useNx` is opt-in and set to `false` by default. Also, if someone is worried about the license, Nx has been open source from the very beginning, using the MIT license.
## How does this work under the hood?
So how does this work on a technical level. So far Lerna (`lerna run` to be more specific) has been delegating the task scheduling to `p-map` or `p-queue`. Meanwhile though, the industry has advanced and tools like Nx are much more powerful and efficient in their task orchestration and in addition also support caching.
With the change we made in Lerna 5.1 we are adding Nx (MIT licensed) as a third option in addition to the already existing `p-map` and `p-queue`. By having `nx` installed and configured (as mentioned in the previous section), Lerna can now delegate its `lerna run` command to Nx directly. All of this is done in a backwards-compatible way: every `lerna run` command will work but will be significantly faster and can optionally even be distributed across multiple machines without any config (more about that in the next section).
## Whats more?
By having Nx integrated, you not just get faster builds but also some other Nxs features for free!
[**Nx Project graph**](/features/explore-graph) — By running `npx nx graph` you get the visualization of the graph. You can interactively explore what your workspace looks like and the relationships between the packages. We actually used this same graph on the Lerna repo itself, which helped us to get a better understanding of how the repo is structured when we took over the maintenance. Heres an example of filtering the lerna packages to understand what `@lerna/exec` is about and how it relates to other packages in the repo.
![](/blog/images/2022-05-25/0*uW4TaZQy7smwCDEj.avif)
**Distributed caching** — Right now when you enable `useNx` in your existing Lerna repo, you will get local caching, meaning the cache sits in a local folder on your machine. You get much more value out of it when you start distributing and sharing it with your teammates but especially in CI. This can be done by adding Nx Cloud, which comes with a no-credit card, 500 hours free / month offer which is more than what most workspaces need. Adding that is easy and can be done by adding `@nrwl/nx-cloud` to your root-level `package.json` and then by running:
```shell
npx nx connect-to-nx-cloud
```
**Distributed task execution** — Distribution of the cache is one thing, but the real speed improvements come from also [distributing the task execution](/ci/features/distribute-task-execution) to speed up your CI. Having the Nx project graph and as well as the cache and historical data about previous runs, Nx Cloud DTE is able to maximize the CI agent utilization by evenly distributing tasks based on their (historical) duration as well as based on their topological order. In addition, the DTE process makes sure to properly move cached assets between the agents. Setting up DTE is straightforward, read more on our [Nx Cloud docs](/ci/features/distribute-task-execution). Hint: we also have a CI generator in Nx (you need the `@nrwl/workspace` package) that allows you to generate your CI setup using a single command: `npx nx generate @nrwl/workspace:ci-workflow --ci=github`
**Lerna roadmap** — We also just published a roadmap of the next steps for the Lerna repository. Check it out here: [https://github.com/lerna/lerna/discussions/3140](https://github.com/lerna/lerna/discussions/3140)
## Conclusion
This is the first beta which we are trying out on some projects already. We arent worried about task orchestration, caching or distribution — all of those are done by Nx, which has been around for 5 years and is solid. We are trying to see if there is something in the integration that is confusing. We hope to release s stable version by mid-June.
Please have a look, upgrade your repo and [open an issue](https://github.com/lerna/lerna/issues) if you run into some weird behavior with the new `useNx` enabled. But not only that, feel free to ping us on the [@NxDevTools](https://twitter.com/nxdevtools) account with your success stories too. We'd love to hear 😃.

View File

@ -0,0 +1,747 @@
---
title: 'Setup a Monorepo with PNPM workspaces and speed it up with Nx!'
slug: 'setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-07-14/1*ABrBjQPg4SrYzFQQXFxY-Q.png'
tags: [nx, tutorial]
---
In this article were going to have a deep dive into setting up a new monorepo using [PNPM workspaces](https://pnpm.io/workspaces) that hosts a Remix application as well as a React-based library. We will learn how to run commands with PNPM, how to run them in parallel and finally were going to add Nx for a more sophisticated task scheduling, including command caching and more.
**Important:** If you are already familiar with the setup and configuration of a new PNPM workspace, feel free to skip to the part where we add Nx later in the article.
**Prefer a video walkthrough?**
{% youtube src="https://www.youtube.com/watch?v=ngdoUQBvAjo" /%}
### Table of Contents
· [Initialize a new PNPM workspace](#initialize-a-new-pnpm-workspace)
· [Setting up the Monorepo structure](#setting-up-the-monorepo-structure)
· [Adding a Remix application](#adding-a-remix-application)
· [Create a Shared UI library](#create-a-shared-ui-library)
· [Consuming our shared-ui package from the Remix app](#consuming-our-sharedui-package-from-the-remix-app)
· [Running commands with PNPM](#running-commands-with-pnpm)
· [Speeding up with Nx](#speeding-up-with-nx)
· [Installing Nx](#installing-nx)
· [Running tasks with Nx](#running-tasks-with-nx)
· [Configure Caching](#configure-caching)
· [Fine-tuning the caching](#finetuning-the-caching)
· [Reusing Cache Input Globs](#reusing-cache-input-globs)
· [Defining task dependencies (aka build pipeline)](#defining-task-dependencies-aka-build-pipeline)
· [Running just what changed](#running-just-what-changed)
· [Additional features](#additional-features)
· [Dynamic Terminal Output](#dynamic-terminal-output)
· [Project Graph Visualization](#project-graph-visualization)
· [Conclusion](#conclusion)
## Initialize a new PNPM workspace
To get started, lets make sure you have PNPM installed. The [official docs have an installation page](https://pnpm.io/installation) with detailed instructions. I also recommend using something like [Volta](https://volta.sh/) in particular if you have to deal with multiple different versions of NPM/PNPM and node versions.
Lets create a new folder named `pnpm-mono`, cd into it and then run `pnpm init` to generate a top-level `package.json`. This will be the root `package.json` for our PNPM monorepo.
```shell
mkdir pnpm-mono
cd pnpm-mono
pnpm init
```
It is probably also handy to initialize a new Git repository such that we can commit and backup things as we progress in the setup:
```shell
git init
```
At this point lets also create a `.gitignore` file to immediately exclude things like `node_modules` and common build output folders.
```.gitignore {% fileName=".gitignore" %}
node_modules
dist
build
```
## Setting up the Monorepo structure
The structure of a monorepo might vary depending on what you plan to use it for. There are generally two kinds of monorepo:
- **package centric** repositories which are used for developing and publishing a cohesive set of reusable packages. This is a common setup in the open source world and can be seen in repositories such as [Angular](https://github.com/angular/angular), [React](https://github.com/facebook/react), [Vue](https://github.com/vuejs/vue) and many others. Those repos are characterized by most commonly having a `packages` folder and which are then commonly published to some public registry such as [NPM](https://npmjs.com/).
- **app centric** repositories which are used mainly for developing applications and products. This is a common setup in companies. Such repos are characterized in having an `apps` and `packages` or `libs` folder, where the `apps` folder contains the buildable and deployable applications, while the `packages` or `libs` folder contains libraries that are specific to one or multiple applications that are being developed within the monorepo. You can still also publish some of these libs to a public registry.
In this article were going to use the “app centric” approach, to demonstrate how we can have an application that consumes packages from within the monorepo.
Create an `apps` and `packages` folder within `pnpm-mono`:
```
mkdir apps packages
```
Now lets configure PNPM to properly recognize the monorepo workspace. Basically we have to create a `pnpm-workspace.yaml` file at the root of the repository, defining our monorepo structure:
```yaml {% fileName="pnpm-workspace.yaml" %}
packages:
# executable/launchable applications
- 'apps/*'
# all packages in subdirs of packages/ and components/
- 'packages/*'
```
## Adding a Remix application
We should now be ready to add our first application. For this example I picked [Remix](https://remix.run/) but you can really host any type of application in here, it wont really matter.
> _Info: We use the normal_ [_Remix installation & setup procedure_](https://remix.run/docs/en/v1) _here which you can find on their docs page._
Since we want to have the app within the `apps` folder, we need to `cd` into it:
```shell
cd apps
npx create-remix@latest
```
You will be asked for an app name. Lets just go with “my-remix-app” which well be using for the rest of this article. Obviously feel free to use a different one. In addition, the Remix setup process is also going to ask you a couple of questions that customize the exact setup. The particular options are not really relevant for our article here, so feel free to choose whatever best suits your needs.
You should have now a Remix app, within the `apps/my-remix-app` folder or whatever name you chose. Remix has already a `package.json` with corresponding scripts configured:
```json
{
"private": true,
"sideEffects": false,
"scripts": {
"build": "remix build",
"dev": "remix dev",
"start": "remix-serve build"
},
...
}
```
Usually, in a monorepo you want to run commands from the root of the repository to not have to constantly switch between folders. PNPM workspaces have a way to do that, by passing a `filter` argument, like:
```shell
pnpm --filter <package-name> <command>
```
Now it happens (at the writing of this article) that Remixs default `package.json` doesn't have a `name` property defined which PNPM wants to run the package. So let's define one in the `apps/my-remix-app/package.json`:
```json
{
"name": "my-remix-app",
"private": true,
"sideEffects": false,
...
}
```
You should now be able to serve your Remix app in dev-mode by using:
```shell
pnpm --filter my-remix-app dev
```
![](/blog/images/2022-07-14/1*QXjUpc402IKnVSwJC9cw9g.avif)
## Create a Shared UI library
Now that we have our app set up, lets create a library package that can be consumed by our application.
```shell
cd packages
mkdir shared-ui
```
Next, lets create a `package.json` with the following content (you can also use `pnpm init` and adjust it):
```json
{
"private": true,
"name": "shared-ui",
"description": "Shared UI components",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {}
}
```
Note, we declare it as `private` because we don't want to publish it to NPM or somewhere else, but rather just reference and use it locally within our workspace. I also removed the `version` property since it is not used.
As the technology stack Ive chosen to go with [React](https://reactjs.org/) (so we can import it in Remix) and [TypeScript](https://www.typescriptlang.org/) (because it can almost be considered a standard nowadays). Lets install these dependencies from the root of the workspace:
```shell
pnpm add --filter shared-ui react
pnpm add --filter shared-ui typescript -D
```
By passing `--filter shared-ui` to the installation command, we install these NPM packages locally to the `shared-ui` library.
> _Info: Be aware that this might potentially cause version conflicts if the React/TypeScript version used by the library package and the consumer (e.g. our app) differs. Adopting a_ [_single version policy_](https://opensource.google/documentation/reference/thirdparty/oneversion)_, where you move the packages to the root of the monoreopo, is a possible solution for that._
Our first component will be a very simple `Button` component. So let's create one:
```tsx {% fileName="packages/shared-ui/Button.tsx" %}
export function Button(props: any) {
return <button onClick={() => props.onClick()}>{props.children}</button>;
}
export default Button;
```
We also want to have a public API where we export components to be used outside of our `shared-ui` package:
```tsx {% fileName="packages/shared-ui/index.tsx" %}
export * from './Button';
```
For sake of simplicity we just use the TypeScript compiler to compile our package. We could have some more sophisticated setup for bundling multiple files together etc with something like [Rollup](https://rollupjs.org/guide/en/) or whatever you prefer using, but thats outside the scope of this article.
To create the desired compilation output create a `packages/shared-ui/tsconfig.json` file with the following configuration.
```json
{
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"outDir": "./dist"
},
"include": ["."],
"exclude": ["dist", "node_modules", "**/*.spec.ts"]
}
```
> _In a monorepo it is good practice to extract the common config part into a higher-level config (e.g. at the root) and then extend it here in the various projects. This to avoid a lot of duplication across the various monorepo packages. For the sake of simplicity I kept it all in one place here._
As you can see the `outDir` points to a package-local `dist` folder. So we should add a main entry point in the `shared-ui` package's `package.json`:
```json
{
"private": true,
"name": "shared-ui",
"main": "dist/index.js"
}
```
Finally, the actual build consists of deleting some residual folders from the previous output and then invoking the TypeScript compiler (`tsc`). Here's the complete `packages/shared-ui/package.json` file:
```json
{
"private": true,
"name": "shared-ui",
"description": "Shared UI components",
"main": "dist/index.js",
"scripts": {
"build": "rm -rf dist && tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^17.0.2"
},
"devDependencies": {
"typescript": "^4.6.4"
}
}
```
Use the following command to run the build from the root of the PNPM workspace:
```shell
pnpm --filter shared-ui build
```
If the build succeeds, you should see the compiled output in the `packages/shared-ui/dist` folder.
## Consuming our shared-ui package from the Remix app
Our `shared-ui` library is ready so we can use it in the Remix application hosted within the `apps` folder of our repository. We can either manually add the dependency to Remix's `package.json` or use PNPM to add it:
```shell
pnpm add shared-ui --filter my-remix-app --workspace
```
This adds it to the dependency in the `apps/my-remix-app/package.json`:
```json
{
"name": "my-remix-app",
"private": true,
"sideEffects": false,
...
"dependencies": {
...
"shared-ui": "workspace:*"
},
...
}
```
`workspace:*` denotes that the package is resolved locally in the workspace, rather than from some remote registry (such as [NPM](https://npmjs.com/)). The `*` simply indicates that we want to depend on the latest version of it, rather than a specific one. Using a specific version really just makes sense if you're using external NPM packages.
To use our `Button` component we now import it from some Remix route. Replace the content of `apps/my-remix-app/app/routes/index.tsx` with the following:
```tsx {% fileName="apps/my-remix-app/app/routes/index.tsx" %}
import { Button } from 'shared-ui';
export default function Index() {
return (
<div>
<Button onClick={() => console.log('clicked')}>Click me</Button>
</div>
);
}
```
If you now run the Remix app again you should see the button being rendered.
```shell
pnpm --filter my-remix-app dev
```
If you happen to get the following error, then it is because you need to build `shared-ui` first
```shell
Error: Cannot find module '/Users/juri/nrwl/content/pnpm-demos/pnpm-mono/apps/my-remix-app/node_modules/shared-ui/dist/index.js'. Please verify that the package.json has a valid "main" entry
at tryPackage (node:internal/modules/cjs/loader:353:19)
at Function.Module._findPath (node:internal/modules/cjs/loader:566:18)
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/Users/juri/nrwl/content/pnpm-demos/pnpm-mono/apps/my-remix-app/app/routes/index.tsx:1:24)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
```
To build that, run
```shell
pnpm --filter shared-ui build
```
Why? This is due to the symlinks PNPM creates in order to be able to reference and resolve local dependencies. By adding `shared-ui: "workspace:*"` to Remix's `package.json` you instruct PNPM to add a symlink to Remix's `node_modules` folder.
![](/blog/images/2022-07-14/1*MYLr1kb3cscQo7JW9_Jg8Q.avif)
_PNPM creates a symlink in the local node_modules folder to be able to import local packages_
## Running commands with PNPM
PNPM comes with handy features to run commands across the monorepo workspace. We have already seen how to scope commands on single packages using the `--filter` :
```shell
pnpm --filter my-remix-app dev
```
You can also run a command recursively on all the packages in the workspace using the `-r` flag. Imagine for instance running the build for all projects.
```shell
pnpm run -r buildScope: 2 of 3 workspace projects
packages/shared-ui build$ rm -rf dist && tsc
└─ Done in 603ms
apps/my-remix-app build$ remix build
│ Building Remix app in production mode...
│ The path "shared-ui" is imported in app/routes/index.tsx but shared-ui is not listed in your package.json
│ Built in 156ms
└─ Done in 547ms
```
Similarly you can parallelize the run by using `--parallel`
```shell
pnpm run --parallel -r buildScope: 2 of 3 workspace projects
apps/my-remix-app build$ remix build
packages/shared-ui build$ rm -rf dist && tsc
apps/my-remix-app build: Building Remix app in production mode...
apps/my-remix-app build: The path "shared-ui" is imported in app/routes/index.tsx but shared-ui is not listed in your package.json dependencies. Did you forget to install it?
apps/my-remix-app build: Built in 176ms
apps/my-remix-app build: Done
packages/shared-ui build: Done
```
## Speeding up with Nx
PNPM workspaces come with some basic facilities for running tasks on the monorepo packages, even in parallel. As the monorepo grows, you might want to have a more sophisticated approach that allows to
- run tasks on only the packages that changed
- advanced caching based on file contents to not run anything that has already been computed previously
- remote distributed caching to speed up your CI
This is exactly where Nx can help. It is optimized for monorepo scenarios and comes with an advanced task scheduling mechanism. We still rely on the package installation and package linking mechanism that PNPM workspaces provide us, but use Nx instead to run our tasks in the most efficient way.
## Installing Nx
Since Nx will be used for running operations across the entire monorepo workspace were going to install it at the root level `package.json`.
```shell
pnpm add nx -D -w
```
Thats it.
## Running tasks with Nx
Nx uses the following form to run your commands:
```shell
npx nx <target> <project>
```
`target` is the NPM script in this specific case you want to execute.
Lets try to run the build for our `shared-ui` package using the following command:
```shell
npx nx build shared-ui
```
This produces the following output
```shell
nx run shared-ui:build
shared-ui@ build /Users/juri/nrwl/content/pnpm-demos/pnpm-mono/packages/shared-ui
rm -rf dist && tsc
NX Successfully ran target build for project shared-ui (1s)
```
Nx automatically finds `shared-ui` and runs the `build` script defined in `packages/shared-ui/package.json`.
Similarly, to launch our Remix app, run `npx nx dev my-remix-app`.
We can also run commands in parallel across the projects with:
```shell
npx nx run-many --target=build --all
✔ nx run my-remix-app:build (1s)
✔ nx run shared-ui:build (1s)
NX Successfully ran target build for 2 projects (1s)
```
Or selectively specify projects with
```shell
npx nx run-many --target=build --projects=my-remix-app,shared-ui
✔ nx run my-remix-app:build (1s)
✔ nx run shared-ui:build (1s)
NX Successfully ran target build for 2 projects (1s)
```
> _Note Im prefixing the commands with_ `_npx_` _which runs the Nx executable in the_ `_node_modules_` _folder. In this way I don't have to install_ `_nx_` _globally. If you prefer doing that, feel free to do so._
## Configure Caching
One of the main benefits of adding Nx to our PNPM workspace is **speed via caching**. [Computation caching](/concepts/how-caching-works) is a feature where different inputs (source files, env variables, command flags, etc.) are collected and a hash computed & stored in a local folder. Next time you run the command again, Nx looks for a matching hash, and if it finds one it just restores it. This includes restoring the terminal output as well as build artifacts (e.g. JS files in `dist` folders).
Not all operations are cacheable, only side-effect free ones are. For example, if you run an operation with the same inputs, it reliably always has to produce the same output. If as part of that operation you call some API for instance, it wouldnt be cacheable because the result of that API might vary given the same input parameters.
In order to enable caching, lets configure our cacheable operations. To do that we create an `nx.json` at the root of our workspace with the following content
```json {% fileName="nx.json" %}
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test"]
}
}
}
}
```
Note the `cacheableOperations` array where we specify `build` and `test` . You can add more such as linting.
Having enabled this, if we now run our Remix app build the first time it is executed just as normal and well see it takes roughly 1s.
```shell
npx nx build my-remix-app
nx run my-remix-app:build
my-remix-app@ build /Users/juri/nrwl/content/pnpm-demos/pnpm-mono/apps/my-remix-app
remix buildBuilding Remix app in production mode...
The path "shared-ui" is imported in app/routes/index.tsx but shared-ui is not listed in your package.json dependencies. Did you forget to install it?
Built in 163ms
NX Successfully ran target build for project my-remix-app (1s)
```
If you re-run the same command, it will now be pulled out of the cache and take only a few milliseconds.
```shell
npx nx build my-remix-app> nx run my-remix-app:build [existing outputs match the cache, left as is]
my-remix-app@ build /Users/juri/nrwl/content/pnpm-demos/pnpm-mono/apps/my-remix-app
remix buildBuilding Remix app in production mode...
The path "shared-ui" is imported in app/routes/index.tsx but shared-ui is not listed in your package.json dependencies. Did you forget to install it?
Built in 163ms
NX Successfully ran target build for project my-remix-app (9ms)
Nx read the output from the cache instead of running the command for 1 out of 1 tasks.
```
You can also see that from the terminal output mentioning “existing outputs match the cache, left as is” as well as at the end “Nx read the output from the cache instead of running the command for 1 out of 1 tasks.”
Having caching in place can drastically improve command execution times. It also gets even more useful if the cache is remotely distributed so that it can be shared with CI as well as other developer machines. In the case of Nx this can be done by enabling [Nx Cloud](/ci/features/remote-cache), which comes with 500 hours saved/month for free (no credit card required) and unlimited hours for open source projects.
## Fine-tuning the caching
By default the caching mechanism takes [all project-level files as an input](/concepts/how-caching-works). We might want to distinguish though which files are being considered based on the target that we execute. Example: you might not want to invalidate the cache for the `build` task if only spec files for unit testing got changed.
To illustrate this on our example, run `npx nx build my-remix-app` twice, such that the caching gets activated. Next, change the `README.md` of the Remix project (`apps/my-remix-app/README.md`). If you re-run the Remix app build the cache will be invalidated due to the change of the README file. This might definitely not be a desirable operation.
We can fine-tune the caching by adding a `targetDefaults` node in the `nx.json` and define that the default `input` for the `build` target should exclude `*.md` files.
```json
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test"]
}
}
},
"targetDefaults": {
"build": {
"inputs": ["!{projectRoot}/**/*.md"]
}
}
}
```
With this change, MD files would not be considered as part of the cache input whenever you run the `build` task.
> _Note that all path globs are_ **_relative to the root of the workspace_**_. This avoids confusion as the inputs could also be defined at the project level in the_ `_package.json_` _(_[_more here_](/reference/project-configuration)_). You can use the interpolation variables_ `_{projectRoot}_` _and_ `_{workspaceRoot}_` _do distinguish whether the path should be targeting the project specific files or workspace level files._
## Reusing Cache Input Globs
You can also go a step further as you might re-use this glob for excluding markdown files also for a hypothetical `test` target. You can do so by extracting the glob into a `namedInputs` property:
```json
{
"tasksRunnerOptions": {
...
},
"namedInputs": {
"noMarkdown": ["!{projectRoot}/**/*.md"]
},
"targetDefaults": {
"build": {
"inputs": ["noMarkdown", "^noMarkdown"]
},
"test": {
"inputs": ["noMarkdown", "^noMarkdown"]
}
}
}
```
By adding `^` in front of the `namedInput` we indicate that this should also apply for changes in any dependencies of the project.
## Defining task dependencies (aka build pipeline)
We have seen previously that when running our Remix dev server, but not having compiled the dependent `shared-ui` package first, we got an error when running our Remix app.
```
Error: Cannot find module '/Users/juri/nrwl/content/pnpm-demos/pnpm-mono/apps/my-remix-app/node_modules/shared-ui/dist/index.js'. Please verify that the package.json has a valid "main" entry
at tryPackage (node:internal/modules/cjs/loader:353:19)
at Function.Module._findPath (node:internal/modules/cjs/loader:566:18)
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/Users/juri/nrwl/content/pnpm-demos/pnpm-mono/apps/my-remix-app/app/routes/index.tsx:1:24)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
```
To fix it, we had to manually build `shared-ui` first. Normally you want to avoid this, which is exactly why Nx comes with a `targetDefaults` definition (often also denoted as the "build pipeline").
We can define such task dependencies in `nx.json` at the root of the workspace in the `targetDefaults` property.
As the first dependency we want to define that whenever we run the `build` target on a project, all the `build` targets of its dependent projects should be executed first. We can express that by adding an additional `dependsOn` property to the `build` task definition:
```json
{
"tasksRunnerOptions": {
...
},
...
"targetDefaults": {
"build": {
...
"dependsOn": ["^build"]
}
},
}
```
Similar as we have seen in the definition of the `inputs`, the `^` here denotes that the target should be run on all dependent projects. If you remove the `^`, then the target would be invoked on the same project. That can be useful if you have a `prebuild` step that always needs to be invoked.
Next, we also want to define a targetDefault for our Remix `dev` command, such that first the `build` on all dependent packages (e.g our `shared-ui`) is run.
```json
{
"tasksRunnerOptions": {
...
},
...
"targetDefaults": {
"build": {
...
"dependsOn": ["^build"]
},
"dev": {
"dependsOn": ["^build"]
}
}
}
```
Heres the entire `nx.json` file again as a reference point:
```json
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test"]
}
}
},
"namedInputs": {
"noMarkdown": ["!{projectRoot}/**/*.md"]
},
"targetDefaults": {
"build": {
"inputs": ["noMarkdown", "^noMarkdown"],
"dependsOn": ["^build"]
},
"dev": {
"dependsOn": ["^build"]
}
}
}
```
If we now run `npx nx build my-remix-app` we can see that Nx first runs tasks on dependent projects, and only then runs the command we invoked.
![](/blog/images/2022-07-14/1*DhI4glb7lrvW_nSgHZz9KA.avif)
_Nx highlights dependent projects being built, but it keeps the main attention to the current task at hand without distracting_
## Running just what changed
In addition to providing caching, Nx also allows to just run what changed in a given branch with respect to a base branch by using the so-called [“affected command”](/ci/features/affected).
```shell
npx nx affected:<target>
```
You can use any target you have defined in your workspace. For example
- `npx nx affected:build`
- `npx nx affected:test`
- `npx nx affected:lint`
- `npx nx affected:publish`
**How does this work?** Nx builds a project graph based on the structure and dependencies among packages in your monorepo workspace. Lets assume the following hypothetical graph:
![](/blog/images/2022-07-14/1*wdMo0VwoyAdZbAmDbn6uMw.avif)
_Potential graph of a monorepo workspace_
Whenever we run the affected commands on a branch, Nx compares all the commits and relative changes with the base branch. By default that is `main`, but you can fine-tune that in the `nx.json` file:
```json
{
"affected": {
"defaultBase": "main"
}
}
```
If `lib2` gets changed in our feature branch, running tests against the workspace using `affected:test` would only run tests for `lib2` and `appB`.
![](/blog/images/2022-07-14/1*FACbo_7-AlbPOna_6-hDaw.avif)
_Affected projects if “lib2” gets changed_
Be aware however, if we run `affected:build` and we defined a dependency in our `nx.json` indicating that dependent projects need to be built first as well (see section "Defining task dependencies"), then `affected:build` would build
- `lib3`
- `lib2`
- `appB`
It would not build `lib1` or `appA` though.
## Additional features
Besides speed and task scheduling improvements, we also get some additional features by adding Nx to our PNPM workspace. Lets explore some:
## Want to automate the creation of packages?
Once you have a good setup for a package, you obviously want to replicate that as you create new ones. The usual approach: copy & paste and then remove all stuff that's not needed.
That's tedious and potentially error prone. Nx has a concept of "generators", basically code scaffolding which allows you to generate new packages in the monorepo rather than copy & pasting old ones.
If that sounds interesting, here's a walkthrough:
{% youtube src="https://www.youtube.com/watch?v=myqfGDWC2go" /%}
## Dynamic Terminal Output
Running tasks in parallel with PNPM results in quite a messy terminal output. The logs are hard to parse as the messages from the different commands being executed in parallel are interleaved.
```shell
pnpm run --parallel -r buildScope: 2 of 3 workspace projects
apps/my-remix-app build$ remix build
packages/shared-ui build$ rm -rf dist && tsc
apps/my-remix-app build: Building Remix app in production mode...
apps/my-remix-app build: The path "shared-ui" is imported in app/routes/index.tsx but shared-ui is not listed in your package.json dependencies. Did you forget to install it?
apps/my-remix-app build: Built in 176ms
apps/my-remix-app build: Done
packages/shared-ui build: Done
```
When using Nx to run tasks you get a dynamic terminal that shows just what is necessary and most relevant to the current command that has been executed. Running the same parallel build task results in the following output when using Nx:
![](/blog/images/2022-07-14/1*GbaJL87ZfOpBQm-W6lBheQ.avif)
_Terminal output of Nx dynamically showing the parallel tasks being computed as well as the ones that already succeeded_
## Project Graph Visualization
```shell
npx nx graph
```
This launches an interactive visualization of the workspaces project graph with some advanced capabilities of filtering, debugging your workspace structure and more.
![](/blog/images/2022-07-14/1*KpUCyj6SvYR3t7tmADloog.avif)
_Nx project graph visualization of our PNPM workspace_
> _As a side-note: you can run the project graph on any PNPM workspace, even if you dont have Nx installed. Running_ `_npx nx graph_` _should work._
## Conclusion
We did it! Here are some of the things we covered:
- how to setup a PNPM based monorepo workspace
- create a Remix and shared React library within a PNPM monorepoe
- how to run different commands with PNPM
- how to add Nx & incrementally adopt it in the monorepo
- benefits and features that come with adding Nx to a PNPM workspace
You can find an example of such setup on the **Nx Recipe GitHub repository**:
[https://github.com/nrwl/nx-recipes/tree/main/pnpm-workspace](https://github.com/nrwl/nx-recipes/tree/main/pnpm-workspace)
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/nrwl_io)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)

View File

@ -0,0 +1,97 @@
---
title: 'Helping the Environment by Saving Two Centuries of Compute time'
slug: 'helping-the-environment-by-saving-two-centuries-of-compute-time'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-08-18/1*FBQVoC9YXF7wlq3dhxfQMQ.png'
tags: [nx]
---
Among the core features of Nx is the ability to save computation time by applying different strategies. Scroll to the end of the article for some more info, but first, **how much time is actually being saved?**
## How much time is being saved?
This is how much got saved so far (data from August 16th, 2022). Pretty crazy!
![](/blog/images/2022-08-18/1*pT5u_K51oZBHGll7lz5VzA.avif)
Here are the raw numbers:
- **Last 7 days:** 5 years 4 months 2 days 2 hours 32 minutes 46 seconds
- **Last 30 days:** 23 years 8 months 25 days 8 hours 57 minutes 19 seconds
- **Since the beginning of Nx Cloud:** 200 years 10 months 13 days 19 hours 37 minutes 57 seconds
## The Effect on the Environment
Calculating the CO2 emissions can be tricky. It really depends on what machines are being used to run the computation saved by Nx Cloud. We gave it a try by using [https://green-algorithms.org/](https://green-algorithms.org/).
**Last 7-day savings correspond to:**
![](/blog/images/2022-08-18/0*wtlsJfqliTPK677u.avif)
[See all the details](https://green-algorithms.org//?runTime_hour=46752&runTime_min=0&appVersion=v2.2&locationContinent=North+America&locationCountry=United+States+of+America&locationRegion=US&coreType=CPU&numberCPUs=2&CPUmodel=Xeon+E5-2683+v4&memory=4&platformType=cloudComputing&provider=aws)
**Last 30-day savings correspond to:**
![](/blog/images/2022-08-18/0*20CiOx5JE5Lr0zaU.avif)
[See all the details](https://green-algorithms.org//?runTime_hour=207462&runTime_min=0&appVersion=v2.2&locationContinent=North+America&locationCountry=United+States+of+America&locationRegion=US&coreType=CPU&numberCPUs=2&CPUmodel=Xeon+E5-2683+v4&memory=4&platformType=cloudComputing&provider=aws)
**Since the beginning of Nx Cloud:**
![](/blog/images/2022-08-18/0*BvLzgEHLCJg9_isq.avif)
[See all the details](https://green-algorithms.org//?runTime_hour=1760505&runTime_min=0&appVersion=v2.2&locationContinent=North+America&locationCountry=United+States+of+America&locationRegion=US&coreType=CPU&numberCPUs=2&CPUmodel=Xeon+E5-2683+v4&memory=4&platformType=cloudComputing&provider=aws)
## Help me out! A Primer on how Nx saves computation
Nx has various strategies to help you reduce computation time, locally and on CI. Heres a very short overview of the strategies Nx applies with some links for further reading.
### Affected Commands
Example: Run tests only for changed projects in a given PR.
```
nx affected:test
```
[Nx affected commands](/ci/features/affected) allow you to only run commands against projects that changed with respect to a baseline. Usually, this is applied in PRs processed by your CI system. Nx analyzes the Git commits and identifies all projects that got changed with respect to a base branch (usually `main` or `master`). It then makes sure to run the given command only for those projects as well as all projects depending on them since they might be affected by the change too.
This helps save computation by reducing the set of projects that need to be processed.
### Local Computation Caching
Nx comes with a so-called [computation caching](/concepts/how-caching-works) feature. For every cacheable operation, Nx takes a set of input parameters, computes a hash and stores the result.
![](/blog/images/2022-08-18/0*MusIEMCW5NlEtaaA.avif)
Whenever a hash matches, the computation is not run, but rather the previous result is restored. This can dramatically speed up things and avoid running any computation that has already been run previously.
### Distributed Remote Caching (with Nx Cloud)
By default, the Nx computation cache is stored locally (usually within the `node_modules/.cache/nx` folder). The real benefits come from sharing it with others, that being your co-workers or CI agents.
[Nx Cloud](/nx-cloud) allows to distribute the Nx computation cache across machines.
![](/blog/images/2022-08-18/0*0uisxJ76ycdSZdA1.avif)
Connecting an existing Nx workspace to Nx Cloud can be done with
```
nx connect-to-nx-cloud
```
[More on the docs](/ci/features/remote-cache). Nx Cloud comes with [500 hours of computation time saved per month](/pricing) which is plenty for most workspaces. If you go over, you can buy more, or in the worst case, caching simply stops until the next month.
## Bonus! Lerna can do this too!!
[Nrwl](/company), the company behind Nx, recently [took over stewardship of Lerna](/blog/lerna-is-dead-long-live-lerna). Meanwhile, Lerna 5.4 just got released which features a nice integration with Nx, allowing existing Lerna users to keep using the very same commands, but still benefit from the improved task scheduling and caching abilities Nx comes with.
How to enable it? [Read more on the Lerna docs](https://lerna.js.org/docs/features/cache-tasks)
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/nrwl_io)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)

View File

@ -0,0 +1,206 @@
---
title: 'Lerna reborn — Whats new in v6?'
slug: 'lerna-reborn-whats-new-in-v6'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-10-12/1*RGQCNNO-SSQ8PHnIZ4BVTQ.png'
tags: [nx, release]
---
Lerna v6 is out!! Heres everything you need to know about the **new Lerna experience!**
**Table of Contents**
· [Lerna continues to evolve](#lerna-continues-to-evolve)
· [Fast Lerna with caching by default](#fast-lerna-with-caching-by-default)
· [Remote caching with Lerna](#remote-caching-with-lerna)
· [Defining a task pipeline](#defining-a-task-pipeline)
· [Lerna add-caching command](#lerna-addcaching-command)
· [PNPM support for Lerna](#pnpm-support-for-lerna)
· [Dynamic terminal output](#dynamic-terminal-output)
· [VSCode extension for Lerna workspaces](#vscode-extension-for-lerna-workspaces)
· [Lerna Repair](#lerna-repair)
· [Lerna and Prettier](#lerna-and-prettier)
· [Migrating to Lerna v6](#migrating-to-lerna-v6)
· [Lerna is using Nx now. Can I keep using my Lerna commands?](#lerna-is-using-nx-now-can-i-keep-using-my-lerna-commands)
· [Are you maintaining an OSS repository using Lerna?](#are-you-maintaining-an-oss-repository-using-lerna)
## Lerna continues to evolve
If you already know this, feel free to skip ahead. But surprisingly many still havent heard that **Lerna is back**, far from obsolete or deprecated and is getting brand new features. We from [Nrwl](/company) are the creators of Nx and given our long history in the monorepo space, we offered to [take over stewardship of Lerna](/blog/lerna-is-dead-long-live-lerna) when it was declared “dead” in April 2022.
Since we took over, in May 2022, it has been an absolute rollercoaster. We launched [a brand new website](https://lerna.js.org/), updated the content of the docs, and [made Lerna 10x faster](/blog/lerna-used-to-walk-now-it-can-fly). And now, **Lerna v6 is out!**
## Fast Lerna with caching by default
Up until Lerna v4, either the `p-map` or `p-queue` npm packages have been used to delegate the task scheduling. With [v5.1](/blog/lerna-used-to-walk-now-it-can-fly) we introduced `nx` as an additional mechanism to schedule tasks. The advantage? Nx has caching built-in, which **also gives Lerna caching support**, making it lightning fast. A recent benchmark test resulted in **Lerna being 2.5x faster than Lage** and around **4x faster than Turbo** (as of Oct 2022; [test it out by yourself](https://github.com/vsavkin/large-monorepo)).
So far you had to enable “Nx support” by setting the `useNx` flag in `lerna.json`:
```
// lerna.json
{
...
"useNx": true
}
```
Weve been testing this opt-in for the last couple of months and got tons of amazing feedback from companies and open source projects. As a result, **with v6 all Lerna workspaces have the useNx set to** `**true**` **by default** even if you don't have it in your Lerna config file. If you don't want to use it, you can disable it by setting the flag to false.
To experience fast caching, ensure you have a `nx.json` file at the root of your Lerna workspace where you define the cacheable operations. Check out [the docs for more details](https://lerna.js.org/docs/features/cache-tasks). Here's an example configuration file:
```json
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test"]
}
}
}
}
```
Note that you can also run..
```shell
npx lerna add-caching
```
..to automatically generate a `nx.json` configuration file based on your existing Lerna workspace.
## Remote caching with Lerna
By using Nx as the task scheduler for Lerna it inherits all the capabilities Nx comes with. That not only just includes local caching, but also the possibility of having **remote caching** and **distributed task execution**.
Remote caching allows you to distribute your local cache with your co-workers and your CI system. This is done via [Nx Cloud](/nx-cloud). But distributed caching is just one aspect. Nx Cloud also comes with a “run view” that visualizes your CI run with easy grouping and filtering capabilities, but in particular, it comes with the ability to distribute your tasks dynamically across multiple machines. All by optimizing for the best parallelization and machine utilization.
![](/blog/images/2022-10-12/0*CtvU5Me27YRidzG1.avif)
All you need to set this up is to run..
```shell
npx nx connect-to-nx-cloud
```
..in your Lerna workspace, which will guide you through a couple of questions and set you up with an [Nx Cloud](/nx-cloud).
Read more [on the docs](https://lerna.js.org/docs/features/cache-tasks#distributed-computation-caching).
## Defining a task pipeline
When running tasks in a monorepo environment, you want to maximize the parallelization, but **still account for potential dependencies among tasks**. For example, assume you have a Remix application that depends on some `shared-ui` library. You want to ensure that `shared-ui` is built before either building or serving the Remix application.
With Lerna v6 you can do so in the `nx.json` file by defining the `targetDefaults`:
```
// nx.json
{
...
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
},
"dev": {
"dependsOn": ["^build"]
}
}
}
```
In this case, whenever you run either `build` or `dev`, Lerna would first run the `build` task on all the dependent packages.
[Read more on our docs](https://lerna.js.org/docs/concepts/task-pipeline-configuration).
## Lerna add-caching command
If you dont have caching or your task pipeline set up just yet, no worries. We wanted to make it as easy as possible by providing a dedicated command:
```shell
npx lerna add-caching
```
This will scan your workspace, find all your `package.json` scripts and then guide you through the **configuration of both, your cacheable operations as well as your task pipeline**.
Heres a quick walkthrough video:
{% youtube src="https://www.youtube.com/watch?v=jaH2BqWo-Pc" /%}
You are obviously always free to create the `nx.json`by hand.
## PNPM support for Lerna
In the past, Lerna didnt properly support PNPM. We fixed this in v6. Now whenever you use Lerna in combination with PNPM, we make sure to detect packages based on the `pnpm-workspace.yaml`, to enforce `useWorkspaces: true` , we update the `pnpm-lock.yaml`
accordingly when using `lerna version` and we also added proper support for the `workspace:` protocol that PNPM uses.
You can now finally use one of the fastest package managers in combination with a new fast Lerna experience. Also, make sure to check [out our docs for all the details](https://lerna.js.org/docs/recipes/using-pnpm-with-lerna).
## Dynamic terminal output
When running tasks in parallel across a large number of projects, it can become quite difficult to follow along in the terminal with what got built and where tasks failed. Thats why the new Lerna version comes with a dynamic terminal output that only shows what is most relevant at a given moment.
![](/blog/images/2022-10-12/0*8hPYG2wuAMk5hri0.avif)
Note that you would still see all of the output as usual on CI.
## VSCode extension for Lerna workspaces
Lerna now has a [dedicated VSCode extension](https://lerna.js.org/docs/features/editor-integrations) to help you navigate your monorepo. This allows you to run commands directly from the context menu (by right-clicking on a project):
![](/blog/images/2022-10-12/0*-TlHvP1Kd46Vzbfg.avif)
Or visualize a project and its relationships with other projects in the workspace.
![](/blog/images/2022-10-12/0*ZFhpQX9xS59eZD7Q.avif)
You will also get intelligent autocompletion in configuration files. Heres an example of Nx console providing context-based information when editing the `nx.json` task dependencies.
![](/blog/images/2022-10-12/0*pMotejmmm1TUsLR2.avif)
## Lerna Repair
Lerna v6 comes with a built-in `lerna repair` command. Running this command will automatically fix your Lerna configuration. For instance, in Lerna v6, there's no need to have `useNx: true` in your `lerna.json` since that will be the new default going forward. Running `lerna repair` fixes this.
![](/blog/images/2022-10-12/0*SNKZvHYE2CG7jX7A.avif)
This allows you always to have the most up-to-date Lerna setup and it will become even more powerful as we keep adding migrations in the future.
## Lerna and Prettier
Prettier is part of the standard toolchain of every developer nowadays. In Lerna v6 we added a feature to detect whether Prettier is set up in the workspace. If so, we automatically apply it to all files that get updated by running the `lerna version` command. No more follow-up commits just to fix the file formatting!
## Migrating to Lerna v6
Migrating from Lerna v5 to v6 is non-breaking. We increased the major because we changed some defaults and wanted to be cautious about that and communicate it properly.
{% youtube src="https://www.youtube.com/embed/kOD7880DNEE" /%}
Similarly, if youre still on v4 and want to migrate to v6 it should be pretty straightforward and not be breaking in most cases.
Just update the Lerna package version to the latest and then run..
```shell
npx lerna add-caching
```
..to enable and configure caching for your workspace.
## Lerna is using Nx now. Can I keep using my Lerna commands?
Absolutely! One of the key advantages of the new integration of Lerna with Nx is that you can keep using your existing Lerna commands without migrating them to a new syntax. They will now just be a lot faster.
You can read more about that [on our docs](https://lerna.js.org/docs/lerna-and-nx).
## Are you maintaining an OSS repository using Lerna?
If you are an OSS maintainer and you use a Lerna workspace, let us know!
Ping the Lerna team [on Twitter](https://twitter.com/lernajs) or ping [me directly](https://twitter.com/juristr). Wed love to have a look and help with the migration, look at the repository and make sure it is configured in the best optimal way in terms of monorepo setup and features like caching.
That said, as an open-source maintainer you also get unlimited free computation caching with Nx Cloud. So wed love to set you up with that.
## Learn more
- 🧠 [Lerna Docs](https://lerna.js.org/)
- 👩‍💻 [Lerna GitHub](https://github.com/lerna/lerna)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)(join the `#lerna` channel)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/nrwl_io)

View File

@ -0,0 +1,43 @@
---
title: 'From Bootstrapped to Venture-Backed: Nx Raises $8.6M'
slug: 'from-bootstrapped-to-venture-backed'
authors: ['Jeff Cross']
cover_image: '/blog/images/2022-11-17/0*a3eT-mjLsXTiHU5m.png'
tags: [nx]
---
Im excited to let the Nx Community know about our first round of outside financing, led by [Nexus Venture Partners](https://nexusvp.com/) and [A16z](https://a16z.com/), with several amazing angel investors. Weve raised a seed round of $8.6M to scale the growth of open source Nx, [Nx Cloud](/nx-cloud), and [Nx Enterprise](/enterprise). With this new capital, were able to allocate significantly more resources to rapidly evolving our open source and commercial products to help development teams **ship faster at any scale**.
![](/blog/images/2022-11-17/1*RYpEUOFtvrtdGwKx3RgGLA.avif)
_Just a few of the companies powered by Nx_
When Victor Savkin and I left Google to start this company in December 2016, we saw a big gap between how enterprises were building software and how companies like Google were building software. So in 2017, we released the first version of our developer toolkit, Nx, which focused on enabling monorepo-style development for large software teams. Nx has continued to evolve and grow in adoption since then, at more than 5x year-over-year in npm downloads to now 12M+ monthly downloads! Were proud that the worlds top brands depend on Nx to help their development teams iterate faster on critical products.
![](/blog/images/2022-11-17/1*WIkl00uLsSt6p6dmQbIA0g.avif)
[Nx Cloud](/nx-cloud) has also seen a significant uptake in adoption, thanks in large part due to the addition of [Distributed Task Execution](/ci/concepts/parallelization-distribution) last year. With the combination of Distributed Task Execution and Distributed Caching, Nx Cloud is having a massive impact on the time it takes to validate and merge pull requests, drastically reducing product time-to-market. There are now more than 100k connected Nx Workspaces on nx.app. With Nx Cloud, Nx and Lerna workspaces can drastically reduce build times by letting Nx Cloud manage task cache distribution, and optimal distribution of tasks across many machines using Nxs deep understanding of project relationships and task timings. Weve determined that Nx and Nx Cloud have [saved over 250 years of compute time](blog/helping-the-environment-by-saving-two-centuries-of-compute-time) since we started measuring.
![](/blog/images/2022-11-17/1*ysWZ8fn2K3m3GjCNGRwshw.avif)
Our most significant commercial innovation in the past year has been [Nx Enterprise](/enterprise), which allows companies to deploy Nx Cloud on their own infrastructure. Some of the worlds leading brands are relying on Nx Enterprise to help their developers get products and features to market significantly faster. One repository powered by Nx Enterprise is saving over 40,000 hours per month of compute time thanks to Distributed Caching and Distributed Task Execution, drastically reducing the time it takes to validate and merge pull requests.
![](/blog/images/2022-11-17/0*zkOkZXDTZiNB6TAk.avif)
_Monorepo.tools, by Nx in collaboration with other monorepo projects_
With Nx and Lerna under our stewardship, we now maintain [more than 75% of leading JavaScript monorepo tooling](https://npmtrends.com/@bazel/typescript-vs-@microsoft/rush-vs-@nrwl/tao-vs-lerna-vs-turbo). Were sharing this space with some other great teams, who are all pushing the state of the art forward. We developed the site [monorepo.tools](https://monorepo.tools/) in collaboration with these teams to spread the monorepo love and help developers decide which tool is right for them.
## Why Outside Funding?
Victor Savkin and I originally decided not to raise funding when starting the company, to give ourselves space to experiment with different business models and find product-market fit. Weve revisited the idea of funding from time to time, but our consulting business has provided more than enough income to sustain the companys growth. It wasnt until Nx Cloud and Nx Enterprise started growing at a much more rapid pace that we decided we could provide a lot more value, more quickly to our community and customers by taking on some partners and capital to help us with our next phase of growth.
We couldnt be more excited to partner with our co-lead investors, [Nexus Venture Partners](https://nexusvp.com/) and [Andreesen Horowitz (a16z)](https://a16z.com/). Both firms have deep expertise in developer tooling and strongly believe in our vision of helping development teams scale. Were excited to have them bring their own unique talents, experience, and resources to help us execute on that vision. Abhishek Sharma from Nexus has tremendous commercial open source experience, and has been excited about Nx for years. A16z is a powerhouse with an extremely talented enterprise infrastructure team led by Martin Casado and Jennifer Li, alongside amazing partners including, Satish Talluri, and Yoko Li. Were also excited to be joined by many angels, including Tom Preston-Werner, Matt Biilmann, and several other notable CEOs, founders and technologists.
![](/blog/images/2022-11-17/0*37ySQYL9U1xF7ezq.avif)
_Most of the Nx team at Nx Conf in Tempe, AZ, October 2022_
We are only scratching the surface of how we can help teams scale their development, and were drastically increasing our R&D time to move even faster on new innovations in build performance and team scaling. Fortunately, we already have a world-class team of top engineers whove helped us build Nx and Nx Cloud, while also helping our customers succeed with Nx. With this new capital, our engineers are able spend significantly more R&D time building industry-changing products and features, while continuing to work with and learn from our Nx Cloud and Nx Enterprise customers.
Well be sharing more exciting announcements soon, so make sure to follow our journey on [@NxDevTools](https://twitter.com/nxdevtools)!
Jeff Cross
CEO, Nx

View File

@ -0,0 +1,419 @@
---
title: 'Nx 15.3 — Standalone Projects, Vite, Task Graph and more!'
slug: 'nx-15-3-standalone-projects-vite-task-graph-and-more'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2022-12-06/1*VXYjjWhOUpNuHFGCoF63OQ.png'
tags: [nx, release]
---
What a massive release! Here are all the news 👇
**Table of Contents**
· [Funding — Nx raises $8.6M](#funding-nx-raises-86m)
· [3 million downloads per week](#3-million-downloads-per-week)
· [New Task Graph Visualization](#new-task-graph-visualization)
· [Standalone Projects](#standalone-projects)
· [Integrated Vite and Vitest support is here!](#integrated-vite-and-vitest-support-is-here)
· [Adopting Nx has never been easier](#adopting-nx-has-never-been-easier)
· [Adding Nx to an Existing Standalone Project](#adding-nx-to-an-existing-standalone-project)
· [Root-level Scripts](#rootlevel-scripts)
· [Simplified Nx run-commands](#simplified-nx-runcommands)
· [Coming up](#coming-up)
· [How to Update Nx](#how-to-update-nx)
Prefer **a video version?**
{% youtube src="https://www.youtube.com/watch?v=KBFQZw5ynFs" /%}
## Funding — Nx raises $8.6M
In case you missed it, we raised $8.6 million a couple of weeks ago. Heres the official blog post from our CEO Jeff: [/blog/from-bootstrapped-to-venture-backed](/blog/from-bootstrapped-to-venture-backed)
It is exciting for us as we can now have more employees focused on pushing Nx and Nx Cloud forward, which will significantly boost development speed!
For most of our workforce, working on Nx and Nx Cloud was only part of their “20% project”. Yet we released terrific features over the last years and have seen tremendous growth with Nx (which brings us to the next section)
## 3 million downloads per week
2022 has been a particularly crazy but successful year for us. And Nxs growth confirms that were on the right track:
- January: Nx crosses 1 million downloads per week
- June: Nx crosses 2 million downloads per week
- November: Nx crosses 3 million downloads per week
On to 4 million!
![](/blog/images/2022-12-06/0*TxO8bDuJW6pJZ-zy.avif)
## New Task Graph Visualization
{% youtube src="https://www.youtube.com/watch?v=wOE3r4299fs" /%}
One of our most loved features also just got more powerful: the Nx graph!
Nx already visualizes your project graph, mapping the dependencies different projects have on one another through imports and exports in your code. But your tasks also have a graph. Your task can either depend on another target on the same project, lets say you have a `prebuild`
and a `build` target. Whenever you run `build`, you want to run `prebuild` first. Similarly, if your project depends on other projects, you might want to make sure to build them first as well. This is called a [task pipeline](/concepts/task-pipeline-configuration) and can be defined in `nx.json` as follows:
```json5 {% fileName="nx.json" %}
{
...
"targetDefaults": {
"build": {
"dependsOn": ["prebuild", "^build"]
}
}
}
```
This example is pretty straightforward, but such pipelines can become much more involved.
Therefore, let me introduce you the **task graph**. You might already be used to seeing the project graph after running the `nx graph` command. But there's now a dropdown in the corner that enables you to switch to the task graph. Select a target from the "Target Name dropdown" to filter the list of projects to only those with that target. Click on a project to show that target's task graph.
You can add another project as well, showing what the task graph looks like for a command that runs tasks for multiple projects like `nx run-many` or `nx affected`. Click on the `Group by project` checkbox to group related tasks by their project, and click on a task to see what executor it uses.
![](/blog/images/2022-12-06/0*NZWdLWLIxwzwcfmp.avif)
## Standalone Projects
{% youtube src="https://www.youtube.com/watch?v=qEaVzh-oBBc" /%}
Nx is widely known as [THE developer tool](https://monorepo.tools/) people look at when it comes to implementing monorepos in the frontend space. However, a lot of the unique features that Nx ships (in particular when it comes to implementing [Integrated Monorepos](/deprecated/integrated-vs-package-based)) can be beneficial even outside of the typical monorepo scenario. In particular, Nx plugin features such as code generation, pre-configured build tooling setup, and battle-tested integration with best practices tools (e.g. Cypress, Jest, ESLint, Vite, …).
But one stands out most prominently: the **ability to easily modularize** your codebase.
![](/blog/images/2022-12-06/0*wBnyRIMm8_K6K9k3.avif)
A lot of our users adopt Nx for precisely this reason. They have a large app and want to break it into smaller pieces while still having the comfort of deploying it as a single one.
In 15.3 we are therefore making **standalone projects** a first-class feature. Suppose you now create a new workspace with `npx create-nx-workspace` alongside the usual monorepo options. In that case, you will now see two more options for scaffolding a standalone React or Angular application (we will add more in the future).
![](/blog/images/2022-12-06/0*z3UOtkyCIKcL2LNg.avif)
In a standalone project setup, you dont have the typical `apps` and `libs` structure you might be accustomed to if you have been using Nx in the past. Instead, the app lives directly at the root of your workspace. The structure looks similar to the following:
```text
e2e/
src/
cypress.config.ts
project.json
...
src/
app/
main.tsx
...
public/
index.html
project.json
tsconfig.spec.json
tsconfig.app.json
tsconfig.json
vite.config.ts
nx.json
package.json
```
The critical part here is that you can still have multiple nodes. Even in this example, we have the app itself at the root of the workspace and a nested `e2e` project for that application (using Cypress).
To modularize your application, you can add libraries as you would do in a more traditional integrated Nx monorepo setup, but you can now have those alongside your application. Either create them directly at the root-level or group them in one or more root-level folders. In the example below, I have a `features` as well as `utils` folder, both of which can host multiple libraries.
```text
e2e/
...
src/
app/
main.tsx
...
features/
feature1/
feature2/
utils/
...
index.html
...
nx.json
package.json
```
It is really up to you how you want to structure them.
Think of it as a supercharged development tool, providing powerful generators, features like [module boundary rules](/blog/mastering-the-project-boundaries-in-nx) and obviously the ability to run tests, linting, building on individual libraries. Not to forget about Nxs powerful caching ability. And if youre ready for a “real” monorepo because you want to add multiple applications, there will be paths for you to “upgrade” to that structure.
## Integrated Vite and Vitest support is here!
Finally! We talked about it; now it is here! Official Vite and Vitest support for Nx-based integrated monorepos and standalone app projects! That adds the Vite community into the Nx family, and weve been chatting with core members there recently, and we love it!
So before we dive into this: if you are using a package-based monorepo with Nx, you could already use Vite or whatever other technology you want. Nx does just the task scheduling there, running your `package.json` scripts efficiently. Whatever those scripts do "internally" is up to you.
But if you power an integrated setup, youd want more support via a dedicated Nx plugin. And there has already been a [Nx community plugin](/community) created by the folks from [https://nxext.dev/](https://nxext.dev/). Given the high demand for Vite support, we (the Nx core team) started to look into creating and maintaining our own. We reached out to the out [Dominik Piper](https://mobile.twitter.com/dominik_pieper) and [Jordan Hall](https://mobile.twitter.com/JordanHall_dev) from the NxExt team and they were on board from the beginning! We got lots of helpful input, while designing the new Vite plugin. Huge shoutout to them!!
`@nrwl/vite` (just like `@nrwl/webpack`) is a package that can be integrated as part of other packages. Right now, we're prioritizing our React setup. If you generate a new Nx workspace and choose the new "Standalone React app" version, you will get a React application powered by Vite and Vitest.
Similarly, you can add a new Vite-powered React app to an existing Nx workspace using the `vite` bundler option:
```shell
npx nx generate @nrwl/react:application --bundler=vite
```
This new setup gives you an easy jumpstart as it does all the configuration for you:
- React with Vite
- Tests with Vitest
- Making sure it nicely works with TypeScript (both in src and spec files)
Open the applications `project.json` to inspect the setup:
```json
{
"name": "viteapp",
...
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/vite:build",
...
},
"serve": {
"executor": "@nrwl/vite:dev-server",
"defaultConfiguration": "development",
...
},
"test": {
"executor": "@nrwl/vite:test",
"outputs": ["{projectRoot}/coverage"],
"options": {
"passWithNoTests": true
}
},
...
}
}
```
Furthermore, theres a `vite.config.ts` at the project root level, which you can further customize to your needs. It is already pre-configured to seamlessly work in a monorepo scenario and has the Vitest setup. Just run `npx nx serve` or `npx nx build` or `npx nx test` to serve, build or test your standalone React app.
If you are currently using the NxExt based Vite plugin, or even a Webpack based Nx React setup, you can easily transition to the new Vite plugin by just running the following generator:
```shell
npx nx g @nrwl/vite:configuration
```
This will adjust the NxExt Vite plugin configuration to match the one provided by our core team. Check out our docs for more info: [/nx-api/vite/generators/configuration](/nx-api/vite/generators/configuration)
You can also find all the details about the new Vite package on our docs: [/nx-api/vite](/nx-api/vite)
## Adopting Nx has never been easier
Many developers dont necessarily start with a greenfield project, but rather have an existing reality where they want to use Nx. Weve been improving this process of adopting Nx over this year to the point where it has never been easier than now!
Regardless of whether you have
- an existing package-based monorepo setup using NPM/Yarn or PNPM workspaces
- an existing Lerna workspace (for this you probably want to consult the [Lerna docs](https://lerna.js.org/upgrade) for some awesome feature updates)
- a Create-React-App (CRA) application
- a Angular CLI standalone application
- or really any other form of project
You can just run
```shell
npx nx@latest init
```
Running this command will install the `nx` package, and then analyze your existing project structure and correctly identify whether it is a monorepo workspace or some standalone project, whether it's a CRA app or whether you're coming from the Angular CLI. Based on that, you'll get a couple of questions asked and then your workspace gets configured to run it with Nx.
Check out our docs for all the details on
- [adding Nx to an existing monorepo](/recipes/adopting-nx/adding-to-monorepo)
- [adding Nx to any non-monorepo setup](/recipes/adopting-nx/adding-to-existing-project)
- [migrating your CRA project to Nx](/recipes/adopting-nx/adding-to-existing-project)
- [migrating your Angular CLI app to Nx](/recipes/angular/migration/angular)
Oh..youre wondering why you would want to add Nx to an existing non-monorepo project? Then keep reading 👇
## Adding Nx to an Existing Standalone Project
{% youtube src="https://www.youtube.com/watch?v=VmGCZ77ao_I" /%}
Adding Nx to a single application? Why would that be useful? Well, most apps have multilple scripts in their `package.json`, which includes building, testing, linting your app and potentially much more. Nx can cache these! Obviously it is just app-level caching (since you didn't modularize it with libraries), but imagine your CI setup running these:
```shell
npx nx build
npx nx test
npx nx lint
npx nx e2e
```
If your change just modified a couple of “spec files”, then theres no point on running `build` or `e2e` again, but just `test` and potentially `lint`. Nx can restore the results of the other operations from the cache.
To add Nx to an existing standalone project, all you need to run is
```shell
npx nx@latest init
```
This process will ask you a few questions about which operations are cacheable. We optimized it so that you dont necessarily have to use `nx` to run your build, linting or serving your app. You can keep using `npm run build` or `npm start`. This is because Nx wraps your scripts in the `package.json`. Notice how `build` and `lint` are wrapped because they are cacheable operations.
```json
{
...
"scripts": {
"build": "nx exec -- vite build",
"lint": "nx exec -- eslint \"src/**/*.ts*\"",
...
"dev": "vite",
"start": "vite --open",
},
"devDependencies": {
...
"nx": "15.3.0"
}
}
```
Read more on our docs: [/recipes/adopting-nx/adding-to-existing-project](/recipes/adopting-nx/adding-to-existing-project)
## Root-level Scripts
{% youtube src="https://www.youtube.com/watch?v=PRURABLaS8s" /%}
Most of the tasks in a workspace run against a specific project, like building or testing it. Thats why they live in the corresponding `package.json` or `project.json`. But sometimes you have workspace-wide commands which you want to run through the "Nx pipeline" to get the benefits of caching.
Assume you already have a script called `docs` in your root-level `package.json`.
```json5
// package.json
{
name: 'myorg',
scripts: {
docs: 'node ./generateDocsSite.js',
},
}
```
To allow it to be cached and to be run with Nx, all you need to do is add the follow `nx` property to your `package.json`:
```json5
// package.json
{
"name": "myorg",
"scripts": {
"docs": "node ./generateDocsSite.js"
}
"nx": {}
}
```
You can then run it with
```shell
npx nx docs
```
As the next steps you might obviously want to add `docs` to the [cacheable operations](/ci/reference/config) and [fine-tune it's cache inputs](/recipes/running-tasks/configure-inputs).
Read more about it on our docs: [/recipes/running-tasks/root-level-scripts](/recipes/running-tasks/root-level-scripts)
## Simplified Nx run-commands
{% youtube src="https://www.youtube.com/watch?v=iygb-KhAeik" /%}
Nx can automatically detect your scripts in `package.json`. But if you have an integrated setup using Nx plugins, they usually come with a `project.json` . There you have targets like `build`, `test`, `lint` etc.. and they mostly look as follows:
```json5 {% fileName="project.json" %}
{
"name": "demoapp",
...
"targets": {
"build": {
"executor": "@nrwl/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"outputPath": "dist/demoapp"
},
...
},
"serve": {
"executor": "@nrwl/vite:dev-server",
...
},
...
}
}
```
The task itself is handled by an [Nx executor](/extending-nx/recipes/local-executors) that comes with the plugin, in this case `@nrwl/vite:build` to build a Vite project.
To add a custom command, like invoking a node script, Nx has the so-called [“run-commands”](/recipes/running-tasks/run-commands-executor). So far you had to wrap those commands as follows:
```json5 {% fileName="project.json" %}
{
"name": "demoapp",
...
"targets": {
"prebuild": {
"executor": "nx:run-commands",
"options": {
"command": "echo 'hi'"
}
},
"build": {
...
},
...
}
}
```
For simple commands this was a huge overhead, so we simplified it to just this:
```json5 {% fileName="project.json" %}
{
"name": "demoapp",
...
"targets": {
"prebuild": {
"command": "echo 'hi'"
},
"build": {
...
},
...
}
}
```
Simple, isnt it! Obviously the expanded form is still there and also useful for when you need more options, run multiple commands or features such as argument forwarding.
You can read all about it on our docs: [/recipes/running-tasks/run-commands-executor](/recipes/running-tasks/run-commands-executor)
## Coming up
Wow, what a launch! But more features are on the way in the coming weeks that didnt make it for this release. Super excited about these, which most prominently include
- Workspace watching
- Lock-file pruning
- Nx Cloud integration into Nx Console
Follow us [on our socials](https://twitter.com/nxdevtools) and on [Youtube](https://www.youtube.com/@nxdevtools) to make sure to see it when we announce them!
## How to Update Nx
Updating Nx is done with the following command and will update your Nx workspace dependencies and code to the latest version:
```shell
npx nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
npx nx migrate --run-migrations
```
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)

View File

@ -0,0 +1,163 @@
---
title: 'Nx 15.4 — Vite 4 Support, a new Nx Watch Command, and more!'
slug: 'nx-15-4-vite-4-support-a-new-nx-watch-command-and-more'
authors: ['Zack DeRose']
cover_image: '/blog/images/2022-12-22/1*N4_XxtYFr-V2cF6fPoBO3g.png'
tags: [nx, release]
---
Nx just had a massive release 2 weeks ago with Nx 15.3 — if you missed it be sure to check out [our article](/blog/nx-15-3-standalone-projects-vite-task-graph-and-more) featuring some huge improvements including Vite support, Standalone Angular and React presets, and a Task Graph visualization!
But over the past couple of weeks, weve been able to land quite a few awesome features, so were going back at it again releasing Nx 15.4 today, including:
- [Vite 4.0 Support](#vite-40-support)
- [Nx Watch](#nx-watch)
- [Webpack-less Cypress Support for Our React Standalone preset](#webpackless-cypress-support-for-our-react-standalone-preset)
- [Server-Side Rendering support for Module Federation for both Angular and React Applications](#serverside-rendering-support-for-module-federation-for-both-angular-and-react-applications)
- [Running Multiple Targets in Parallel for Multiple Projects](#running-multiple-targets-in-parallel-for-multiple-projects)
- [Interactive Prompts for Custom Preset](#interactive-prompts-for-custom-preset)
Prefer a **video version**?
{% youtube src="https://www.youtube.com/watch?v=G02THNy3PcE" /%}
## Vite 4.0 Support
Nx 15.4 brings in the latest Vite major version following the Vite 4 release earlier this month.
![](/blog/images/2022-12-22/0*w-TkOJGLJpif48RN.avif)
As the [Vite launch article](https://vitejs.dev/blog/announcing-vite4.html) mentions, we are investing in the Vite ecosystem, and now officially support a first-party Vite plugin. Nx 15.4 continues this investment with timely support for Vite 4, and were excited to be a part of the Vite ecosystem and a part of bringing more value to our devs through Vite support!
Projects already using our [@nrwl/vite plugin](/nx-api/vite) will be automatically upgraded to Vite 4 when they upgrade to the latest Nx version with the `nx migrate` command, and we've also simplified the configuration required to support Vite.
Weve also spent some effort into making the conversion of existing projects to use Vite simpler, including:
- the ability to choose which targets you want to convert
- enhanced `vite.config.ts` file configuration
- better DX with detailed messages during conversion
- [better documentation around converting using our generator](/nx-api/vite/generators/configuration)
- [adding a guide to our docs for converting manually](/recipes/vite/configure-vite)
You can check out more details about our Vite plugin including how to add Vite and Vitest to your existing Nx workspace by visiting our docs at [nx.dev/nx-api/vite](/nx-api/vite)
## Nx Watch
{% youtube src="https://youtu.be/0eVplUl1zBE" /%}
Nx 15.4 includes a new feature to support file-watching with Nx! Heres how it works:
Syntax:
```shell
nx watch [projects modifier option] -- [command]
```
Example:
```shell
nx watch --all -- nx build $NX_PROJECT_NAME
```
For the projects modifier option:
- you can use `--all` for all projects in the workspace
- or you can filter down to specific projects with the `--projects=[comma separated list of project names]` option that can be used in conjunction with a `--includeDependentProjects` option as well
The `nx watch` command will support the variables `$NX_PROJECT_NAME` and `$NX_CHANGED_FILES`. This feature opens the door for nice developer workflows where we can provide an out-of-the-box mechanism for Nx to run relevant tasks on save, and were excited to see our users get their hands on this feature.
Personally, Im excited to use the following command:
```shell
npx -c 'nx watch all npx nx affected --target=test --files=$NX_FILE_CHANGES'
```
To link in `nx watch` with the `nx affected` command to have a single watch command to run all my affected tests on save as they are affected!
Check out [our docs](/recipes/running-tasks/workspace-watching) for more details.
## Webpack-less Cypress Support for Our React Standalone preset
![](/blog/images/2022-12-22/0*wF2QV3h_G5ZjBfLK.avif)
_Running e2e with React Standalone Projects_
We added a React Standalone preset in 15.3 to support single react application workspaces with Nx, and in 15.4, weve added back in Cypress for this preset.
With Nx 15.4, a standalone React application will be created with an e2e directory preconfigured and optimized for running Cypress with the command `npx nx e2e e2e` as soon as your initial workspace is generated.
## Server-Side Rendering support for Module Federation for both Angular and React Applications
![](/blog/images/2022-12-22/0*3pXE3lHOtndkH8jO.avif)
Now you can get the benefits of both Server Side Rendering and Module Federation for your applications, which will improve page loads, Search Engine Optimization, and build times!
Our existing `host` and `remote` Module Federation generators have an added `--ssr` flag that will enable Server-Side Rendering by generating the correct server files.
Weve also added a new executor to allow you to serve the host server locally, along with all remote servers from a single command.
Learn more about this new feature [in our docs](/recipes/react/module-federation-with-ssr)!
## Running Multiple Targets in Parallel for Multiple Projects
{% youtube src="https://www.youtube.com/watch?v=ROTO89i5m_4" /%}
Nx 15.4 includes updates to the `nx run-many` command, allowing you to add multiple whitespace-separated targets, as well as globs in the `projects` option, for example:
```shell
npx nx run-many --target test build lint
```
^ this would run all `test`, `build`, and `lint` targets in your workspace, and you can now filter this down to select projects via globbing:
```shell
npx nx run-many --target test build lint --projects "domain-products-*"
```
^ this will now run all `test`, `build`, and `lint` targets for all projects in your workspace that start with "domain-products-".
## Interactive Prompts for Custom Preset
Last but not least, weve added support for interactive prompts for Custom Presets!
In Nx, [presets](/extending-nx/recipes/create-preset#create-a-custom-plugin-preset) are special code generation scripts that can be used to create a brand new Nx Workspace, using our `create-nx-workspace` command.
![](/blog/images/2022-12-22/0*d4gI6k61RAEU_XfF.avif)
For instance, I happen to know [Shai Reznik](https://twitter.com/shai_reznik) at [builder.io](https://builder.io/) has been working on a qwik plugin for Nx, and since the [qwik-nx](https://www.npmjs.com/package/qwik-nx) plugin that hes published includes an [Nx generator called “preset”](https://github.com/qwikifiers/qwik-nx/blob/main/packages/qwik-nx/generators.json#L33), I can run the command:
```shell
npx nx create-nx-workspace preset=qwik-nx
```
As we can see, the preset option matches the name of the published npm package.
This custom preset feature has been around for a while, but as of 15.4 weve added support for these custom presets to interactively prompt the user following the initial installation step!
This should open up some powerful functionality for plugin and package authors to parameterize their code generation scripts with Nx, and were excited to see folks like [Shai](https://twitter.com/shai_reznik), [builder.io](https://builder.io/), and [qwik](https://qwik.builder.io/) leverage this new feature!
## Thats it for this release.
Follow us on our socials and on [Youtube](https://www.youtube.com/channel/UCF8luR7ORJTCwSNA9yZksCw) to make sure to see more news and releases as we announce them!
You can find [full changelogs for the release](https://github.com/nrwl/nx/releases/tag/15.4.0) on github.
## How to Update Nx
Updating Nx is done with the following command and will update your Nx workspace dependencies and code to the latest version:
```shell
npx nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
npx nx migrate --run-migrations
```
## Learn more
- [🧠 Nx Docs](/getting-started/intro)
- [👩‍💻 Nx GitHub](https://github.com/nrwl/nx)
- [💬 Nx Official Discord Server](https://go.nx.dev/community)
- [📹 Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)

View File

@ -0,0 +1,127 @@
---
title: 'Setting up Module Federation with Server-Side Rendering for Angular'
slug: 'setting-up-module-federation-with-server-side-rendering-for-angular'
authors: ['Colum Ferry']
cover_image: '/blog/images/2023-01-10/1*kyMChnJ-X6jK9sbuaOdOiw.png'
tags: [nx, tutorial]
---
[Module Federation](https://webpack.js.org/plugins/module-federation-plugin/) is a technology provided by [Webpack](https://webpack.js.org/) that enables modules to be federated across different origins at runtime. This means that Webpack will simply ignore these modules at build time, expecting them to be available to be fetched across the network at runtime.
This technology has enabled a much cleaner approach to Micro Frontend Architecture but also is employable as a strategy to implement incremental builds for large applications, reducing overall build times. This can lead to faster feedback cycles and less money spent on CI workflows.
Nx offers great out-of-the-box support and developer experience for Module Federation for Angular and React. You can learn more about it from the resources below:
📄 [Module Federation Recipes on Nx](/recipes/module-federation)
📺 [Speed up your Angular serve and build times with Module Federation and Nx](https://www.youtube.com/watch?v=JkcaGzhRjkc)
However, until now, it has only supported Client-Side Rendering (CSR). Essentially it worked only for Single Page Applications (SPAs). While this is still valuable, it is becoming ever more apparent that Server-Side Rendering (SSR) is becoming the de-facto standard for building web applications, due to the multitude of benefits it provides.
> [What is server-side rendering: definition, benefits and risks](https://solutionshub.epam.com/blog/post/what-is-server-side-rendering)
Since [version 15.4](blog/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more), Nx now offers Module Federation with support for SSR! 🎉
Now we can get both, the benefits of Module Federation and SSR in our Nx Workspaces!
## How it works
A traditional SSR application is rendered on the server. It receives the requested route from the browser, Angular evaluates that route, and the server generates the HTML and sends it back to the browser.
![](/blog/images/2023-01-10/0*ZqG4jdD8DaqmG_It.avif)
With Module Federation and SSR, it takes that concept and the concept of MF to allow portions of the app to be run on their own server. The host server will receive the route and if its a route pointing to a remote, it will ask the remote to process the route, then send the rendered HTML to the browser.
![](/blog/images/2023-01-10/0*eQis_bQnsj-MToCa.avif)
This gives us full power of SSR but also still allowing us to break our build into multiple smaller builds. It also means that we _could_ redeploy the remote server with new changes without having to redeploy the host server, allowing for independent deployability of features within the overall application.
## Example
Lets walk through how to set this up with Nx for Angular. We will generate a host application (dashboard) and a remote application (login).
```shell
npx create-nx-workspace@latest myorg
```
Youll be prompted for the type of workspace you want to create, and the preset to use.
Answer with the following:
✔ Choose what to create · integrated
✔ What to create in the new workspace · apps
✔ Enable distributed caching to make your CI faster · No
> _You will also be prompted whether to add Nx Cloud to your workspace. We wont address this in this article, but it is highly recommended to use this along with Module Federation to allow for the cache of your remote applications to be shared amongst teammates and CI, further improving your build times. You can learn more about Nx Cloud here:_ [_https://nx.app_](https://nx.app/)_._
When your workspace is created, run `cd myorg`.
Next, we will need to install the [Official Nx Angular Plugin](/nx-api/angular):
```
npm install @nrwl/angular
```
Once this is installed, we only need one command to scaffold out our full Module Federation with SSR architecture:
```shell
npx nx g host dashboard --remotes=login --ssr
```
We will see in the terminal that this generates a bunch of files. What it actually creates is:
Two applications with Angular Universal (SSR)
Webpack Configuration for Browser and Server with Module Federation
We can serve our dashboard (host) application, along with our login (remote) application, by simply running the command:
```shell
npx nx serve-ssr dashboard
```
This will build the browser and server bundles of our login application, then run the login using node.
The login application will be run without any file watchers, meaning that if you make a change to the code for the login application, it will not be reflected automatically. More on this later.
> Note: Nx will cache the build of the browser and server bundles for the login application. If you were to run the command again, it would simply use the cache rather than actually rebuilding the application! 🔥.
Once this is complete, it will then build and run the server for the dashboard application, _with_ file watchers, allowing it to pick up changes to the code.
You should see a success message like this in the terminal:
```
Compiled successfully.
\*\* Angular Universal Live Development Server is listening on http://localhost:4200, open your browser on http://localhost:4200 \*\*
```
Lets open a new tab in our browser, and open Network tab in the DevTools. After this, navigate to [http://localhost:4200](http://localhost:4200/). You should see the following:
![](/blog/images/2023-01-10/0*3irxzNENB79JiQmR.avif)
The most interesting piece here is the first entry in the network log. Lets look at it more closely:
![](/blog/images/2023-01-10/0*Ikvgk8dF8rKmutTY.avif)
We can see that the server returned the fully rendered HTML for the page!
Angular Universal will switch to CSR after the initial page load, which means if we were to click on the `login` link, it would use CSR to render that page. The Angular Module that is resolved and rendered still lives on the remote server, but Module Federation will still resolve this correctly! 🔥
But to see where the real magic happens, lets manually navigate the browser to [http://localhost:4200/login](http://localhost:4200/login). You should see that in the Network tab, the fully rendered HTML for the login page has been returned!
Despite the code for that page living on a different, remote, server, the host server composed it correctly and was still able to return the correct HTML for that route, thanks to Module Federation!
And thats it! Its super simple to get Module Federation and SSR up and running with Nx!
## Serving the login application and watching for changes
If youre working on the login application, and are iteratively checking the results of your changes, youll want the server to rebuild when you make your change. You can easily enable that by using the `devRemotes` flag::
```shell
npx nx serve-ssr dashboard --devRemotes=login
```
## Learn More
🧠 [Nx Docs](/getting-started/intro)
👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
💬 [Nx Official Discord Server](https://go.nx.dev/community)
📹 [Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)
🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
🧐 [Need help with Angular, React, Monorepos, Lerna or Nx? Talk to us 😃](https://nx.app/enterprise)

View File

@ -0,0 +1,535 @@
---
title: 'React, Vite and TypeScript: Get started in under 2 minutes'
slug: 'react-vite-and-typescript-get-started-in-under-2-minutes'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2023-01-12/1*ucL7YQ2v8aaOy426soLPZA.png'
tags: [nx]
---
Lets be honest. Dealing with tooling is not something enjoyable if you have to deliver code. It should just work and not be in the way. So lets explore how to kickstart your next React project using Vite, in under 2 minutes, without worrying about the setup.
## Table of Contents
· [How do I create a new project setup?](#how-do-i-create-a-new-project-setup)
· [Running, building and testing the app](#running-building-and-testing-the-app)
· [Building the app](#building-the-app)
· [Testing the app](#testing-the-app)
· [Running integration tests with Cypress](#running-integration-tests-with-cypress)
· [Linting](#linting)
· [Customize Vite and Vitest](#customize-vite-and-vitest)
· [Hidden gem: Caching](#hidden-gem-caching)
· [Hidden gem: Easily modularize your app](#hidden-gem-easily-modularize-your-app)
· [Hidden gem: Visualize your architecture](#hidden-gem-visualize-your-architecture)
· [Hidden gem: Guard your boundaries](#hidden-gem-guard-your-boundaries)
· [Hidden gem: Just run what changed](#hidden-gem-just-run-what-changed)
· [Hidden gem: A dedicated Editor extension](#hidden-gem-a-dedicated-editor-extension)
· [Hidden gem: Automated Upgrades](#hidden-gem-automated-upgrades)
· [Using CRA? Automatically migrate to Vite + Nx](#using-cra-automatically-migrate-to-vite-nx)
· [Conclusion](#conclusion)
{% youtube src="https://youtu.be/fkTz6KJxhhE" /%}
Traditionally, you might lean towards [Create-React-App (CRA)](https://create-react-app.dev/) started to do precisely that. But what if I told you theres a better alternative, providing
- not just scaffolding for the initial setup but helping you along the way to generate components, routing, etc
- automatically sets you up with best practices tools for e2e testing, unit testing, code formatting, and linting
- has built-in support for Vite and Vitest (alternatively Webpack & Jest)
- caches your scripts to speed up things
- helps you modularize your application
- comes with automated upgrade features to keep your tooling evergreen
Im talking about Nx. Nx comes with a set of plugins that come with code generation abilities and help abstract some of the lower-level tooling setups. And this can be really interesting for the use case we wanna tackle today.
> **_Reader:_** _“Wait a minute, I heard about Nx. Isnt that for monorepos?”_**_Me:_** _“Yeah youre right. But in 15.3 they introduced something called standalone apps
> Reader: “Standalone?”
> _**_Me:_** _“Yeah, a fancy term for a setting up a single app and allows for some cool modularization. Theres a video introducing that feature here:_ [_https://youtu.be/qEaVzh-oBBc_](https://youtu.be/qEaVzh-oBBc)_"
> _**_Reader:_** _“ha, interesting 🤔”_
So lets go and set up our **React + Vite + TypeScript project**.
## How do I create a new project setup?
To set up a new project, just invoke the following command:
```shell
npx create-nx-workspace@latest awesomereactapp --preset=react-standalone
```
Note `awesomereactapp` is the name of the app and folder being created, and `--preset=react-standalone` tells Nx which template to use when scaffolding the initial setup. You can also invoke it like:
```shell
npx create-nx-workspace@latest awesomereactapp
```
And then choose the option you prefer in the terminal prompt:
![](/blog/images/2023-01-12/0*WceoJTEWec2ZTp5X.avif)
In the end, what youll get is the following structure:
![](/blog/images/2023-01-12/0*mykjIRKX-a5VtyQl.avif)
## Running, building and testing the app
First off, lets run our new, shiny application. Just invoke
```
npm start
```
And in a matter of milliseconds, your app should be served at [http://localhost:4200/](http://localhost:4200/).
`npm start` just invokes the script defined in the `package.json`:
```json {% fileName="package.json" %}
{
"name": "awesomereactapp",
...
"scripts": {
"start": "nx serve",
"build": "nx build",
"test": "nx test"
}
...
}
```
Internally this delegates to `nx serve`, where `serve` is the [Nx target](/reference/glossary#target) to be invoked. You can find those in the `project.json`:
```json {% fileName="project.json" %}
{
"name": "awesomereactapp",
"$schema": "node_modules/nx/schemas/project-schema.json",
"sourceRoot": "./src",
"projectType": "application",
"targets": {
"build": {...},
"serve": {
"executor": "@nrwl/vite:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "awesomereactapp:build"
},
"configurations": {
"development": {
"buildTarget": "awesomereactapp:build:development",
"hmr": true
},
"production": {
"buildTarget": "awesomereactapp:build:production",
"hmr": false
}
}
},
"test": {...},
"lint": {...}
},
"tags": []
}
```
This is where you can see all the targets available for a given project, and you can [add your own](https://youtu.be/iygb-KhAeik)! In a Nutshell, an Nx target contains
- `executor` - a function (here `dev-server`) exposed by the plugin (here `@nrwl/vite`) to run the task at hand. Think of it as the wrapper of your usual Npm scripts
- `options` - this is where you can pass options to the `executor`
- `configurations` - allows you to create different versions of the `options` . You control which configuration is used by passing it via the `--configuration=production` flag to your commands. Also, note the `defaultConfiguration`.
You can go more in-depth if you want on the [Nx docs](/concepts/executors-and-configurations).
## Building the app
Just in the same way as serving our web app, we can build it with
```shell
npx nx build
```
This places an output into a `dist` folder. Now that we've seen the `project.json` targets, you probably guessed that you could customize that output folder directly in those settings.
## Testing the app
This setup also comes with testing baked in using [Vitest](https://vitest.dev/). And you probably guessed it, you can just run tests as follows:
```shell
npx nx test
```
## Running integration tests with Cypress
You might have noticed the `e2e` folder. That's a fully-functioning setup of [Cypress](https://cypress.io/) for doing integration-level or even full end-to-end tests.
This is excellent because you dont have to configure anything at all. No need to
- Cypress configured to use Vite (instead of Webpack)
- set up linting for the e2e project (yes writing good quality test code is just as important)
- spinning up our development server manually first that serves our React app such that we can load it in our Cypress tests environment
All we need to do is to use
```shell
npx nx e2e e2e
```
This might look weird initially, but basically, we run the `e2e` target (see `e2e/project.json`) on the `e2e` project.
```json {% fileName="e2e/project.json"" %}
{
"name": "e2e",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "e2e/cypress.config.ts",
"devServerTarget": "awesomereactapp:serve:development",
"testingType": "e2e"
},
"configurations": {
"production": {
"devServerTarget": "awesomereactapp:serve:production"
}
}
},
...
}
}
```
By default, these tests run in headless mode, but you can pass `--watch` to run it interactively with the Cypress test runner such that the tests get re-executed whenever we change our source.
> _Want Cypress Component testing? Theres an Nx generator that can help set that up. Check out the docs:_ [_/nx-api/react/generators/cypress-component-configuration_](/nx-api/react/generators/cypress-component-configuration)
## Linting
And similarly, linting can be triggered by running the following command:
```shell
npx nx lint
```
Theres a `.eslintrc.json` file already at the workspace's root that contains some best practices rules.
## Customize Vite and Vitest
The project setup is made in a way that you can easily customize your [Vite](https://vitejs.dev/) and [Vitest](https://vitest.dev/) setup. Just open the pre-generated `vite.config.ts` at the root of your workspace and add custom Vite plugins or fine-tune Vitest.
```typescript
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
server: {
port: 4200,
host: 'localhost',
},
plugins: [
react(),
viteTsConfigPaths({
root: './',
}),
],
// vitest config
test: {
globals: true,
cache: {
dir: './node_modules/.vitest',
},
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});
```
## Hidden gem: Caching
Nx is known for its caching that helps optimize the speed in monorepos. Caching takes the inputs (the command, source files, environment variables…) and computes a hash.
![](/blog/images/2023-01-12/0*Af7lMrhaO0gcIUeY.avif)
On every run, Nx compares that hash against a local cache folder. If the hash exists, Nx restores the command line output and potential artifacts (JS, CSS,… files) produced by a previous run. This helps speed up computation because you dont run it if you dont need to.
> _See Nx the docs for more info:_ [_/concepts/how-caching-works_](/concepts/how-caching-works)
While this obviously makes a lot of sense in a monorepo, it can also help **speed up single-project workspaces**. Most projects have multiple targets, such as `build`, `test`, `lint`. These can be cached! Imagine you have a PR where you change some `*.spec.ts` files because you add a test or fix some. Your CI script probably runs all the targets (`build`, `test`, `lint`) all the time. And it should totally do that. But you could avoid the `build` step because your spec file should not influence that outcome. As such, it could be restored from the cache. `test` needs to run and potentially also `lint` if you run linting also for spec files.
You can fine-tune what goes into the cache for each command. [More on the Nx docs](/recipes/running-tasks/configure-inputs)
## Hidden gem: Easily modularize your app
Imagine a storefront application. You will probably have domain areas like
- Product list — which would have facilities for listing all currently available products, their ratings, user reviews etc
- Orders — for viewing your currently open orders as a user or browsing past orders. Things like placing a new order or triggering a refund on a previously acquired product
- Payments — for handling the payment flow, asking for the credit card, triggering the payment, and starting the order placement process once the payment is successful
- Authentication — which handles the whole signup/login flow and provides lower-level utilities for other domain areas in the app, like getting access to the current user.
- User Profile — which manages everything user related. Think of it when you access Amazon and go to your account. Things like managing your addresses
- …
Were just scratching the surface here. This can become big quickly. The only way to manage such a structure with the current tooling (including CRA) is to organize these domains in folders. So youd have something like this in a CRA setup:
```
cra-app
├─ public/
├─ src/
│ ├─ authentication/
│ │ ├─ current-user/
│ │ │ ├─ ...
│ │ │ └─ index.ts
│ │ ├─ login/
│ │ └─ signup/
│ ├─ orders/
│ │ ├─ checkout/
│ │ ├─ place-order/
│ │ ├─ refund/
│ │ └─ order-list/
│ ├─ payments/
│ ├─ products/
│ ├─ user-profile/
│ │ ├─ addresses/
│ │ └─ credit-cards/
│ ├─ App.css
│ ├─ App.tsx
│ ...
├─ package-lock.json
├─ package.json
└─ README.md
```
Most devtools (including CRA) force you into a monolithic structure, where you divide your features into folders. Folders are limited in terms of isolation, though; as your application grows, this might quickly go out of hand.
We can impose a different, stronger structure with Nx by extracting these areas into dedicated libraries or modules. These live side-by-side with your application. Lets say we have a folder named “domains” which contains these domain areas. Then you can easily generate a new library with the following command:
```shell
npx nx g @nrwl/react:lib checkout --directory=domains/orders/checkout --bundler=none
```
The above command creates a new “ checkout “ library in the `domains/orders/` folder. Here's what it looks like:
```
awesomereactapp
├─ public
│ └─ favicon.ico
├─ src
│ ├─ app
│ ├─ ...
├─ domains
│ └─ orders
│ └─ checkout
│ ├─ src
│ │ ├─ index.ts
│ │ └─ lib
│ │ ├─ domains-orders-checkout.module.css
│ │ ├─ domains-orders-checkout.spec.tsx
│ │ └─ domains-orders-checkout.tsx
│ ├─ tsconfig.json
│ ├─ tsconfig.lib.json
│ ├─ tsconfig.spec.json
│ └─ vite.config.ts
├─ ...
├─ index.html
├─ package-lock.json
├─ package.json
├─ ...
├─ tsconfig.app.json
├─ tsconfig.base.json
├─ tsconfig.json
├─ tsconfig.spec.json
└─ vite.config.ts
```
Notice the `domains/orders/checkout/src/index.ts`: this is the public API of the `checkout` library where you can decide what to export and what should remain private within the library. This conscious process of selecting what to expose and what not leads to a much stronger encapsulation than just a folder structure. It also greatly helps with the maintainability aspect as your app grows.
When generating the library, a TypeScript path mapping is automatically created in the root-level `tsconfig.base.json`:
```json
{
"compileOnSave": false,
"compilerOptions": {
...
"paths": {
"@awesomereactapp/domains/orders/checkout": [
"domains/orders/checkout/src/index.ts"
]
}
},
"exclude": ["node_modules", "tmp"]
}
```
In this way, anything thats being exported from the `checkout` library can be consumed like
```typescript
import { SomeComponent } from '@awesomereactapp/domains/orders/checkout';
```
You can also just run linting or testing in isolation for these new libraries:
```shell
npx nx test domains-orders-checkout
```
And obviously, caching (as seen previously) would work on these new libraries as well.
> _Note,_ `_domains-orders-checkout_` _is the unique name of the project, composed by its file structure. You can change the name in the_ `_domains/orders/checkout/project.json_` _if you'd like._
## Hidden gem: Visualize your architecture
Another side-effect of splitting up your codebase into libraries is that your code structure and architecture emerge and becomes visible. Nx comes with a `graph` command built-in, so you can even visualize it:
```shell
npx nx graph
```
![](/blog/images/2023-01-12/0*lQqPKUstJg1JHD-f.avif)
It becomes even more interesting if you select the “Group by folder” checkbox as the domains become visible at that point:
![](/blog/images/2023-01-12/0*5s3J449vgsfYVLkL.avif)
> _Note this is a hypothetical app to demo some of the features of the Nx graph visualization. Some of the connections might only make a little sense._
## Hidden gem: Guard your boundaries
Scaling a software product is more than just the initial structuring and modularization. It consists of a constant ongoing process of ensuring modules stay in shape and dont contain any undesired cross-references or circular dependencies. You could leverage the Nx graph to verify that visually, but that doesnt scale.
To help with that, Nx has a built-in [module boundary lint rule](/features/enforce-module-boundaries). Projects can be assigned “tags”, like `type:domain`, `type:utils`, `type:shared` and `domain:products`, `domain:orders`, `domain:auth`. These tags can be assigned in the `project.json`, like
```json
{
// ... more project configuration here
"tags": ["domain:products", "type:domain"]
}
```
> _Note that_ `_type:domain_` _or_ `_domain:products_` _are really just strings. You can define them however you want._
In the `.eslintrc.base.json` you can then define the rules. Here for instance we're stating that a library of `type:utils` can only depend on other utility libraries, while a `type:domain` can depend on both, other domain libraries as well as utility libraries.
```json {% fileName=".eslintrc.base.json" %}
{
"overrides": [
{
"rules": {
"@nrwl/nx/enforce-module-boundaries": [
"error",
{
"depConstraints": [
{
"sourceTag": "type:utils",
"onlyDependOnLibsWithTags": ["type:utils"]
},
{
"sourceTag": "type:domain",
"onlyDependOnLibsWithTags": ["type: domain", "type:utils"]
},
{
"sourceTag": "domain:products",
"onlyDependOnLibsWithTags": ["domain:products", "domain:orders"]
}
]
}
]
}
}
]
}
```
If some of these lint rules need to be followed, your editor will show it right in your code, and you can also run lint checks for each PR on CI.
If youre curious, you can read more [here](/blog/mastering-the-project-boundaries-in-nx).
## Hidden gem: Just run what changed
In such a modular structure (as shown above) where your code is organized in smaller modules/libraries, it is very common that a given team member just works within a single domain area. Hence, very often PRs just touch a subset of the entire set of libraries. Nx comes with a backed-in command that allows you to take advantage of that on CI, using the so-called “[affected commands](/ci/features/affected)”.
Lets say we make a change in the `product-detail` library of our application. This would affect all other libraries that depend on it. You can also visualize it by running
```shell
npx nx affected:graph
```
![](/blog/images/2023-01-12/0*W_ttiuzGHhjnUC2I.avif)
To run tasks only for the affected areas, use:
```shell
npx nx affected:<target>
```
To make a concrete example, running just tests for those projects:
```shell
npx nx affected:test
```
## Hidden gem: A dedicated Editor extension
If you are not the “command line interface type” developer and youd rather prefer something integrated within your IDE, then theres good news. The Nx core team also ships a dedicated VSCode extension: [Nx Console](/getting-started/editor-setup).
It has a dedicated view within VSCode to trigger common commands, browse the workspace structure and even inline render the graph.
![](/blog/images/2023-01-12/0*ekMC03F1rFd_acmu.avif)
It also comes with contextual menus to quickly access most of the commonly used functionality:
![](/blog/images/2023-01-12/0*0wOJ7DPKcNV25D-V.avif)
Heres a walkthrough video showing some of the powerful capabilities of Nx Console:
{% youtube src="https://youtu.be/ZST_rmhzRXI" /%}
## Hidden gem: Automated Upgrades
To keep workspaces evergreen, Nx comes with automated code migrations that
- upgrade your `package.json` packages to the next version
- can automatically update your configuration files if necessary
- can automatically update your source files if necessary (in case of breaking changes in the API)
This allows for smooth transitions even if there are breaking changes. Just run
```shell
npx nx migrate latest
```
Nx gathers the currently installed packages and updates them to the latest version. If a package comes with Nx migration scripts, Nx collects them in a `migrations.json` file. You can inspect and then run them. This dramatically helps to keep your project tooling up to date.
Read more about how [Nx migrations work](/features/automate-updating-dependencies) on the docs.
## Using CRA? Automatically migrate to Vite + Nx
If youre currently on a [CRA](https://create-react-app.dev/) setup, you can easily migrate to an Nx + React + Vite-based setup by running the following command in your CRA project:
{% youtube src="https://youtu.be/zvYb7XCLQzU" /%}
```shell
npx nx init
```
Read more on the Nx docs: [/recipes/adopting-nx/adding-to-existing-project](/recipes/adopting-nx/adding-to-existing-project)
> _If for some reason you cannot migrate to Vite just yet, you can pass_ `_--vite=false_` _to keep a Webpack-based setup for now._
## Conclusion
Ready? Give it a try:
```shell
npx create-nx-workspace mycoolapp --preset=react-standalone
```
And let us know what you think :)
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
- 🧐 [Need help with Angular, React, Monorepos, Lerna or Nx? Talk to us 😃](/enterprise)

View File

@ -0,0 +1,116 @@
---
title: 'Nx Console meets Nx Cloud'
slug: 'nx-console-meets-nx-cloud'
authors: ['Max Kless']
cover_image: '/blog/images/2023-01-18/1*Mkqkadhkk7DydWvPg5L0bA.png'
tags: [nx]
---
We just released Nx Console 17.28.0 and it comes with a huge new feature: Nx Cloud Integration, right in VSCode! 🎉
In case youre not sure what it does, Nx Cloud takes your Nx workspace to the next level with awesome features like:
- **Remote Caching** — share your Nx cache with your coworkers and CI agents. By using Nx Cloud, you can be sure that no computation is done twice — throughout your company.
- **Distributed Task Execution** — the most important feature for truly scaling up repositories. Nx already knows about your project graph and what tasks depend on each other. With Nx Cloud, you can leverage this knowledge to distribute tasks smartly across multiple agents while making sure that everything is run in the correct sequence. This can speed up your CI times by orders of magnitude!
- **VCS \[version control system\]** **Integration** — see the results of your CI runs right on your pull request! Nx Cloud can talk to GitHub and other version control systems in real-time, giving you an overview of successes and failures as they happen.
And the best part? Its free! You wont pay anything for the first 500 hours of computation time saved per month. If you exceed 500 hours of computation saved, you can buy more; in the worst case, caching stops until the next month. For open-source projects, its free even beyond that. 😍
Head over to [http://nx.dev/nx-cloud](/nx-cloud) to learn more.
**Prefer a video walkthrough? Here we go**
{% youtube src="https://www.youtube.com/watch?v=WfWmK1x52HE" /%}
## Show me the new features already!
Now that were caught up, lets look at how Nx Console will make connecting to and working with Nx Cloud even easier.
To follow along, ensure you have installed the latest Nx Console version:
[Nx Console — Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)
In the Nx sidebar, you will see a new Nx Cloud section.
![](/blog/images/2023-01-18/1*JHNQd88EKmPVfnWBRqSidQ.avif)
If your workspace is not using Nx Cloud, click the “Set up Nx Cloud” button to set up the cloud runner automatically.
You will see that some changes happen in your `nx.json`:
```
"default": {
- "runner": "nx/tasks-runners/default",
+ "runner": "@nrwl/nx-cloud",
"options": {
+ "accessToken": "NDM2MmU2YmUtNDFl…ifHJlYWQtd3JpdGU=",
"cacheableOperations": [
"build",
"lint",
"test",
"e2e"
],
}
}
```
**Thats it. You can now use Remote Caching and Distributed Task Execution (DTE). 🎉**
## Running your first task
Lets try it out! Select a task to run and see the results in the run list. You can get an even more detailed breakdown in the Nx Cloud web app.
![](/blog/images/2023-01-18/1*hFG4lqGwEYV3imSFATeKog.avif)
If you rerun the same task, you can see that the time it took to complete is under a second. This is because of Nxs [advanced computation caching](/features/cache-task-results). Whenever a task is executed, Nx caches it. If the task has been run before, it just restores the result from the cache. By default, this cache is local to your own workstation. However, with Nx Cloud, you can distribute and share it between machines.
![](/blog/images/2023-01-18/1*kMKh30ojVJC-hSkZA5c46A.avif)
To see it in action, push your newly created access token and have a coworker (or CI pipeline) run a task on their machine. If you execute that same task again, it will be pulled from the cache just like it did locally! 🔮
![](/blog/images/2023-01-18/1*DkuIHQ6engBhAyhN1TTUGQ.avif)
To learn more about Nx Cloud access tokens, head over to the docs: [Access Tokens Documentation](/ci/recipes/security/access-tokens).
## Claiming your workspace
If youve just started using Nx Cloud, you will probably see this message prompting you to claim your workspace:
![](/blog/images/2023-01-18/1*vNRM1u3J5dixcXjoJWkHLQ.avif)
Out of the box, Nx Cloud works without the need to register. It is, however, highly recommended to create an account and associate it with your workspace. This process is called _claiming your workspace_ and has become much easier with Nx Console! After claiming, you can take full control of your cloud workspace, manage access restrictions and other settings.
Just click on Login and claim your workspace to be redirected to the browser where you can sign in to Nx Cloud or create an account. After successful authentication, you will come back to VSCode, where you can select one of your organizations and connect your workspace to it.
From now on, Nx Console will be able to make authenticated requests to the cloud API, so even if you choose to make your workspace private, logged-in users that are authorized to access it can do so.
## Distributed Task Execution
Distributed Task Execution (DTE) becomes very important as your workspace grows. With Nx, powerful features like [computation caching](http://√) and [affected analysis](/ci/features/affected) help you drastically cut down your CI times. Most of the time, large parts of your codebase will not need to be rebuilt and retested. However, we also have to consider the worst-case-scenarios. Lets say you do change a core lib that everything in your monorepo depends on. This could mean hundreds or even thousands of projects needing to be rebuilt and retested, which would mean hours of CI time. This is obviously very impractical and you should consider solutions that allow you to parallelize all this work and keep worst-case CI times at a reasonable level. [There are different approaches to achieving this](/ci/concepts/parallelization-distribution) but its hard to get right and not something most teams want to spend engineering resources on.
![](/blog/images/2023-01-18/1*EZhpRG2t-vp8Y7pGNnuRpA.avif)
Distributed Task Execution with Nx Cloud solves this issue — it allows you to optimally parallelize tasks without thinking about their interdependencies or agent management. You dont have to use it immediately, but its useful if you want to keep your CI times low even as your workspace grows. 🚀
DTE is available for all Nx Cloud workspaces with minimal setup. If you see a yellow DTE status in Nx Console, that just means you havent used it yet. [Check out the docs](/ci/features/distribute-task-execution) to [learn more about the motivation for DTE](/ci/concepts/parallelization-distribution) and [how to test it out in your workspace](/ci/features/distribute-task-execution).
![](/blog/images/2023-01-18/1*T-GAMsmUCVVeO2ZCGuO3WA.avif)
## VCS Integration
Nx Cloud isnt just great for its remote caching and DTE features, it also generates readable and searchable reports for any executed tasks — whether it be 10 or 10.000. In a monorepo, your CI pipelines will seldom run just a single task. Its more common to have commands like `nx affected — -target=build` which amounts to “rebuild everything that changed”. This could potentially be dozens, hundreds or thousands of tasks. If something goes wrong, combing through thousands upon thousands of lines of logs quickly becomes tedious. So having a nicely structured, per-target view that you can filter and sort while still preserving all terminal styling is incredibly useful!
![](/blog/images/2023-01-18/1*i-eyF1ED2_mBkB1A_4piqg.avif)
To take advantage of this valuable information without changing your development workflow, use the Nx Cloud integration for your favourite platform: Github, GitLab or Bitbucket Cloud. You can see the results of your cloud runs in a PR comment with an overview of failed tasks and links to easily readable outputs. No more scrolling through endless logs until you find what you need!
![](/blog/images/2023-01-18/1*UPAL-352xTPsm-Pf_7sROw.avif)
To set it up, just click on the button in the Nx Console cloud view and follow the prompts in your browser. Read more in the [full guide on connecting your workspace to](/ci/recipes/set-up/monorepo-ci-github-actions) VCS.
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](<[https://github.com/nrwl/nx](https://github.com/nrwl/nx)>)
- 🎮 [Nx Console GitHub](<[https://github.com/nrwl/nx-console](https://github.com/nrwl/nx-console)>)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](<[https://www.youtube.com/@nxdevtools](https://www.youtube.com/@nxdevtools)>)

View File

@ -0,0 +1,74 @@
---
title: 'Configuration Files and Potholes in Your Codebase'
slug: 'configuration-files-and-potholes-in-your-codebase'
authors: ['Isaac Mann']
cover_image: '/blog/images/2023-01-31/0*T-xiDccBOxMQpDrG.png'
tags: [nx]
---
Lets talk about configuration. The detractors call it boilerplate while proponents call it scaffolding or infrastructure. No matter what your feelings are, configuration code is all the setup that needs to be done before you can work on the features that actually accomplish something for your business. Like road maintenance, infrastructure code is often unnoticed when it is done well, but as soon as problems crop up, everyone feels the pain. How can this crucial configuration code be effectively maintained without dragging down the productivity of your development team?
## Less Configuration
There have been many attempts over the years to make it easier to bypass configuration code.
![](/blog/images/2023-01-31/0*RHP5AYxe6DD7UaYx.avif)
Ruby on Rails popularized the philosophy of Convention over Configuration. In this philosophy, the default configuration settings are derived from your folder structure or the way you name your files. These unwritten conventions are used as a way of bypassing writing configuration files that most of the time will follow a set pattern.
![](/blog/images/2023-01-31/0*y-gFItbtvrFYx9_3.avif)
Parcel advertises itself as a zero configuration bundler. This is mostly a reaction to webpack, which requires a fairly complex config file before it can do anything useful. As application grow more complex, so does the config file. These often become so complicated that developers dread fixing any problems with them, because once it becomes known that they have fixed a problem with webpack, they will be forever saddled with the burden of maintaining that file. In contrast, Parcel does all the tasks required of a typical SPA web app without any config file.
![](/blog/images/2023-01-31/0*-sWVhhyftTBiuMef.avif)
Apple also leveraged this sentiment with marketing slogan “It Just Works”. Compared to Windows or Linux ecosystems that require modifying settings to get software from different companies to work together, Apple provides its own suite of tools and hardware that have a major selling point of being intentionally designed to all work together. Theoretically, any hardware or software produced by Apple should fit seamlessly into the rest of the system.
All of these efforts to skip the configuration step reach their limits at some point. The idea of hiding default configuration works well, until you need to modify that default and have no starting point. The Zen of Python philosophy of “explicit is better than implicit” is a direct contradiction to Convention over Configuration. If you like most of what the zero config tool gives you, but you want to tweak it a little bit, it can be hard to find where to do the tweaking. Apple is great when It Just Works. But sometimes, It Just Doesnt.
![](/blog/images/2023-01-31/0*8f5YjBkc6SqPBA5E.avif)
## How much configuration is the right amount of configuration?
When your application is just getting started or when the configuration defaults work just fine for you, any time spent writing those defaults is wasted time and mental space. This applies to default configuration for initializing a project as well as default configuration for adding a new route or component in your application. When a developer is starting a new project or feature, we want their initial burst of energy to go as much as possible toward code that is valuable for the business, rather than code that is just infrastructure.
On the other hand, when the infrastructure code needs to be modified to make your application faster or modify the way the app behaves in some way, that infrastructure code needs to be easily accessible and clearly organized so that developers dont need to understand everything about the system before they can change a single part.
## Skip the Scaffolding
A cursory glance at the repos on Github will reveal numerous starter repos that people use to bypass the initial time investment involved in setting up the initial configuration files. Yeoman was a tool used to help generate scaffolding code, both for starting a project and for creating new sections of an application.
The problem with both of these tools is that any code they generate for you is instantly technical debt. By definition, no one in your company wrote the code that was created by those tools. But developers in your company will now have to maintain this code that they didnt write. Even if the starter project or Yeoman generator was well maintained and always used the latest state of art practices, any application built using them will only be state of the art the instant its created. The infrastructure code grows stale without constant maintenance.
## Nx Generators and Migration Generators
![](/blog/images/2023-01-31/1*p-fVnh5Cwp1rTZPhehl14g.avif)
Nx has an elegant solution to this dilemma. There are three key parts.
1. Use [code generators](/features/generate-code) to create configuration files that you can safely ignore
2. Modify those configuration files whenever your application needs some custom setting
3. Run [migration generators](/features/automate-updating-dependencies) to maintain state of the art defaults
If you never think about a configuration file is it still technical debt? Some people are put off by the number of configuration files that Nx generates when creating a new application. Perhaps these developers have been burned by starter repos burdening them with instant technical debt that must be maintained. These config files are created only for the eventuality that some day youll need to modify them.
When you do need to modify a setting for Webpack, Vite or Jest (or any of the other tools for which we maintain plugins) the configuration file provides you an easy access point to make your own modifications without needing to understand all the default settings.
Every Nx plugin provides migration generators that will automatically update the default settings to the latest state of the art. With these generators, Nx can take on the burden of maintaining your infrastructure code, except for the specific portions that your developers have customized.
## One Size Never Fits All
While the generators that Nx provides work for most people, there will always be infrastructure that is unique to your own organization. Nx makes it easy to extend generators so that your developers can use generators that create code that has been tailored to your own organizations set up. Instead of having a manual check list to run through every time a developer makes a new feature, you can automate that check list with a generator.
## Negative Configuration?
Nx provides the ability to define default configuration settings at the global level and have individual projects inherit those settings from the global defaults. If a lot of your projects have the same settings, adding Nx to your repo will actually reduce the lines of code in your codebase — thus negative configuration. This isnt convention over configuration or zero configuration, because the configuration settings are still explicitly defined. The configuration code is just better organized and defined in a predictable way.
If youre ready to have Nx help you manage your infrastructure so that your developers can speed down the highway without needing to avoid configuration potholes, check out [nx.dev](/getting-started/intro) to get started.
## Learn more
- [🧠 Nx Docs](/getting-started/intro)
- [👩‍💻 Nx GitHub](https://github.com/nrwl/nx)
- [💬 Nx Official Discord Server](https://go.nx.dev/community)
- [📹 Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)

View File

@ -0,0 +1,92 @@
---
title: 'Setup React and Tailwind — The Easy Way'
slug: 'setup-react-and-tailwind-the-easy-way'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2023-02-09/1*TK4Kdj-cc890gQkgUtKNyA.png'
tags: [nx, tutorial]
---
Developers love to argue about whether Tailwind is good, almost like arguing about code formatting or tabs vs. spaces (I use spaces!!). But whether you love it or hate it, Tailwind has found massive adoption among the frontend developer community. In fact, Im right now in the process of refreshing and rebuilding my personal site (it will be at [https://juri.dev](https://juri.dev/) soon, so keep an eye on that).
## Prefer a video? Ive got you covered!
{% youtube src="https://www.youtube.com/watch?v=hHh0xhzSnx8" /%}
## Configuring Tailwind for React
Tailwind has good docs around getting started quickly. There are options to set up Tailwind with their Tailwind CLI, PostCSS, and framework-specific guides.
![](/blog/images/2023-02-09/0*Z6SYFsnv-oA5FHz-.avif)
These steps mostly involve
- installing `tailwindcss`, `postcss` and `autoprefixer`
- configuring your `tailwind.config.js` to make sure Tailwind can properly "purge" its generated CSS file based on the content files (usually your `html`, `[j|t]sx`, `[t|j]s` )
- adjusting your main CSS file to include the Tailwind base classes (in case you want to use Tailwind also in your CSS files, a heated topic)
**One important thing:** if you use [Create-React-App](https://create-react-app.dev/) you might want to check out [what the Tailwind docs say](https://tailwindcss.com/docs/guides/create-react-app) first.
![](/blog/images/2023-02-09/0*tcPmgZM4SjA2QM80.avif)
This came up a couple of weeks ago due to a [PR opened on the CRA repo](https://github.com/reactjs/reactjs.org/pull/5487) asking to kinda deprecate it as the main choice for new React projects. I couldnt help but share my opinion on this as well:
{% youtube src="https://youtu.be/fkTz6KJxhhE" /%}
And so did also [Fireship](https://youtu.be/2OTq15A5s0Y) and ultimately [Dan Abramov](https://github.com/reactjs/reactjs.org/pull/5487#issuecomment-1409720741). Anyway, if youre in the **“CRA situation”, read on**. Theres a way to get unblocked there.
## There is an easier way — Code Generators
Code generators speed up such configuration tasks. They are valuable for scaffolding the initial project structure and adding new features to the app setup, such as Tailwind.
Nx has such generators. To use them, you need an Nx-based React setup. If youre starting new, you can create an [Nx Standalone React project](/getting-started/tutorials/react-standalone-tutorial) easily using the following command
```shell
$ npx create-nx-workspace reactapp --preset=react-standalone
```
![](/blog/images/2023-02-09/0*Zw73l-Hm4PBi1mBD.avif)
As you can see, this allows you to choose which bundler to use as well as other options (such as the CSS setup). Again, this is already such a code generator that creates this initial project scaffold.
Alternatively, **if you happen to use CRA already**, you can easily convert to an Nx and Vite (or also Webpack) based setup by running:
```shell
$ npx nx@latest init
```
You can pass `--vite=false` if you still want to keep the Webpack configuration or pass `--integrated` if you already plan to have a monorepo instead of a single-project setup. The [Nx docs go into more detail here](/recipes/adopting-nx/adding-to-existing-project).
## Generating a Tailwind Setup
Once you have a [Nx-based React](/getting-started/tutorials/react-standalone-tutorial) setup, adding Tailwind is as easy as running:
```shell
$ npx nx g @nrwl/react:setup-tailwind
```
This launches a generator that will guide you through the setup. It works **not only for Nx React-based projects** but **also if you use Next.js** in an Nx workspace.
Youll get
- Tailwind, PostCSS, and Autoprefixer installed
- Tailwind configured together with PostCSS
- your main `styles.css` file updated with the Tailwind base classes
![](/blog/images/2023-02-09/0*lOVFEvRc7Wrsm5V_.avif)
## Thats it!
You should be all setup and ready now! Here are some related resources to explore:
- [Nx docs: React Standalone tutorial](/getting-started/tutorials/react-standalone-tutorial)
- [Nx docs: React Monorepo tutorial](/getting-started/tutorials/react-monorepo-tutorial)
- [Youtube: Is CRA Dead](https://youtu.be/fkTz6KJxhhE)
- [Nx docs: Migrate CRA to React and Vite](/recipes/adopting-nx/adding-to-existing-project)
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)

View File

@ -0,0 +1,188 @@
---
title: 'Nx 15.7 — Node Support, Angular LTS, Lockfile Pruning'
slug: 'nx-15-7-node-support-angular-lts-lockfile-pruning'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2023-02-16/1*2AAo-mng7QyJP9yC80zNFQ.png'
tags: [nx, release]
---
Heres all you need to know about our latest Nx release.
### Table of Contents
· [10k Subscribers on Youtube](#10k-subscribers-on-youtube)
· [Updates to our Nx Plugin Guides](#updates-to-our-nx-plugin-guides)
· [Nx meets Node — First-Class Support landed](#nx-meets-node-firstclass-support-landed)
· [Detaching Angular versions](#detaching-angular-versions)
· [Bootstrapping a new Angular app with Standalone API support](#bootstrapping-a-new-angular-app-with-standalone-api-support)
· [Lockfile parsing and pruning](#lockfile-parsing-and-pruning)
· [Storybook 7.0 beta support](#storybook-70-beta-support)
· [More flexible Webpack config](#more-flexible-webpack-config)
· [How to Update Nx](#how-to-update-nx)
· [Coming up](#coming-up)
### Prefer a video? Weve got you covered!
{% youtube src="https://www.youtube.com/watch?v=IStJODzZSoc" /%}
## 10k Subscribers on Youtube
Its almost a tradition to have some stats at the beginning of our Nx release blog posts. This time, about our YT channel: incredibly, we crossed 10k subscribers [on our Youtube channel](https://www.youtube.com/@nxdevtools)!!
![](/blog/images/2023-02-16/0*s8uTPTC3X01sE3u2.avif)
Apart from delivering high-quality engineering work, were very invested in producing educational content around developer tooling and monorepos. Weve been almost consistently shipping new content every week, whether that is blog posts on the [Nx blog](/blog) or in the form of new videos and live streams on our channel. Seeing our audience grow on Youtube confirms were on the right track and gives us new fuel to keep pushing!!
If you havent subscribed yet, please do 🙏: [https://www.youtube.com/@nxdevtools](https://www.youtube.com/@nxdevtools). We also announce most of our new videos and live streams [on Twitter](https://twitter.com/nxdevtools).
## Updates to our Nx Plugin Guides
Nx has been designed to be extensible from the ground up. Which is precisely why Nx Plugins are so powerful. They dont just come as part of an Nx integrated monorepo or standalone setup. Still, you can leverage them in the same way to automate your local workspace or even share them as proper Nx plugins with the community.
Please have a look at our updated guide: [/extending-nx/tutorials/organization-specific-plugin](/extending-nx/tutorials/organization-specific-plugin)
## Nx meets Node — First-Class Support landed
{% youtube src="https://youtu.be/K4f-fMuAoRY" /%}
Due to a lack of time we never invested much more into streamlining the Node experience within Nx, though. This [changed now](/blog/from-bootstrapped-to-venture-backed), which is why were committed to making Nx the best developer tool for node based apps. Starting with v15.7 we improved support for [ExpressJS](https://expressjs.com/), [Fastify](https://fastify.io/) and [Koa](https://koajs.com/).
When starting a new Nx workspace, you now have a new option: “Standalone Node Server app”.
![](/blog/images/2023-02-16/0*yTl82iMY0EsbjmBQ.avif)
This is when you want a single-project Nx workspace to build out your Node backend.
All the features Nx is known for also apply to backend development. That includes
- **code generation support** for all the previously mentioned Node frameworks
- avoiding monolithic codebases via **modularizing it with local libraries** (with code generation support)
- Ability to **automatically setup a Dockerfile** for packaging your app
- **Optionally bundle** your Node app for easy deployment in the case of edge-functions
- **Speed** via running building, linting, testing for only **(**[**affected**](/ci/features/affected)**) parts of your applications**, via [caching](/concepts/how-caching-works) and [optimized CI setups](/ci/features/distribute-task-execution)
- the ability to use and/or expand to a monorepo
This is the first iteration with first-class Node support. But were already working on a whole set of improvements for the Nx + Node story. So stay tuned!
## Detaching Angular versions
{% youtube src="https://youtu.be/AQV4WFldwlY" /%}
The Angular CLI supports a single version of Angular and requires the user to upgrade them together with the help of automated upgrade mechanisms like `ng update`. On the other hand, Nx operates on a different release cycle and is independent of Angular versions. However, prior technical limitations resulted in each Nx major version only being compatible with a specific Angular major version. This caused challenges for Angular developers and corporations who were either stuck on an older Angular version or unable to upgrade promptly but still wanted access to the latest and greatest Nx features for increased productivity.
Starting with v15.7.0, the `@nrwl/angular` plugin will support both Angular v14 and v15, and our goal is to continue supporting the Angular LTS versions from Angular v14 onwards.
New workspaces will always be created with the latest Angular version, but during migration, you can skip some package updates as defined by Nx plugin authors. For Angular, this means you can skip migrating to newer versions. This feature can be enabled by running the following command in an interactive mode:
```
$ nx migrate latest --interactive
```
When collecting migrations in interactive mode, youll be prompted to apply any optional migrations, and any updates you choose to skip wont be applied. The rest of the updates will be used as usual.
If you need to apply an Angular update that you previously skipped, you can collect migrations from an older version of Nx by running:
```
$ nx migrate latest --from=nx@<version>
```
In particular, were working on making that part more intuitive in upcoming versions.
Also, have a look at our [updated docs](/recipes/tips-n-tricks/advanced-update) as well as our [Nx and Angular compatibility matrix](/nx-api/angular/documents/angular-nx-version-matrix) for more details.
## Bootstrapping a new Angular app with Standalone API support
{% youtube src="https://youtu.be/Hi3aJ0Rlkls" /%}
Angulars new [standalone APIs](https://angular.io/guide/standalone-components) is exciting as it provides a new, more lightweight way of developing and composing Angular applications without the need for `NgModules`. Nx has had the ability to generate new Angular components using the Standalone API for a while. With v15.7, we now also allow you to quickly bootstrap a new single-project Nx workspace with a NgModule-less Angular application.
```shell
npx create-nx-workspace@latest ngapp
--preset=angular-standalone
--standaloneApi
```
## Lockfile parsing and pruning
Lockfiles can be highly complex, and different formats across the NPM, Yarn, and PNPM package managers dont make it easier. Nx used to consider the lock-file a black box. Starting with 15.7, this changes! Nx can now properly process the lock-file of all three major package managers (and their different versions!).
Why is this useful? Glad you asked! Mostly for three reasons:
- more **accurately map the nodes and dependencies** in the Nx graph (yep the graph also includes npm packages used by every single project)
- generate a `package.json` with **precise snapshot of the used versions** (especially useful in a monorepo with single-version policy)
- ability to **generate a pruned lock-file** that can be used along-side the `package.json` when packaging your app in a Docker container
Some of our plugins `build` executors include:
- `generatePackageJson` flag (`@nrwl/webpack:webpack` and `@nrwl/node:webpack`) that automatically generates `package.json` and lock file.
- `generateLockfile` flag (`@nrwl/js:swc`, `@nrwl/js:tsc` and `@nrwl/next:build`) that generates lock file
If youre an Nx plugin developer, you can generate `package.json` and lock file using the following functions from the `@nrwl/devkit` package:
```
import { createPackageJson, createLockFile } from '@nrwl/devkit';
const projectGraph = await createProjectGraphAsync();
const packageJson = createPackageJson(projectName, projectGraph);
const lockFile = createLockFile(packageJson);
// save files using e.g. `fs.writeFileSync`
```
Stay tuned for a more in-depth blog post coming soon to [our blog](blog).
## Storybook 7.0 beta support
Nx provides support for Storybook version 7.0 beta, with generators and executors, so that you can try it out now, either in a new or in your existing Nx workspace. Storybook version 7 is a major release that brings a lot of new features and improvements. You can read more about it in the [Storybook 7 beta announcement blog post](https://storybook.js.org/blog/7-0-beta/). Apart from the new features and enhancements, it also brings some breaking changes. You can read more about them in the [Storybook 7 migration docs](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-65x-to-700) and the [Storybook 7 migration guide](https://chromatic-ui.notion.site/Storybook-7-migration-guide-dbf41fa347304eb2a5e9c69b34503937). Do note that _version 7 is still in beta_, and so is the Nx support for it.
You can try out Storybook 7.0 beta in a new Nx workspace by passing the `--storybook7betaConfiguration` flag when generating the Storybook configuration for your projects. Read more in our [Storybook 7 setup guide](/nx-api/storybook/documents/storybook-7-setup). If you want to migrate your existing Storybook configuration to Storybook 7.0 beta, please read our [migration guide](/nx-api/storybook/generators/migrate-7).
## More flexible Webpack config
{% youtube src="https://youtu.be/CIT4MFMraXg" /%}
Previously when you created a new React application with the Nx `@nrwl/react` plugin, the actual Webpack config was hidden within the plugin itself.
![](/blog/images/2023-02-16/0*1rWmKSybkBC8I-0O.avif)
It was for a good reason, but at the same time, it is a thin line to walk between giving more flexibility and ensuring integrity and consistency (not to speak about features such as [automated code migrations](/features/automate-updating-dependencies)). We wrote a [blog post about it last week](/blog/configuration-files-and-potholes-in-your-codebase).
Inspired by our new [Vite setup](/nx-api/vite), which allows for a more modular configuration in the `vite.config.ts`, we wanted to bring some of the same flexibility to our Webpack setup as well. As such, now every Nx Webpack setup (e.g. a new React + Webpack based app) have a `webpack.config.js` in the project root. Old project are automatically migrated to this new setup.
![](/blog/images/2023-02-16/0*emRP2gF7umWc4UE-.avif)
If you want to upgrade but still retain the previous behavior, we introduced an `isolatedConfig` mode that can be set to `false`. More details on our docs: [/recipes/webpack/webpack-config-setup](/recipes/webpack/webpack-config-setup)
## How to Update Nx
Updating Nx is done with the following command and will update your Nx workspace dependencies and code to the latest version:
```shell
npx nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
npx nx migrate --run-migrations
```
## Coming up
We are currently working on some exciting stuff, including
- Deno support
- Improvements to Nx Console, including support for IntelliJ
- NestJS
- Rust 👀
- Nx for non-JS environments
- …
So keep an eye on our [Twitter](https://twitter.com/nxdevtools), [Youtube](https://www.youtube.com/@nxdevtools) and [blog](/blog) to not miss those announcements.
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/nrwl_io)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)

View File

@ -0,0 +1,181 @@
---
title: 'Using NgRx Standalone APIs with Nx'
slug: 'using-ngrx-standalone-apis-with-nx'
authors: ['Colum Ferry']
cover_image: '/blog/images/2023-02-21/1*pJHhA04d6jIjOb5vpCDjyw.png'
tags: [nx, tutorial]
---
Version 15 of [NgRx](https://ngrx.io/) introduced Standalone APIs to the package, enabling usage of the NgRx with Standalone Component-based [Angular](https://angular.io/) applications. This allows for a simpler integration of NgRx to your application.
Nx has added support for using these Standalone APIs from NgRx when generating NgRx stores with our `@nrwl/angular:ngrx` generator when you give it a path to a `Routes` definition file. _(Usually denoted by_ `_*.routes.ts_`_)_
In this article, well walk through using Nx to create a new Standalone Component-based Angular application and add NgRx to it, using _ONLY_ Nx Generators!
**Prefer a video version? Weve got you covered!**
{% youtube src="https://www.youtube.com/watch?v=fp9E5G9C61Q" /%}
## Create a new Nx Workspace
`npx create-nx-workspace myorg`
Select:
- Standalone Angular app
- Yes to using Standalone Components
- Yes to add routing
- Any option for the stylesheet format
- Yes to Nx Cloud
The result should look something like this:
![](/blog/images/2023-02-21/0*-91CdqmMaqFjMDVK.avif)
Now run `cd myorg` to enter the workspace.
The `src/main.ts` should look different than you remember with standard NgModule-based Angular applications.
You should see something similar to
```
import { bootstrapApplication } from '@angular/platform-browser';
import {
provideRouter,
withEnabledBlockingInitialNavigation,
} from '@angular/router';
import { AppComponent } from './app/app.component';
import { appRoutes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: \[provideRouter(appRoutes, withEnabledBlockingInitialNavigation())\],
}).catch((err) => console.error(err));
```
This is important, as this is the file where your root NgRx providers need to be placed, within the `providers` option of the `bootstrapApplication` function.
Nx will aid this also!
## Generate the root state
`nx g @nrwl/angular:ngrx --root --parent=src/main.ts`
Youll be asked for a name for the feature state, but you can ignore this and simply press enter in your terminal, it is not necessary at this stage.
Say false to Facades also.
![](/blog/images/2023-02-21/0*6igpc5F6dk9UMswf.avif)
The generator will now make changes to your `main.ts` file and install the NgRx packages for you!
Your `main.ts` file should now look like this
```
import { bootstrapApplication } from '@angular/platform-browser';
import {
provideRouter,
withEnabledBlockingInitialNavigation,
} from '@angular/router';
import { AppComponent } from './app/app.component';
import { appRoutes } from './app/app.routes';
import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
bootstrapApplication(AppComponent, {
providers: \[
provideEffects(),
provideStore(),
provideRouter(appRoutes, withEnabledBlockingInitialNavigation()),
\],
}).catch((err) => console.error(err));
```
Notice the addition of `provideEffects()` and `provideStore()` to the `providers` array.
## Generate a new feature library
NgRx works better when you split your store based on the features you have within your application. This is a pretty common use case. Nx allows you to do this very easily and in a very structured way.
First, lets generate a new feature library, called `feature-users`, in Nx that will house everything related to our feature including the NgRx State.
`nx g @nrwl/angular:lib feature-users --standalone --routing --lazy --parent=src/app/app.routes.ts`
This command does a few things:
- It creates a new library in our Nx Workspace
- It uses an Angular Standalone Component as the entrypoint
- It adds a routing configuration to the library and adds the component as the default route.
- It will add a lazy-loaded route to the applications `app.routes.ts` file, wiring up the application to the library!
Some files you may want to explore in your own time are:
`src/app/app.routes.ts`
`feature-users/src/lib/lib.routes.ts`
## Add feature state to the feature library
Now that we have a feature library for our users feature, lets generate the feature state! Its as simple as one command.
`nx g @nrwl/angular:ngrx users --parent=feature-users/src/lib/lib.routes.ts --route=''`
Youll be asked if this is the root state of the application, enter `N`. Then say no to Facades (unless you really want them).
The `--route` option here is used to dictate what `route` within our routes definition file (`lib.routes.ts`) should have the state attached to it. This is to allow the NgRx Standalone APIs to be attached to that route.
We can see that if we look at the `lib.routes.ts` file
```
import { Route } from '@angular/router';
import { FeatureUsersComponent } from './feature-users/feature-users.component';
import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import \* as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
export const featureUsersRoutes: Route\[\] = \[
{
path: '',
component: FeatureUsersComponent,
providers: \[
provideState(fromUsers.USERS\_FEATURE\_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
\],
},
\];
```
The command will also have generated our
- Actions
- Reducers
- Selectors
- Effects
And with that, we now have NgRx installed and integrated into our application!
If youd like to confirm the integration, you can run the following commands and see successful outputs!
`nx build`
`nx test`
`nx test feature-users`
## Conclusion
This guide has shown how easy it is to set up NgRx with Nx and how to take advantage of the latest Standalone APIs with your application. All with just 5 Nx commands!
With the Angular roadmap pointing to Standalone Components becoming the preferred option for developing Angular applications, this support will be crucial in the future, and Nx will help you achieve it with the best possible DX!
> Btw, did you know you can now scaffold a single-project Angular Nx workspace that fully leverages the Standalone APIs? Check it out here: [https://youtu.be/Hi3aJ0Rlkls](https://youtu.be/Hi3aJ0Rlkls)
You can check out an example repository that was created following the steps above here: [https://github.com/Coly010/nx-ngrx-standalone](https://github.com/Coly010/nx-ngrx-standalone)
## Learn More
🧠 [Nx Docs](/getting-started/intro)
👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
💬 [Nx Official Discord Server](https://go.nx.dev/community)
📹 [Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)
🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
🧐 [Need help with Angular, React, Monorepos, Lerna or Nx? Talk to us 😃](https://nx.app/enterprise)

View File

@ -0,0 +1,126 @@
---
title: 'Whats New With Lerna 6.5?'
slug: 'whats-new-with-lerna-6-5'
authors: ['Zack DeRose']
cover_image: '/blog/images/2023-02-22/1*izlWzEYnkZ9myXi58Rmv8A.png'
tags: [nx, release]
---
In case you missed it, Lerna version 6.5 recently launched. Well catch you up on the latest Lerna news and newest features.
## Table of Contents
- [Lerna: Brought to You by Nx](#lerna-brought-to-you-by-nx)
- [Still On Lerna 4?](#still-on-lerna-4)
- [Idempotency Added to the `lerna publish from-git` Command](#idempotency-added-to-the-lerna-publish-fromgit-command)
- [`lerna run` Can Run Multiple Scripts In a Single Command](#lerna-run-can-run-multiple-scripts-in-a-single-command)
- [New --include-private Option Added To lerna publish](#new-includeprivate-option-added-to-lerna-publish)
- [Massive Refactor](#massive-refactor)
- [Getting Started With Lerna From The Lerna Team](#getting-started-with-lerna-from-the-lerna-team)
- [The Future of Lerna](#the-future-of-lerna)
## Lerna: Brought to You by Nx
In case you missed it, Lerna, the OG JavaScript monorepo tool, went largely unmaintained for a while, starting around 2020. Then, it officially declared itself to be unmaintained in April of 2022, only for Nx to step in to take over maintenance of the project in May of 2022!
You can find a more detailed account of Lernas “Maintainance Odyssey” in [this article](/blog/lerna-is-dead-long-live-lerna).
Since Nx took over in Lerna 4, weve added a brand new site to refresh the Lerna Docs:
![](/blog/images/2023-02-22/0*3GKvhzStrTwq7re5.avif)
The top of our priorities for Lerna 5 was to resolve all vulnerabilities and outdated dependencies facing Lerna. We went on to make Lerna faster by allowing users to [opt into Nxs task caching inside of Lerna with the new `lerna add-caching` command](https://github.com/lerna/lerna/tree/main/packages/lerna/src/commands/add-caching#readme), and [add support for distributed caching to share task results amongst your organization in Lerna with Nx Cloud](https://lerna.js.org/docs/features/share-your-cache).
We were proud to go on to launch [Lerna 6](/blog/lerna-reborn-whats-new-in-v6) last October, where we began focusing on further improving Lernas feature set — focusing specifically on its unique strengths: versioning and publishing.
## Still on Lerna 4?
[Heres how to upgrade to the latest and greatest](https://lerna.js.org/upgrade).
Weve also started an initiative to assist Open Source projects in getting the most out of Lerna. Projects that use Lerna can now request free consulting to learn how to take advantage of Lernas newest features.
Weve just started this initiative and have already been able to help [Sentry](https://github.com/getsentry/sentry-javascript) get optimized with task caching and task pipeline optimizations for their workspace!
![](/blog/images/2023-02-22/0*7Wu1y3L6BNPZmZwE.avif)
This initiative complements [our free tier of unlimited Nx Cloud](/pricing) for any Open Source project.
If youre interested in optimizing your Open Source project to take advantage of the latest Lerna features, [reach out to us on Twitter!](https://twitter.com/lernajs)
Now lets jump into the newest Lerna 6.5 features!
## Idempotency Added to the `lerna publish from-git` Command
{% youtube src="https://youtu.be/kh4TaiKbC8c" /%}
“Idempotent” is a word used to describe an operation you can perform any number of times, and the resulting state is the same as if you had only run the operation once.
The [`lerna publish` command](https://github.com/lerna/lerna/tree/main/libs/commands/publish#readme) is a beneficial tool for quickly publishing multiple packages from your workspace:
- Running `lerna publish` by itself will version and publish all packages in the workspace since your latest release
- Running `lerna publish from-git` will publish all projects tagged in the latest commit
- Running `lerna publish from-package` will publish all projects whose version does not yet exist in the target registry based on the version listed in their `package.json` file.
As we can see, `lerna publish from-package` is already idempotent (since it only publishes packages whose version doesn't exist, any run past the first will not adjust the state of the registry).
With 6.5, weve added the same idempotency to `lerna publish from-git`. This update is handy for recovering from a situation where some of your packages failed to publish initially (maybe due to a networking issue).
[For more information, check out the PR](https://github.com/lerna/lerna/pull/3513)
## `lerna run` Can Run Multiple Scripts In a Single Command
For 6.5, weve added the ability to run multiple scripts in a single `lerna run` command! Checkout this quick video demonstrating this below:
{% youtube src="https://youtu.be/Ey73CEGcVKw" /%}
Learn more [here](https://github.com/lerna/lerna/pull/3527).
## New `--include-private` Option Added To `lerna publish`
[Npm supports a `["private": true]` configuration](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#private) as a way of preventing the publication of a library that is private.
```shell
lerna publish from-git --include-private my-private-package
```
Running `lerna publish` with this new [`--include-private`](https://github.com/lerna/lerna/tree/main/libs/commands/publish#--include-private) option (as above) will strip this `"private": true` configuration from the `package.json` of the packages listed in the command.
This new option is beneficial for the use case where youd like to run e2e for a package that will eventually be public but is currently private to prevent getting published too soon.
{% youtube src=" https://youtu.be/7TgjCk7Diks" /%}
You can find more information on this change [here](https://github.com/lerna/lerna/pull/3503).
## Massive Refactor
Unlike the other updates mentioned for 6.5, this update does not affect Lernas public API, but as you can see from the numbers, this was quite an undertaking:
![](/blog/images/2023-02-22/0*AKQyRtbrKzzOUdPZ.avif)
![](/blog/images/2023-02-22/0*GUSOJi5vj5fGYYj3.avif)
The result is a significant improvement to the Typescript support for Lernas internals and a substantial simplification of the codebase. This investment will make Lerna significantly more approachable to other would-be contributors!
Find more on this change [here](https://github.com/lerna/lerna/pull/3517).
## Getting Started With Lerna From The Lerna Team
We recently ran a live stream with [James Henry](https://twitter.com/MrJamesHenry) and [Austin Fahsl](https://twitter.com/AustinFahsl) from our Lerna team to show how to get started with Lerna, all the way through to versioning and publishing our packages to npm!
{% youtube src="https://youtu.be/HqPOoU35xzA" /%}
Check out the recap of this session above, and check out [the repo from our session on GitHub](https://github.com/ZackDeRose/for-the-lulz).
## The Future of Lerna
Looking to the future, we are targeting Q2 of 2023 for Lerna v7 (including a `--dry-run` option for both `lerna version` and `lerna publish` commands - you can catch a sneak-peak of this in James' talk from Nx Conf 2022 below!)
{% youtube src="https://youtu.be/CNdDv2MsBuw" /%}
You can find [a roadmap for all the features we plan to add in Lerna 7](https://github.com/lerna/lerna/discussions/3410) on Github!
## Lerna More!
- [🧠 Lerna Docs](https://lerna.js.org/)
- [👩‍💻 Lerna GitHub](https://github.com/lerna/lerna)
- [💬 Nx Official Discord Server](https://go.nx.dev/community)
- [📹 Nrwl Youtube Channel](https://www.youtube.com/nrwl_io)

View File

@ -0,0 +1,248 @@
---
title: 'Bundling a Node API with Fastify, esbuild, and Nx'
slug: 'bundling-a-node-api-with-fastify-esbuild-and-nx'
authors: ['Jack Hsu']
cover_image: '/blog/images/2023-02-28/1*PADY_RKrkXj39p4nj79ESw.png'
tags: [nx, tutorial]
---
There are many decisions to make when it comes to building a Node API. There are a variety of frameworks to choose from (Express, Fastify, Koa, etc.), and a million different ways to build and deploy the application.
In this article, Ill show you the easiest way to go from zero to production by using Nx to create a Node API project.
Well be using [Fastify](https://www.fastify.io/) as the framework of choice. Fastify is a fast (as the name implies) and low-overhead server in Node. It has grown in popularity, recently crossing the 1 million weekly download mark on npm. Im a fan of Fastifys plugin architecture, and the ecosystem is quite impressive, boasting over [250 core and community plugins](https://www.fastify.io/ecosystem/).
## **Table of Contents**
· [Creating the project](#creating-the-project)
· [Running tests](#running-tests)
· [Building for production using esbuild](#building-for-production-using-esbuild)
· [Docker support](#docker-support)
· [Deploying the server](#deploying-the-server)
· [Summary](#summary)
**Prefer a video version? Weve got you covered!**
{% youtube src="https://www.youtube.com/watch?v=K4f-fMuAoRY" /%}
## Creating the project
You can create a new API with a single command.
```shell
$ npx create-nx-workspace@latest \
--preset=node-standalone \ # create a Node.js project
--framework=fastify \ # other options are express and koa
--docker # we'll touch on this later on
```
To run the server in dev-mode, use `npx nx serve` (aliased to `npm start`), and you should see the server starting at port 3000.
```
$ curl <http://localhost:3000>
{"message":"Hello API"}
```
A couple of notable files:
- The `src/main.ts` file is responsible for starting the Fastify server and registering plugins.
- The `src/app/app.ts` file is the app plugin that provides an initial endpoint at `/` that replies with `{"message": "Hello API"}`.
When you edit the source code, the server will reload. You can pass `--no-watch` to disable this behavior.
## Running tests
In additional to generating the source code, Nx will also create two test suites:
1. Unit tests via `npx nx test` (aliased to `npm run test`).
2. E2E tests via `npx nx e2e e2e` (aliased to `npm run e2e`).
Unit tests take advantage of Fastifys plugin architecture, and allows you to test each plugin in isolation. It runs using [Jest](https://jestjs.io/), which is the most popular test runner in Node.
```
// src/app/app.spec.ts
// This file is generated by Nx.
import Fastify, { FastifyInstance } from 'fastify';
import { app } from './app';
describe('GET /', () => {
let server: FastifyInstance; beforeEach(() => {
server = Fastify();
server.register(app);
}); it('should respond with a message', async () => {
const response = await server.inject({
method: 'GET',
url: '/',
}); expect(response.json()).toEqual({ message: 'Hello API' });
});
});
```
The E2E tests run against the actual server (with all plugins registered), which gives better real-world guarantees.
```shell
$ npx nx serve & # run server in background
$ npx nx e2e e2e # run test suite
GET /
✓ should return a message (27 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.429 s
Ran all test suites.Tearing down... ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— >
NX Successfully ran target e2e for project e2e (3s)$ lsof -i:3000 -t | xargs kill # stop server process
```
There are trade-offs between speed versus confidence when it comes to unit versus E2E tests, which is a topic that is out of scope for this article. I think you should do both, but this is a discussion be held with your team. Nx supports both cases out of the box.
## Building for production using esbuild
Now that we have our production-ready app, lets examine how Nx handles the build process using [`esbuild`](https://esbuild.github.io/).
`esbuild` is a bundler written in Go that is extremely fast — it is much faster than other bundlers like webpack and parcel, but that may change in the future as other tools make their own speed improvements.
When you run the build command, Nx uses `esbuild` to generate a self-contained app bundle, which does not require `node_modules`.
```shell
$ npx nx build # aliased to npm build
> nx run api:build
—————————————————————————————————————————————————————
NX Successfully ran target build for project api (2s)
```
A cool feature of Nx, is that commands such as `build` and `test` are cached if the project (or its dependencies) have not changed. If we run the build a second time, youll see it completes in a few milliseconds.
```shell
$ npx nx build
> nx run api:build # existing outputs match the cache, left as is
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— >
NX Successfully ran target build for project api (16ms) Nx read the output from the cache instead of running the command for 1 out of 1 tasks.
```
Well touch more on the caching when we look at Docker support.
And now that the server bundle is ready, we can run it.
```
$ node dist/api
{"level":30,"time":1675880059720,"pid":70605,"hostname":"mbp.lan","msg":"Server listening at http://\[::1\]:3000"}
{"level":30,"time":1675880059721,"pid":70605,"hostname":"mbp.lan","msg":"Server listening at <http://127.0.0.1:3000>"}
[ ready ] <http://localhost:3000>
```
You can even run the e2e suite against the production bundle: `npx nx e2e e2e`.
## Docker support
Recall that we passed the `--docker` option when creating the API project. WIth this option, Nx will generate a default `Dockerfile` and a `docker-build` target.
```shell
# This file is generated by Nx.
#
# Build the docker image with `npx nx docker-build api`.
# Tip: Modify "docker-build" options in project.json to change docker build args.
#
# Run the container with `docker run -p 3000:3000 -t api`.
FROM docker.io/node:lts-alpine
ENV HOST=0.0.0.0
ENV PORT=3000WORKDIR /appRUN addgroup --system api && \
adduser --system -G api apiCOPY dist/api api
RUN chown -R api:api .CMD [ "node", "api" ]
```
To build the image, run `npx nx docker-build`. The image copies only the self-contained bundle, so no `npm install` at all!
Nx is smart enough to bundle the app before building the Docker image — because of the `dependsOn` configuration in `project.json`. You can visualize this dependency with `npx nx graph`.
![](/blog/images/2023-02-28/1*HRfoF6hPy-XH-MSL42PSIQ.avif)
Now that the image is built, we can run it.
```
$ docker run -p 3000:3000 -t api
{"level":30,"time":1675880993256,"pid":1,"hostname":"248744de020a","msg":"Server listening at <http://0.0.0.0:3000>"}
[ ready ] <http://0.0.0.0:3000>
```
**Note:** The server binds to `0.0.0.0` so that it can be access from the host machine. You can run curl to verify that it indeed works, or better yet use the E2E test suite (`npx nx e2e e2e`)!
## Deploying the server
There are numerous platforms that we can deploy our app to. I like [Fly.io](https://fly.io) since it very easy to deploy all over the world using the CLI, and it comes with good [Docker support](https://fly.io/docs/languages-and-frameworks/dockerfile/).
If you havent used Fly before, please follow their [short getting started guide](https://fly.io/docs/speedrun/) (510 mins).
Once you are ready, lets configure our project.
```
$ fly launch --generate-name --no-deploy
```
Follow the prompts and a `fly.toml` file will be generated, which contains the Fly configuration. We need to update this file with the correct port used by our image.
```
[[services]]
http_checks = []
internal_port = 3000 # Make sure this matches what the app listens on
```
Now we can deploy the app.
```
$ fly deploy
```
Fly will log out the monitoring link when the app is successfully deployed.
![](/blog/images/2023-02-28/1*oAuTGrLZCV87OEC0e-6KpQ.avif)
And you can open the deployed server using `fly open`.
![](/blog/images/2023-02-28/1*tV8aAtjRoRMwlj1Tv17IAw.avif)
Thats it! Our server is now deployed for the world to use.
## Summary
In this post, we saw how easy it is to go from zero code to a deployed server using Nx. Here is a quick summary of the points.
1. Use `create-nx-workspace --preset=node-standalone --framework=fastify --docker` to quickly create a Fastify server project.
2. Nx provide both unit test and E2E test suites — `npx nx test` and `npx nx e2e e2e`.
3. Nx builds the server using esbuild — `npx nx build`.
4. Docker support is provided out of the box via the `--docker` option, and Nx understands that Docker build depends on the app to be bundled. Run it via `npx nx docker-build`.
5. Deploying to Fly (or other platforms) is easy since we have a Docker image.
To learn more about Nx and what else it can do, refer to the [intro page](/getting-started/intro) in the docs.
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -0,0 +1,234 @@
---
title: 'Expanding Nx Console to JetBrains IDEs'
slug: 'expanding-nx-console-to-jetbrains-ides'
authors: ['Max Kless']
cover_image: '/blog/images/2023-03-02/1*lEAhfd3d17hGichyT-oGbw.png'
tags: [nx]
---
**_Co-authored by_** [**_Jon Cammisuli_**](https://twitter.com/jcammisuli)
Nx Console has been on the Visual Studio Code marketplace for years, and with over 1.2 million downloads, we know that a
lot of folks enjoy using it for their day to day Nx related tasks.
That makes it even more **exciting for us to officially announce that Nx Console is now available for JetBrains IDEs**!!
Go grab it on the official store.
👉 **Install link:
** [https://plugins.jetbrains.com/plugin/21060-nx-console](https://plugins.jetbrains.com/plugin/21060-nx-console)
![](/blog/images/2023-03-02/1*gnMRzttFFaoTX0tVw-zZbQ.avif)
Before we go into details of Nx Console for IntelliJ, wed really want to go and **thank our community**. [\* \*_Issam Guissouma_\*\*](https://twitter.com/iguissouma) and [**_Edward Tkachev_**](https://twitter.com/etkachev) from the
Nx community had their own Nx Console plugins for IntelliJ out there already for a while. And they have been super
popular. As such wed like to take the occasion to give them a shout-out for the awesome work on the community plugins,
but also for closely collaborating with us over the last weeks to build our official IntelliJ support for Nx Console.
Especially Issam has been actively helping us port over all the features he built to the official Nx Console plugin. So
be sure to look out for the upcoming release because its going to be another huge one!
### Table of Contents
· [Going from one IDE to two](#going-from-one-ide-to-two)
· [Nx Language Server](#nx-language-server)
· [Generate UI](#generate-ui)
· [Communicating with IntelliJ](#communicating-with-intellij)
· [Adapting Styling](#adapting-styling)
· [JCEF](#jcef)
· [Glueing it together](#glueing-it-together)
· [Looking ahead](#looking-ahead)
**Prefer a video version? Weve got you covered!**
{% youtube src="https://www.youtube.com/watch?v=xUTm6GDqwJM" /%}
## Going from one IDE to two
Nx Console has a ton of features to improve your development experience while working on Nx and Angular repos, some
small and some big.
To provide the most value from the get-go for JetBrains users, we first focused on integrating two main areas: The Nx
Language Server and the Generate UI.
**The Nx Language Server (nxls)** is based on
the [Language Server Protocol (LSP)](https://microsoft.github.io/language-server-protocol/). It serves as a single
source of truth for all information about your workspace and its projects. With it, you get features such a code
completion for `project.json` and `nx.json` files, clickable links for all kinds of files and more. Being a standalone
process, its editor-agnostic per default, which is great! However, IntelliJ doesnt natively support the language
server protocol yet, so we had to write some code that bridges the gap between the two. More about that in the following
section!
The great thing about having a central “brain” for both extensions is that it saves a lot of time writing the same
functionality multiple times. We only have to deal with platform-specific code for rendering UI or defining actions
instead of parsing `nx.json` files and the like. This makes both VSCode and IntelliJ extensions thin, DRY wrappers
around the nxls.
Another major part of Nx Console is the **Generate UI**. Instead of combing through CLI commands to fit your specific
use-case, you can use the form-based view it provides. Its a separate web application (currently built with Angular)
that runs inside VSCode as a webview. Again, being a standalone application means that we didnt have to rewrite it
completely in order to integrate it into JetBrains-based editors!
## Nx Language Server
Development of the Nx Language Server (nxls) began as a way to provide autocompletions in Nx specific files. But we came
to the realization that the `nxls` could also provide much more information.
The language server is a separate process that is called by the running IDE (that being VSCode, and now Intellij) that
communicates via json rpc.
With the Language Server Protocol, there are certain methods that are called between the IDE and the language server,
such as
[`textDocument/completion`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion)
that must be implemented.
When the `nxls` does Language Server Protocol related things (like autocomplete), it uses the local workspace copy of Nx
to get information about the workspace. Since this workspace information is already loaded in memory, it presented a
solution to just use that same workspace info in the IDEs without us having to rewrite this logic in multiple
languages (ie, TypeScript and Kotlin).
We found out quickly that we can implement custom requests within the `nxls` to respond to other queries that arent
actually part of the Language Server Protocol. These requests are what allows us to use the `nxls` in multiple IDEs and
allow us to quickly iterate.
One of these custom requests is
[`nx/workspace`](https://github.com/nrwl/nx-console/blob/756fdfb545de413436193227d273d078628d7829/libs/language-server/types/src/index.ts#L18-L23).
Calling this endpoint gives us the same information that you can find when you run `nx graph --file=output.json`. (Plus
a little more information that is needed for IDEs 🙂)
There are more custom requests that are implemented that help with IDE integration, some of these include:
- Nx version
- Available generators
- Finding projects based on file paths
You can see all the custom requests
on [Github](https://github.com/nrwl/nx-console/blob/756fdfb545de413436193227d273d078628d7829/libs/language-server/types/src/index.ts).
**VSCode**
Language Server Protocol support is built into the core of VSCode, so using the language server there was straight
forward. Previously the logic to get workspace information was just part of the VSCode extension. This was the logic
that moved to the `nxls` .
**IntelliJ**
For JetBrains editors (IntelliJ/Webstorm), calling a language server wasnt so obvious.
Thankfully, there were already plugins that integrated language servers using
the [lsp4j](https://github.com/eclipse/lsp4j) library. This was a great starting out point for us and we quickly got
IntelliJ/Webstorm to boot up `nxls` and start sending requests.
In future versions of IntelliJ/Webstorm, language server support is going to be fully baked into the core of the IDE
using the same lsp4j library. This means that we can remove some of the scaffolding that we had to do to get it working
without the core support.
## Generate UI
![](/blog/images/2023-03-02/0*-BMjrO5LdBCWK2TU.avif)
_Screenshot of the generate UI in IntelliJ_
As mentioned, the generate UI is a key feature of Nx Console. It allows users to easily generate code by using a
form-based view, rather than having to remember and type a series of CLI commands.
For VSCode, the only way to add a custom UI like this is to render it from inside
a [webview](https://code.visualstudio.com/api/extension-guides/webview) — similar to an iframe. IntelliJ provides the
functionality to build more complex native UIs. However, this would mean rewriting everything from scratch: how to
process Nx schemas, how to render each kind of field, validation and more. And then, each change to the UI would have to
be made in two places, greatly increasing the maintenance overhead and complexity of the codebase. This is why we
decided to reuse the existing generate UI for IntelliJ.
The generate UI is a standalone app written in Angular. It consists of a few components for the different field types
and a main component that deals with processing the schema, filtering fields and communicating with the IDE. This entire
component was quite tightly coupled with VSCode in two regions: receiving and sending data to the IDE and styling.
Naturally, these aspects had to be refactored out in order to accommodate a new host IDE.
## Communicating with IntelliJ
First, we ripped out all VSCode-specific code from the main component and moved it to a separate
[`ide-communication.service.ts`](https://github.com/nrwl/nx-console/blob/f7de7f9d1f7ae5f59b0605b2e54ef28e6325e839/libs/generate-ui/feature-task-execution-form/src/lib/ide-communication/ide-communication.service.ts#L91).
Communication with the host IDE is now done via one of two methods:
- for VSCode, we continue to use the straightforward (
and [fully typed](https://www.npmjs.com/package/@types/vscode-webview)) `acquireVsCodeApi()` method,
`window.addEventListener` and `webview.postMessage` .
- for IntelliJ, there is no such helper method, so we wrote a custom `window.intellijApi` object. This api will then be
called from both the Angular app and from within Kotlin code by injecting it into JCEF (more on that later). This is
definitely a more involved solution and less developer-friendly, but it works perfectly fine.
The service uses whatever API it finds to send and receive messages, with the rest of the app none the wiser. The
structure of the messages is identical between VSCode and IntelliJ. The fact that the Typescript-based VSCode extension
natively understands JSON is a nice upside, since we can just pass around objects between the browser and extension
without having to convert anything. For the Kotlin-based IntelliJ plugin, this needs an additional de-/serialization
step, which is easily done with [`kotlinx.serialization`](https://github.com/Kotlin/kotlinx.serialization) or
[`gson`](https://github.com/google/gson).
## Adapting Styling
One aspect that makes designing webviews for VSCode a breeze is the massive stylesheets they ship by default. Every UI
elements colors are available in primary, secondary and disabled variants as well as fonts, background colors and more.
However, this ended up being a struggle as all styling was very tightly coupled to these VSCode stylesheets, which are
obviously not present within a different host IDE. We replaced all of the VSCode styles with custom css variables. In a
separate `generate-ui-styles` library, we map the VSCode styles to our matching variables. For IntelliJ, we extract the
the same style variables using `UIUtil` and pass them to the app.
## JCEF
To integrate the web application into IntelliJ, Nx Console
uses [JCEF (Java Chromium Embedded Framework)](https://plugins.jetbrains.com/docs/intellij/jcef.html). JCEF enables Java
applications to render web pages using Chromium. It comes with great debugging support using Chrome Devtools and we
havent run into any issues with it yet. The docs are sadly a bit lacking, but with some trial and error we managed to
wire everything up. I want to give a special shoutout to Rafal Mucha and his
article [Creating IntelliJ plugin with WebView](https://medium.com/virtuslab/creating-intellij-plugin-with-webview-3b27c3f87aea).
It explains how to enable JCEF to load files from the `/resources` folder bundled in the plugin JAR. Theres not much
info on this topic so this one blog post was a true lifesaver. Its written in Scala but I learned a lot rewriting it to
Kotlin. Now we have
a [Kotlin version](https://github.com/nrwl/nx-console/blob/master/apps/intellij/src/main/kotlin/dev/nx/console/generate_ui/CustomResourceHandler.kt)
out there too!
Communication with whatever is running in the browser works by **_injecting_** javascript code to be run into the
browser - kind of like running something in the console. This creates a little more overhead than simply posting
messages to be consumed from a listener like in VSCode. The upside is that it theoretically gives you a lot more
flexibility in what you want to do in the browser - you could talk to multiple, independent APIs and register distinct
callbacks on the host side.
## Glueing it together
One of the unique aspects of the Nx Console for IntelliJ is that it combines different technologies in a polyglot
monorepo. While Nx is often used for Typescript- or Javascript-based repos, its actually technology-agnostic and can
host apps and libraries in any language. With the newly released [**_Encapsulated Nx_
**](/recipes/installation/install-non-javascript) setting, this is even taken a step further! Now you dont need a
`package.json` or `node_modules` to run Nx.
The codebase contains both Typescript code for the VSCode extension and Kotlin code for the IntelliJ plugin. Currently,
all the Kotlin code resides in a single app. Targets defined in `project.json` are available that wrap different gradle
tasks like running a development instance, building or formatting the plugin using the
[`nx:run-commands`](/nx-api/nx/executors/run-commands) executor.
Since the plugin depends on artifacts provided by other Nx apps (namely the `nxls` and `generate-ui`), we have also
created gradle tasks that call Nx to build these dependencies under the hood. This roundabout way of calling one tool
from the other (and back again) could definitely be improved and we might look into having a more straightforward
integration later.
For the generate UI, we were able to keep it as a single app. Using different configurations for the `build` target,
were including the different stylesheets needed for each configuration and copying the files to where they need to be.
## Looking ahead
In the upcoming releases, we plan to integrate more features that already exist in VSCode like the nx project view as
well as add more IntelliJ-native functionality and quality-of-life changes. Our goal is to provide the same experience
and level of productivity, regardless of which IDE you prefer to use. You can join the discussion and vote on what you
think should be added on [the roadmap issue on GitHub](https://github.com/nrwl/nx-console/issues/1578).
We are also looking into automatic type generation for both TypeScript and Kotlin. Currently, all return types of the Nx
Language Server have to be maintained in both languages, but maybe we could use a tool
like [Dukat](https://github.com/Kotlin/dukat). This would help us to save time and reduce the risk of inconsistencies
between the TypeScript and Kotlin codebases.
**Learn more**
- 🎮 [Nx Console GitHub](https://github.com/nrwl/nx-console)
- 🚀 [Nx Console JetBrains plugin](https://plugins.jetbrains.com/plugin/21060-nx-console)
- 🤖 [Nx Console VSCode extension](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)

View File

@ -0,0 +1,213 @@
---
title: 'Nx 15.8 — Rust Hasher, Nx Console for IntelliJ, Deno, Node and Storybook'
slug: 'nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2023-03-08/1*2gKrC6_Yx3hVkQaHxnw5xw.png'
tags: [nx, release]
---
Just weeks after the [release of Nx 15.7](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning) (release video [here](https://www.youtube.com/watch?v=IStJODzZSoc)), the Nx team has now launched Nx 15.8, with exciting new features and enhancements aimed at improving developer experience, productivity, and efficiency. Lets dive straight in.
**Table of Contents**
· [Rustifying the Nx Hasher](#rustifying-the-nx-hasher)
· [Deno Support](#deno-support)
· [Nx Console — IntelliJ Support](#nx-console-intellij-support)
· [Nx Console Field Prioritization (x-priority)](#nx-console-field-prioritization-xpriority)
· [Modular Node Applications](#modular-node-applications)
· [Storybook](#storybook)
· [How to Update Nx](#how-to-update-nx)
· [Learn more](#learn-more)
## Prefer a video? Weve got you covered!
{% youtube src="https://www.youtube.com/watch?v=4XdHT5Y7zj4" /%}
## Heads-up: Release Live stream tomorrow
We have the Nx live stream on Thursday, March 9th at 7 PM CET, to talk about all the features that went into Nx 15.7 and 15.8. So tune in to ask your questions :)
Enable notifications here:
[https://www.youtube.com/live/P3TinTe3O2g?feature=share](https://www.youtube.com/live/P3TinTe3O2g?feature=share)
## Rustifying the Nx Hasher
Starting with Nx 15.8, we now have a Rust-based Hasher enabled by default!
Performance is at the core of what we do at Nx. Hence it isnt surprising that Nx is the fastest JS-based monorepo solution out there. Weve shown [that a couple of times](https://github.com/vsavkin/large-monorepo). But every millisecond counts! As such, we decided to experiment with Rust to see whether we could further optimize our project graph creation as well as the hasher function that is used for the [computation cache](/features/cache-task-results).
Our original implementation used Git to calculate the hash. But it had some downsides as
- it didnt work if you dont have or use Git (obviously)
- it didnt work if you used Git submodules
- it became super slow if you had a lot of file changes on your Git working tree, like when switching between branches
- it triggered a lot of `execSync` calls to get different git status which was a fragile implementation
In some situations where we couldnt rely on or use the Git hasher, we did a fallback to a node implementation which made things even slower.
**All nice and good, but show me the numbers!**
So we did run some experiments on a small repo:
- avg. time for Rust hasher: 17ms
- avg. time for Git hasher: 24ms
We also tried it on the [Nx repository](https://github.com/nrwl/nx) itself:
- Rust hasher: 50ms
- Git hasher: 69ms
When running these tests on Windows (not WSL), the Nx repo hashing timings turned out to be
- Rust hasher: 72ms
- Git hasher: 330ms
Right now, we only observed the Rust hasher to be slightly slower on large repositories when you dont have any changes. Once you start making changes the Git hasher becomes slower again and is overtaken by the Rust version which remains stable in performance.
An interesting side-effect of using the Rust-based hasher is the size of the generated hashes, which are much smaller and thus allow for a quicker serialization between the [Nx Daemon](/concepts/nx-daemon) and Nx.
**Future work**
While we started with the hasher optimization, the next implementation were exploring is using a binary format to communicate between the Nx Daemon and the Nx client. Currently, we serialize the JSON to a string and pass that through an IPC socket. Using a binary format will significantly speed up the communication here.
**Opting out**
We build the binary for the Rust hasher for:
- macOS x64
- macOS arm
- linux arm
- linux gnu
- linux musl
- windows arm64
- windows x64
As such, it should work on most CI and local developer machines. If we missed something, please reach out an [open an issue on GitHub](https://github.com/nrwl/nx)! In case something breaks though, you can also disable the Rust hasher by using the environment variable `NX_NON_NATIVE_HASHER=true`.
## Deno Support
{% youtube src="https://youtu.be/NpH8cFSp51E" /%}
Nx Deno support [already landed in 15.7](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning), but didnt make it into the blog post. So here we go: we have a brand new Nx Deno plugin published at `@nrwl/deno`. For now, it is experimental and lives in our [labs repository](https://github.com/nrwl/nx-labs).
This plugin features the ability to generate Deno applications and libraries inside of an Nx workspace. Obviously, all the other much-loved Nx features such as caching, affected commands and the project graph visualization work out of the box as well.
To use Deno in an existing Nx workspace, just install the `@nrwl/deno` plugin:
```
npm i -D @nrwl/deno
```
Then run the generator to create a new application:
```shell
npx nx g @nrwl/deno:app mydenoapp
```
Or generate a new library with:
```shell
npx nx g @nrwl/deno:lib mydenolib
```
Were excited to see folks welcome in Deno APIs to their Nx workspaces and be able to easily share their Typescript packages across Deno, Node, and web applications, all inside the same monorepo.
Given this is still experimental, were more than happy to receive feedback and hear about ways you are using Deno right now and/or plan to use it in an Nx workspace.
To see some of this in action, be sure to check out our [recent livestream with Caleb and Chau](https://youtu.be/Um8xXR54upQ), two of our engineers that have been working on this plugin:
## Nx Console — IntelliJ Support
{% youtube src="https://youtu.be/xUTm6GDqwJM" /%}
Developer tool CLIs are known for being, well, command-line interfaces. Nx comes with many such CLI commands for scaffolding projects, running tasks, and more. We wanted to make some of this more approachable, so we introduced Nx Console, an extension to the Visual Studio Code editor. And it turned out to be highly successful. Nx Console now has over 1.2 million downloads on the [Visual Studio Code marketplace](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console). We kept improving it over the years,
- adding support for [rendering the Nx graph](https://youtu.be/ZST_rmhzRXI)
- [providing IntelliSense](https://twitter.com/NxDevTools/status/1573323012476051456) support for Nx configuration files
- [integrating Nx Cloud](https://youtu.be/WfWmK1x52HE)
With the growing popularity, the ask for an equivalent extension for JetBrains IntelliJ & WebStorm editors got louder and louder. At Nx, were lucky to have an awesome community. [Issam Guissouma](https://twitter.com/iguissouma) and [Edward Tkachev](https://twitter.com/etkachev) from the Nx community jumped in and provided their implementation of Nx Console for IntelliJ.
Since our team [now works full-time on Nx](/blog/from-bootstrapped-to-venture-backed) and the surrounding tooling, we decided to have a dedicated Nx Console extensions for IntelliJ and WebStorm that is actively maintained and developed by the core team. We reached out to Issam and Edward and started collaborating on it. The result can now be installed from the JetBrains marketplace:
[https://plugins.jetbrains.com/plugin/21060-nx-console](https://plugins.jetbrains.com/plugin/21060-nx-console)
Read all the details [on our blog post](/blog/expanding-nx-console-to-jetbrains-ides) or check out our docs page about [integrating with editors](/getting-started/editor-setup).
## Nx Console Field Prioritization (x-priority)
{% youtube src="https://youtu.be/JJ12zKedwIs" /%}
Nx Console has proven a highly valuable tool for exploring Nx generators. Especially if you cannot recall all the various parameters, you can possibly pass. And sure, you could always pass the `--help` or browse [the docs](/nx-api/react/generators/library), but it is just less convenient.
![](/blog/images/2023-03-08/0*xFSreZ1G_zifIsdf.avif)
With a growing number of parameters that a generator can take, it started to get messy and overwhelming. Furthermore, in 80% of the cases, you would probably need the main parameters such as the name, bundler, and directory where to generate the output.
This is the main reason we introduced a `x-priority` flag to our generator metadata, to have a way to prioritize certain flags and show them more prominently to the end user. Available values are `important` and `internal`.
The property can be defined for the desired parameters in the generators `schema.json`:
```json
{
"directory": {
"description": "The directory of the new application.",
"type": "string",
"x-priority": "important"
}
}
```
All required properties and those marked with an `x-priority: important` will be shown at the top of both, the CLI output (when using `--help`) as well as the Nx Console UI.
![](/blog/images/2023-03-08/0*eDOHabm8ca96lwul.avif)
Read all about it [in the doc about Customizing Generator Options](/extending-nx/recipes/generator-options).
## Modular Node Applications
Nx has had Node backend support since the beginning, where you could add an [ExpressJS](/nx-api/express) or [Nest.js](/nx-api/nest) based application to your monorepo. This is a powerful approach as it allows you to colocate your frontend and backend code, which helps share code and, in particular, TypeScript types for your APIs!!
In [Nx 15.7](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning), we then announced [Nx Standalone Projects](https://youtu.be/qEaVzh-oBBc) support for Node. This allows to develop a Node backend in isolation but still leverages all the features from Nx in terms of code generators, automated migrations, and speed features such as [affected commands](/ci/features/affected), [caching](/concepts/how-caching-works), and [optimized CI setups](/ci/features/distribute-task-execution).
In 15.8, we kept improving our Node support. Our main focus was on
- allowing to have a non-bundled output, while still being able to modularize the codebase with local libraries
- generating a pruned lock file when building in production mode
- improving our docker setup to account for non-bundled output and properly install node packages
Check out the following video walkthrough on using these features for modularizing a Fastify application:
{% youtube src="https://youtu.be/LHLW0b4fr2w" /%}
## Storybook
Nx now generates stories using [Component Storybook Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/). If you are using our `@nrwl/react:storybook-configuration`, `@nrwl/angular:storybook-configuration`, `@nrwl/react:stories` and `@nrwl/angular:stories` generators, you will notice that the stories are now generated in the new format. You can check out our documentation for [Storybook and Angular](/recipes/storybook/overview-angular) or [Storybook and React](/recipes/storybook/overview-react) to see the new syntax.
As the Storybook doc mentions, CSF3 _reduces boilerplate code and improves ergonomics. This makes stories more concise, faster to write and easier to maintain._
You can migrate your existing stories in your Nx workspace to CSF3 using the Storybook [`csf-2-to-3` migrator](https://storybook.js.org/blog/storybook-csf3-is-here/#upgrade-to-csf3-today):
```shell
npx storybook@next migrate csf-2-to-3 --glob="**/*.stories.ts"`
```
## How to Update Nx
Updating Nx is done with the following command and will update your Nx workspace dependencies and code to the latest version:
```shell
npx nx migrate latest
```
After updating your dependencies, run any necessary migrations.
```shell
npx nx migrate --run-migrations
```
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -0,0 +1,82 @@
---
title: 'Rspack — Getting up to speed with Nx'
slug: 'rspack-getting-up-to-speed-with-nx'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2023-03-10/1*fWQ53mw2itEs3SGAOJVonQ.png'
tags: [nx]
---
At Nx, we are excited to see the JavaScript tooling ecosystem evolve, particularly when it comes to improving speed! Performance is at the core of Nx. Faster tools with which we can integrate make our lives easier and allow us to provide a better experience for developers.
Almost a year ago [ByteDance](https://www.bytedance.com/) started developing a new, faster Webpack alternative: **Rspack**. [Valor Software](https://valor-software.com/) joined the collaboration and reached out to us about developing a dedicated Nx plugin. The goal: give developers an easy onboarding path to Rspack and React!
## Faster than Webpack? What is Rspack?
Rspack is a rewrite of Webpack with the primary goal of improving performance. Rust is the main language, allowing for a highly parallelized architecture that takes full advantage of modern multi-core CPUs. In addition, it also comes with essential bundling features already built-in to avoid further bottlenecks from 3rd-party packages. It also highly optimizes HMR (Hot Module Replacement) using a specialized incremental compilation strategy.
ByteDance developed Rspack to solve performance issues they faced when developing and maintaining their internal monolithic applications, all of which rely heavily on complex Webpack configurations. Rspack being a rewrite allows to rely on Webpacks mature architecture and is, at the same time, an easy drop-in replacement.
ByteDance already applied Rspack on some of their internal business applications and has seen between 5 to 10x improvement in compilation performance.
More on the official Rspack docs: [https://rspack.dev](https://rspack.dev/)
## Getting up to speed with Rspack & Nx!
Our goal at Nx is to be the best CLI for your framework of choice. We want to remove friction so developers can easily leverage these new tools and focus on shipping features using a production-ready setup. This is why we developed a dedicated Rspack plugin that lets everyone quickly get up to speed.
Check out the following video for a complete walkthrough of how Nx and Rspack work together to create production-ready React applications.
{% youtube src="https://youtu.be/jGTE7xAcg24" /%}
## React Standalone App with Rspack
You can create a new Rspack-based React application using the following command:
```shell
npx create-nx-workspace myrspackapp --preset=@nrwl/rspack
```
This creates a pre-configured setup with React, TypeScript, ESLint, Jest (optionally Vite), Cypress for e2e testing, and obviously Rspack as the bundler.
All the usual Nx features, such as
- [affected commands](/ci/features/affected)
- [computation caching](/features/cache-task-results)
- remote caching with [Nx Cloud](/nx-cloud)
..work out of the box.
But not just the “speed features”. All the code generators, automate code migrations, and [code editor extensions](/getting-started/editor-setup) work too.
## Rspack in an Nx Monorepo
Similarly, you can use Rspack-based applications in existing Nx monorepos. Just install the NPM package:
```
npm i @nrwl/rspack -D
```
Then generate a new application:
```shell
npx nx g @nrwl/rspack:app myrspackapp
```
This creates a new application in your Nx monorepo that uses Rspack as the bundler. You can even import existing React libraries, which can also be an excellent way to experiment with Rspack in an existing production setup.
## Wrapping up
Go and learn more on the
- official Rspack website: [https://rspack.dev](https://rspack.dev/)
- learn about the Nx Rspack plugin: [/nx-api/rspack](/nx-api/rspack)
## Learn more
- 🦀 [Rspack and Nx docs](/nx-api/rspack)
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -6,7 +6,7 @@ cover_image: '/blog/images/2023-04-19/featured_img.webp'
tags: [nx, nx-cloud] tags: [nx, nx-cloud]
--- ---
It has been almost 2 years since we released [Nx Cloud 2.0](https://nx.app/). Since then, it has saved over 400 years of computation by leveraging its distributed caching and task execution. And we keep adding 8 years every single week. Not only does this tremendously [impact our environment](https://dev.to/nx/helping-the-environment-by-saving-two-centuries-of-compute-time-4nep), but it also helps developers be more productive and companies save money. It has been almost 2 years since we released [Nx Cloud 2.0](/nx-cloud). Since then, it has saved over 400 years of computation by leveraging its distributed caching and task execution. And we keep adding 8 years every single week. Not only does this tremendously [impact our environment](/blog/helping-the-environment-by-saving-two-centuries-of-compute-time), but it also helps developers be more productive and companies save money.
In the last couple of months we have quadrupled the team and have done some amazing things. And we have some big plans for what is coming next. Heres all you need to know! In the last couple of months we have quadrupled the team and have done some amazing things. And we have some big plans for what is coming next. Heres all you need to know!
@ -27,7 +27,7 @@ In the last couple of months we have quadrupled the team and have done some amaz
## New, Streamlined UI ## New, Streamlined UI
This latest release of Nx Cloud comes with a new, streamlined design that offers users a more modern and visually appealing experience. This includes the main [Nx Cloud website](https://nx.app/), where we improved our messaging, including interactive visualizations to better explain some core concepts around remote caching and distributed task execution. This latest release of Nx Cloud comes with a new, streamlined design that offers users a more modern and visually appealing experience. This includes the main [Nx Cloud website](/nx-cloud), where we improved our messaging, including interactive visualizations to better explain some core concepts around remote caching and distributed task execution.
![](/blog/images/2023-04-19/bodyimg1.webp) ![](/blog/images/2023-04-19/bodyimg1.webp)
@ -100,7 +100,7 @@ Finally, the **Enterprise plan** is for companies that want full control over wh
All these changes should allow developers to choose the plan that best suits their needs and budget more easily, ensuring a seamless and transparent experience regarding pricing and subscription management. All these changes should allow developers to choose the plan that best suits their needs and budget more easily, ensuring a seamless and transparent experience regarding pricing and subscription management.
Learn more at [https://nx.dev/pricing](/pricing). Learn more at [/pricing](/pricing).
## Coming Next ## Coming Next

View File

@ -0,0 +1,142 @@
---
title: 'Nx 16 is Here!'
slug: 'nx-16-is-here'
authors: ['Zack DeRose']
cover_image: '/blog/images/2023-05-02/1*n8JTIcKSYkebBOl8zZuF9w.png'
youtubeUrl: 'https://youtu.be/JIhOyJtuxEA'
tags: [nx, release]
---
Were proud to announce the release of Nx version 16! In this article, well go over the major updates from Nx 16 and the key pieces of information youll need to know for the changes that Nx 16 brings!
But before we jump into the new features of Nx 16, lets recap some of the recent features from our Nx 15 minor releases!
- We introduced simpler presets for React, Angular, and [Node starter applications](https://youtu.be/K4f-fMuAoRY)
- We added official support for [Vite](/nx-api/vite) and Vitest for integrated Nx monorepos
- We introduced an [official Deno plugin](https://youtu.be/NpH8cFSp51E), including integration for Node and Deno project collocation and project graph support for Deno imports
- We added Rust into the Nx codebase to speed up core functionality
- We added support for [non-npm workspaces](https://youtu.be/QOhdL02f6BY) to support workspaces focused on other languages like C#, Java, and Kotlin, and saw some of those in action with community plugins for [.NET](https://www.nx-dotnet.com/) and [Java/Kotlin](https://github.com/tinesoft/nxrocks)
- Introduced [Nx Console for JetBrains IDEs like IntelliJ and WebStorm](https://youtu.be/xUTm6GDqwJM)
- We have [decoupled the Nx version from Angular](https://youtu.be/AQV4WFldwlY) versions allowing you to update Nx without updating Angular
### Table of Contents
· [Heres how to Upgrade with Nx Migrate](#heres-how-to-upgrade-with-nx-migrate)
· [Rescoping From @nrwl/_ to @nx/_](#rescoping-from-nrwl-to-nx)
· [Deno Standalone Apps, Edge Deployment and More](#deno-standalone-apps-edge-deployment-and-more)
· [Cypress Feature Testing](#cypress-feature-testing)
· [Task Graph](#task-graph)
· [The Nx Repo Switches to PNPM for its Package Manager](#the-nx-repo-switches-to-pnpm-for-its-package-manager)
· [Learn more](#learn-more)
## Heres how to Upgrade with Nx Migrate
As with all new Nx releases, `nx migrate` can be used to bump your Nx packages to the appropriate version, as well as run any necessary changes to your codebase.
To update to Nx 16, run
```
nx migrate latest
```
This will update your dependencies to the latest version, as well as update those dependencies in your root `package.json` file.
If further migrations are available, youll see a `migrations.json` file in the root of your workspace. This file will describe any further code generation scripts that should be run. To run these, use the command..
```
nx migrate --run-migrations
```
…as prompted in the terminal.
After the migrations have been run, you should be able to see them in your source control tools. Ensure that everything is still working properly by running any automated testing you have set up.
Check out this real-world example using the `nx migrate` command for the `Tanstack/query` repo:
{% youtube src="https://youtu.be/X1I1Aw2sV-Y" /%}
Also as a reminder to our Angular users — weve now **decoupled the Nx version from Angular versions**, so as long as youre on an LTS version of Angular, youre clear to migrate to the latest Nx version without having to touch your Angular version! To do so, be sure to use the `interactive` option (e.g. `nx migrate --interactive`). Check out this video for more info:
{% youtube src="https://youtu.be/AQV4WFldwlY" /%}
## Rescoping From @nrwl/_ to @nx/_
{% youtube src="https://youtu.be/HzkvhPKAepA" /%}
One of the more impactful changes from Nx 16 is that well be changing the npm scope that we publish our packages under from `@nrwl` to `@nx`. In other words, `@nrwl/react` will now be published as `@nx/react`.
Nx will handle this migration automatically via the `nx migrate` command to update your workspaces!
To ensure that community plugins are not broken, the `@nrwl/*` versions of these packages are deprecated but will continue to be published until Nx 17 which is scheduled for October 2023.
## Deno Standalone Apps, Edge Deployment and More
Nx has had support for developing Node-based backends for a while. It was a popular choice for building your BFF in a monorepo-based setup alongside your React or Angular application. [In Nx 15.7](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning) we decided to expand that support and really go deep into improving the overall DX.
**Deno got quite some love** in this iteration:
- Standalone App support — You can now scaffold a new single-project Deno workspace with Nx. Just run `npx create-nx-workspace --preset=@nx/deno`. Probably the fastest way to get up and running with Deno
- We also added Nx generators to set up Deno with [oak](https://oakserver.github.io/oak/). Just pass the `--framework` option when you set up a new Deno app (or use [Nx Console](/getting-started/editor-setup))
Its all about **Edge functions** recently (and, well, serverless in general). Especially when developing with Node it is common that you might want to deploy to the Edge or some serverless environment. Therefore, we..
- created a brand new `@nx/netlify` package (currently [in labs](https://github.com/nrwl/nx-labs/tree/main/packages/netlify)) which allows you to set up a brand new project for developing and pushing Netlify functions, or you can add serverless deployment support to an existing project, using the `@nx/netlify:setup-serverless` generator. Check out our in-depth recipe on the topic: [/recipes/node/node-serverless-functions-netlify](/recipes/node/node-serverless-functions-netlify)
- published anew `@nx/aws-lambda` for deploying [Lambda functions](https://aws.amazon.com/lambda/) to AWS. All details in our latest recipe: [/recipes/node/node-aws-lambda](/recipes/node/node-aws-lambda)
- Improved our existing Deno package to add support for serverless deployment to both Deno Deploy as well as Netlify. Such support can be added to an existing app using the `@nx/deno:setup-serverless` generator and providing the `--platform` flag that either point to `deno-deploy` or `netlify`.
## Cypress Feature Testing
{% youtube src="https://youtu.be/d5i9_Y8Ip54" /%}
Nx sets up e2e tests for apps that tend to collect many features. This ends up as a large atomic suite that Nx isnt good at separating out. With Nx 16, weve made it easier to distribute these tests closer to the actual feature they test. This will make it much easier for `nx affected` to determine which tests are actually necessary.
I also had the opportunity to have a live stream with Nxs own Caleb (who lead most of the development for this feature), as well as Cypresss Jordan Powell who also contributed to this effort — check it out:
{% youtube src="https://youtu.be/y3gFRSqarEo" /%}
## Task Graph
Nx 16.0 also introduces more helpful tools for visualizing your project and task graph as determined by Nx:
{% youtube src="https://youtu.be/9_Y6Mop-Kac" /%}
The task graph in particular is helpful for visualizing what actually runs when you run commands, and with Nx 16.0, you can now use the `--graph` option when running most Nx commands to visualize the graph of tasks that would have run - for example:
```
nx build react --graph
```
The task graph was also highlighted in a recent video demonstrating feature parity between our VsCode and JetBrains plugin:
{% youtube src="https://youtu.be/XCoeNiyM6hw" /%}
## The Nx Repo Switches to PNPM for its Package Manager
Internally, the [Nx repo](https://github.com/nrwl/nx) switched to using `pnpm` as its package manager. Since switching we have noted the following advantages:
- publish is 2x faster
- CI times decreased
- install times decreased
While we are using `pnpm` as our package manager, we are not using the `pnpm` workspaces functionality in the Nx repo, but we've found that Nx actually works extremely well with `pnpm` workspace setups. Juri had released [an article on this topic](/blog/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx) previously, and we used this approach to introduce Task Caching and Distributed Caching (via Nx and Nx Cloud) to [the Tanstack/query repo](https://github.com/TanStack/query), which yielded excellent results:
{% youtube src="https://youtu.be/NvPXK6DVZGE" /%}
## Wrapping up!
Thats about it for Nx 16.0 — weve really loved the opportunity to bring you all this cool stuff, and were eager to start our next iteration with a steady focus on making Nx an awesome tool for increasing your productivity by taking all the repo management tasks out of the equation so you can focus on shipping great stuff.
### Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](/nx-cloud)
### More Nx Release Notes:
- Nx 15.3: [/blog/nx-15-3-standalone-projects-vite-task-graph-and-more-3ed23f7827ed](/blog/nx-15-3-standalone-projects-vite-task-graph-and-more)
- Nx 15.4: [/blog/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more](/blog/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more)
- Nx 15.7: [/blog/nx-15-7-node-support-angular-lts-lockfile-pruning](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning)
- Nx 15.8: [/blog/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook](/blog/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook)

View File

@ -0,0 +1,30 @@
---
title: 'Introducing the Nx Champions Program'
slug: 'introducing-the-nx-champions-program'
authors: ['Isaac Mann']
cover_image: '/blog/images/2023-05-16/0*cVGLh0H-uOpy7-D6.png'
tags: [nx]
---
The Nx community is too large to be adequately supported by the Nx team alone. Luckily, there are many people who volunteer their time and expertise to help others and share how they use Nx to solve their problems. We are launching the Nx Champions program as a way of acknowledging the work of key members of the community and supporting them in their ongoing efforts.
### What Does Champion Mean?
Champion is both a noun and a verb and the champion in Nx Champions is intended in both ways. Nx Champions have achieved a champion level of knowledge and expertise in some area of Nx. They also champion Nx to the community through content like blog posts, videos and conference talks or by contributing code through plugins or the Nx repo itself. In addition, they champion the ideas of the community back to the Nx team.
### Who are the Nx Champions?
A full list of Nx Champions is available at [/community](/community).
![](/blog/images/2023-05-16/1*j58ocCsWEnDe4-8ZMsQd5g.avif)
_List of Nx Champions_
We appreciate everyone who was part of the initial group of Nx Champions, but acknowledge that there are more people who could qualify. If you are interested in joining the program, fill out the [application form](https://forms.gle/wYd9mC3ka64ki96G7) and lets talk about it.
## Learn more about Nx
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 🐥 [Nx Twitter Handle](https://twitter.com/NxDevTools)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)

View File

@ -0,0 +1,113 @@
---
title: 'Determine your User Location with Netlify Edge Functions'
slug: 'determine-your-user-location-with-netlify-edge-functions'
authors: ['Nicholas Cunningham']
cover_image: '/blog/images/2023-05-26/1*G2ynKDm6DIKLcZ2fJlV0dw.png'
tags: [nx, tutorial]
---
Today, we will explore how to use `@nx/netlify` serverless functions to determine a users location. This can be an incredibly useful feature in various applications, such as customizing user experiences based on their region, displaying localized content, or tracking user demographics for marketing purposes. In this post, well walk you through a step-by-step guide on implementing this functionality using `@nx/netlify` serverless functions.
Before we get started though, heres a video introduction to the new `@nx/netlify` package:
{% youtube src="https://youtu.be/idH6GCkWq0w" /%}
### Step 1: Set up your Nx workspace with Netlify
To get started, you need to have an Nx workspace. If you havent already, create a new Nx workspace by running:
```shell
npx create-nx-workspace user-location --preset=@nx/netlify
```
This should create a default function inside `src/functions/hello/hello.ts`, which can be _safely deleted_ if necessary.
### Step 2: Create a serverless function
```
mkdir src/functions/user-location
touch src/functions/user-location/user-location.ts
```
### Step 3: Determine the users location
To determine the users location, we will leverage the `request.headers` object, specifically the `x-forwarded-for` header containing the users IP address. We can then use an IP geolocation API like ipapi ([https://ipapi.co/](https://ipapi.co/)) to fetch location data based on this IP address.
_Note_ in **Node.js 18**, the experimental global fetch API is available by default. If you are using a node version **lower** than **18** you can install `node-fetch` to handle API requests:
```
npm install node-fetch
```
Now, update the `user-location.ts` file with the following code:
```
import { Handler } from "@netlify/functions";
import fetch from "node-fetch"; // Can be removed if node >= 18
export const handler: Handler = async (event, _) => {
const ip = event.headers["x-forwarded-for"];
const url = `https://ipapi.co/${ip}/json/`;
try {
const response = await fetch(url);
const data = await response.json();
return {
statusCode: 200,
body: JSON.stringify({
location: {
city: data.city,
region: data.region,
country: data.country,
},
}),
};
} catch (error) {
return { statusCode: 500, body: `Error fetching user location` };
}
};
```
### Step 4: Deploy your serverless function
When we created our workspace, the initial scaffolding generated a **deploy-target** inside our `project.json`.
> A **target** is a specific task you can run for a project.
> You can think of it as a script/command that does a specific job. The most common targets are “build”, “serve”, “test”, “lint”, “deploy”, etc. For more information regarding `project.json` you can read about it at [project-configuration](/reference/project-configuration)
We can start off by creating our site on Netlify by running:
```shell
npx netlify init
```
After you have answered all the prompts your site should be created. A `.netlify` folder should be created with references to your newly created site.
Now, to deploy your serverless function run:
```
nx run deploy
```
Finally, navigate to your Netlify sites Functions tab, and you should see your `user-location` function deployed and ready to use!
For example, ours can be found at: [https://644a9b17d0299b00b581b33f--find-user-location.netlify.app/.netlify/functions/user-location](https://644a9b17d0299b00b581b33f--find-user-location.netlify.app/.netlify/functions/user-location)
```json
{ "location": { "city": "Miami", "region": "Florida", "country": "US" } }
```
By following these steps, youve successfully used `@nx/netlify` serverless function to determine a users location!
### Wrapping up
Never used Nx before? Learn more about Nx [here](/getting-started/why-nx).
[Official recipe from Nx](/recipes/node/node-serverless-functions-netlify)
[Github example](https://github.com/ndcunningham/nx-netlify-serverless)
### Learn more
🧠 [Nx Docs](/getting-started/intro)
👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
💬 [Nx Official Discord Server](https://go.nx.dev/community)
📹 [Nrwl Youtube Channel](https://www.youtube.com/@nxdevtools)
🚀 [Speed up your CI](/nx-cloud)

View File

@ -0,0 +1,182 @@
---
title: 'Introducing Nx Ecosystem CI'
slug: 'introducing-nx-ecosystem-ci'
authors: ['Katerina Skroumpelou']
cover_image: '/blog/images/2023-06-20/1*EffyLKcVe5gE_x3MT8PJUQ.png'
tags: [nx]
---
The JavaScript ecosystem evolves at a rapid pace, frequently introducing new tools and packages. At Nx, we provide out-of-the-box integrations with the most popular among them so you dont have to worry when stitching them together. That, however…yes you guessed it… can be a challenging task. Theres just one way to keep up: automation.
We already run a ton of automated testing on our repository to ensure we dont break anything. But given Nxs popularity and vast usage across open source and enterprise projects, we want to go a step further: introducing the [Nx Ecosystem CI](https://github.com/nrwl/nx-ecosystem-ci). Inspired by the work done by our friends on the [Vite](https://vitejs.dev/) team, the [Nx Ecosystem CI](https://github.com/nrwl/nx-ecosystem-ci) is designed to enhance the stability of Nx by testing pre-release versions with projects in the Nx ecosystem.
### Inspired by the Vite Ecosystem CI
The [Vite Ecosystem CI](https://github.com/vitejs/vite-ecosystem-ci) is an innovative tool that has significantly enhanced the use of [Vite](https://vitejs.dev/). It monitors the compatibility of Vite with various other packages and projects in the ecosystem by running tests against the latest changes in the Vite codebase and the projects it integrates with. This allows the Vite team to catch issues early and maintain a high level of stability, ensuring that developers using Vite can trust that new contributions to either Vite or their project will not result in breaking changes.
This robust testing system is essential because it gives users confidence in Vites reliability, encouraging more developers to adopt Vite. Its a great example of proactive testing in a fast-paced ecosystem and an inspiration for other projects, including Nx. The concept of the Ecosystem CI introduces a framework-agnostic way of testing integrations of one tool with other tools in the ecosystem. It puts together a “syntax” with which tools can easily find the way to test their latest versions with one another.
### Nx Ecosystem CI
The [Nx Ecosystem CI](https://github.com/nrwl/nx-ecosystem-ci) is a fork of the [Vite Ecosystem CI](https://github.com/vitejs/vite-ecosystem-ci) but is tailored specifically for the Nx ecosystem. Its designed to ensure that Nx maintains its high standards of reliability and compatibility with all our users.
### How Nx Ecosystem CI Works
The Nx Ecosystem CI works in the following way:
1. It clones the provided repo which uses Nx
2. It installs the projects dependencies
3. It runs a number of scripts specified by the projects author (eg. `test`, `build`, `e2e`)
4. It migrates the repository to the `next` version of Nx (using `nx migrate next`)
5. It runs the scripts again
6. It reports the results of the runs to the [Nx Official Discord Server](https://go.nx.dev/community)
in the `#ecosystem-ci` channel.
The main difference between the Nx Ecosystem CI and the Vite Ecosystem CI is that Nx Ecosystem CI uses the \`next\` version of Nx as published on npm, rather than cloning and building Nx locally, like Vite does in the Vite Ecosystem CI. This approach ensures that the tests run against the same code that developers are most likely to use in their projects. It also makes it easier for the script to migrate to that version.
At its core, the Nx Ecosystem CI is a set of command-line tools that run tests for a specific or all available suites. Each test suite corresponds to a specific configuration and consists of a set of commands executed in a given repository. The test suite checks for the correct execution of Nx commands, such as build, test, and e2e tests, ensuring that Nx functions as expected in different environments and projects.
### Adding a new test suite
To add a new test suite for your project in the Nx Ecosystem CI, you would need to create a new file under the tests directory. The name of this file should reflect the suite it represents, for example, [`nx-rspack.ts`](https://github.com/nrwl/nx-ecosystem-ci/blob/main/tests/nx-rspack.ts) .
The first step is to import the necessary modules and types from `utils.ts` and `types.ts` at the top of your file:
```typescript
import { runInRepo } from '../utils';
import { RunOptions } from '../types';
```
`RunOptions` is a type that represents the options for running a test suite. It includes properties such as the repository to test, the branch to use, and the commands to run for building, testing, and performing e2e tests (all optional).
Next, you need to define the `test` function that accepts the `RunOptions`. Within this function, youll call the `runInRepo` function, passing in the options as well as any specific properties required for your suite:
Again, using the example of `nx-rspack`:
```
export async function test(options: RunOptions) {
await runInRepo({
…options,
repo: 'nrwl/nx-labs',
branch: 'main',
build: ['build rspack'],
test: ['test rspack'],
e2e: ['e2e rspack-e2e'],
})
}
```
In this example, the suite is set up to run on the nrwl/nx-labs repository on the `main` branch. It will run `build rspack`, `test rspack`, and `e2e rspack-e2e` as its build, test, and e2e tests respectively. These commands will be invoked using the package manager used by your repository. So, in the `nx-labs` case, it will run `yarn build rspack` in the `nrwl/nx-labs` repo.
For this reason, adding a new test suite to the Nx Ecosystem CI also requires setting up appropriate `scripts` in your repositorys `package.json` file. These scripts provide the commands that will be invoked by your package manager to carry out the `build`, `test`, and `e2e` steps.
Heres an example of how scripts might be configured in a package.json file for a repository using Nx:
```
"scripts": {
"build": "nx build",
"test": "nx test",
"e2e": "nx e2e"
},
```
These scripts should be set up in such a way that they can be invoked directly by your package manager. For example, in a repository using `pnpm`, you could run the build script with the command `pnpm run build`.
When you create your test suite file, youll specify these script names in the `build`, `test`, and `e2e` properties of the `options` object passed to `runInRepo`.
```
export async function test(options: RunOptions) {
await runInRepo({
…options,
repo: 'nrwl/nx-labs',
branch: 'main',
build: ['build'],
test: ['test'],
e2e: ['e2e'],
})
}
```
With this setup, the Nx Ecosystem CI will run these scripts in your repository as part of its CI process, or just when you run `pnpm test <name-of-suite>` locally.
In addition to creating the test suite and setting up the package.json scripts, you will also need to add the name of the new suite to the workflow configuration files in the `.github/workflows` directory of the Nx Ecosystem CI repository. This suite name should match the filename of your test suite script.
There are two workflow files youll need to update:
- `.github/workflows/ecosystem-ci-selected.yml`
- `.github/workflows/ecosystem-ci.yml`
In `.github/workflows/ecosystem-ci.yml` youll find a strategy section with a `matrix` property. This `matrix` property specifies an array of suite names for the workflow to run. Youll need to add your new suite name to this array.
Heres what the strategy section might look like after adding a new suite named `my-new-suite`:
```
strategy:
matrix:
suite:
- ….
- nx-remix
- nx-rspack
- …
- my-new-suite # your new suite
```
By adding your suite name to this file, youre instructing the Nx Ecosystem CI to include your suite in its test runs.
In addition to the `.github/workflows/ecosystem-ci.yml` file, you also need to include your suite in the `.github/workflows/ecosystem-ci-selected.yml` file.
The `ecosystem-ci-selected.yml` workflow is designed to allow manual selection of a test suite to run. To add a suite to this workflow, you add it to the options array under `workflow_dispatch > inputs > suite`. Heres what it might look like with a new suite named `my-new-suite`:
```
on:
workflow_dispatch:
inputs:
suite:
description: "testsuite to run"
required: true
type: choice
options:
- ….
- nx-remix
- nx-rspack
- …
- my-new-suite # your new suite
```
Adding your suite name to this file allows it to be manually selected for a test run via the GitHub Actions interface. This manual selection process provides additional flexibility and control over the testing process, allowing you to run individual suites as needed.
### Reporting the results
The Nx Ecosystem CI is integrated with GitHub Actions, which helps with its automation process. The CI pipeline is scheduled to run three times a week (on Mondays, Wednesdays, and Fridays) and can also be triggered manually. The workflow uses a matrix strategy to run the suites in parallel. Each suite is given a big amount of memory, and the pipeline is configured with a long timeout, meaning that even if one suite encounters an error, the rest will continue to run. This ensures that we get comprehensive feedback on the health of all the test suites, regardless of individual failures. Once the test suites run, Github sends a message to the [Nx Official Discord Server](https://go.nx.dev/community)
`#ecosystem-ci` channel with the status of each suite, enabling the team and the community to view the results. Each result points to the Nx tag that was used, and also the job logs on GitHub.
Here is an example of a test run:
[https://github.com/nrwl/nx-ecosystem-ci/actions/runs/5144215568/jobs/9260227337](https://github.com/nrwl/nx-ecosystem-ci/actions/runs/5144215568/jobs/9260227337)
### Benefits for the Nx Community
The introduction of the Nx Ecosystem CI is a significant win for both the Nx team and the Nx developer community. For us, it enables us to catch issues early, often before they affect most end-users. By running tests against the \`next\` version of Nx, we can ensure that any changes we make are compatible with the various configurations that our users maintain.
For developers using Nx, the Nx Ecosystem CI offers reassurance that the tools they rely on are being actively tested and maintained. This provides confidence in the stability of Nx and its plugins.
### Ecosystem CI as part of the Open Source community
We are not alone in recognizing the value of an Ecosystem CI approach. Other OSS projects including Nuxt, VueJs, VolarJs, and Rspack, have also adopted this strategy. You can explore their implementations here:
- Nuxt: [https://github.com/nuxt/ecosystem-ci](https://github.com/nuxt/ecosystem-ci))
- VueJs: [https://github.com/vuejs/ecosystem-ci](https://github.com/vuejs/ecosystem-ci)
- VolarJs: [https://github.com/volarjs/ecosystem-ci](https://github.com/volarjs/ecosystem-ci)
- Rspack: [https://github.com/web-infra-dev/rspack-ecosystem-ci](https://github.com/web-infra-dev/rspack-ecosystem-ci)
- Storybook: [https://storybook.js.org/blog/storybook-ecosystem-ci/](https://storybook.js.org/blog/storybook-ecosystem-ci/)
As we continue to improve and refine the Nx Ecosystem CI, we remain committed to the goal of making Nx a reliable and integral part of your development workflow. If youre an open-source maintainer, you can create your own Ecosystem CI either from scratch (like Storybook) or by cloning the Vite Ecosystem CI. If your project uses Nx, you can easily add a new test suite for it.
## Learn more
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -26,11 +26,11 @@ If youre curious to learn more about the rewrite and the motivations behind i
### A Short History of Nx Console ### A Short History of Nx Console
Lets go back in time: Nx Console has been around for a while. [It first launched in 2018](https://blog.nrwl.io/announcing-the-first-stable-release-of-angular-console-the-ui-for-the-angular-cli-bb19093a92d4?source=friends_link&sk=d955094b2cb872a130b47c8040ec820e) — then called Angular Console — as a standalone Electron app which let you run Angular schematics and builders from a graphical interface. Of course, it was built with Angular and looked something like this: Lets go back in time: Nx Console has been around for a while. It first launched in 2018 — then called Angular Console — as a standalone Electron app which let you run Angular schematics and builders from a graphical interface. Of course, it was built with Angular and looked something like this:
![Screenshot of the original Angular Console electron app](/blog/images/2023-06-29/bodyimg1.webp) ![Screenshot of the original Angular Console electron app](/blog/images/2023-06-29/bodyimg1.webp)
In 2019, [it was ported to a VSCode extension](https://blog.nrwl.io/brand-new-ui-custom-vscode-task-support-more-in-angular-console-9-0-5e4d3a109fb9?source=friends_link&sk=47fd72d5700b4cb3de09e559c5524ce5) with the now familiar UI and support for the standalone app was dropped. In 2019, it was ported to a VSCode extension with the now familiar UI and support for the standalone app was dropped.
In 2020, support for the entire Nx ecosystem was added, it was renamed to Nx Console and an amazing transformation began: Today, Nx Console is much more than just a single form — it tightly integrates Nx into your IDE, gives you the overview of your projects that you need and puts your task-running just a click away. In 2020, support for the entire Nx ecosystem was added, it was renamed to Nx Console and an amazing transformation began: Today, Nx Console is much more than just a single form — it tightly integrates Nx into your IDE, gives you the overview of your projects that you need and puts your task-running just a click away.
@ -44,7 +44,7 @@ In addition, we started questioning our usage of Angular. Angular is a great fra
So, ultimately, **we decided to pull the plug and rewrite the entire thing in [Lit](https://lit.dev/).** So, ultimately, **we decided to pull the plug and rewrite the entire thing in [Lit](https://lit.dev/).**
Lit is a lightweight framework built on top of web components and “adds just what you need to be happy and productive: reactivity, declarative templates and a handful of thoughtful features to reduce boilerplate and make your job easier” (taken from their docs). We had used it before to [build the Nx Cloud view](https://blog.nrwl.io/nx-console-meets-nx-cloud-d45dc099dc5d?source=friends_link&sk=90215eb316ef332c1324f2d50cd3ad85) and were happy with the simple setup and great DX. So the decision to reuse it here was an easy one, since it allowed us to reuse code, build tooling and expertise. The rewrite also gave us the opportunity to improve the design for both supported IDEs and give the entire UI a clean, new coat of paint. Lit is a lightweight framework built on top of web components and “adds just what you need to be happy and productive: reactivity, declarative templates and a handful of thoughtful features to reduce boilerplate and make your job easier” (taken from their docs). We had used it before to [build the Nx Cloud view](/blog/nx-console-meets-nx-cloud) and were happy with the simple setup and great DX. So the decision to reuse it here was an easy one, since it allowed us to reuse code, build tooling and expertise. The rewrite also gave us the opportunity to improve the design for both supported IDEs and give the entire UI a clean, new coat of paint.
![Screenshot of the reworked generate ui](/blog/images/2023-06-29/bodyimg2.webp) ![Screenshot of the reworked generate ui](/blog/images/2023-06-29/bodyimg2.webp)
@ -62,7 +62,7 @@ This architectures modularity meant we could quickly switch out the Generate
If you want to dive deeper, there are many more resources on the architecture of Nx Console and how its built: If you want to dive deeper, there are many more resources on the architecture of Nx Console and how its built:
- [In-depth blog post about expanding to JetBrains IDEs](https://blog.nrwl.io/expanding-nx-console-to-jetbrains-ides-8a5b80fff2d7?source=friends_link&sk=967080ea30bdbf9f8132f098a2cdd188) - [In-depth blog post about expanding to JetBrains IDEs](/blog/expanding-nx-console-to-jetbrains-ides)
- [Accompanying Youtube video by Zack DeRose](https://www.youtube.com/watch?v=xUTm6GDqwJM) - [Accompanying Youtube video by Zack DeRose](https://www.youtube.com/watch?v=xUTm6GDqwJM)
- [The Power of Nx Console — talk by Jon Cammisuli](https://www.youtube.com/watch?v=3C_9g9kt2KM) - [The Power of Nx Console — talk by Jon Cammisuli](https://www.youtube.com/watch?v=3C_9g9kt2KM)
@ -131,7 +131,7 @@ If you need to pass information up the DOM, you use normal events and you can se
### Communicating with the IDE — using Reactive Controllers ### Communicating with the IDE — using Reactive Controllers
To communicate with the host IDE, we were able to reuse almost all the logic from the previous UI (for more details, see [Communicating with IntelliJ](https://blog.nrwl.io/expanding-nx-console-to-jetbrains-ides-8a5b80fff2d7?source=friends_link&sk=967080ea30bdbf9f8132f098a2cdd188#d151) from the last blog post). Instead of a service that exposes observables that our component can consume, we used a [Reactive Controller](https://lit.dev/docs/composition/controllers/). Controllers are a neat feature of Lit — they hook into a component and can request DOM updates on their behalf. This eliminates the need for observable streams and subscriptions while keeping the communication code self-contained. Look at this example: To communicate with the host IDE, we were able to reuse almost all the logic from the previous UI (for more details, see [Communicating with IntelliJ](/blog/expanding-nx-console-to-jetbrains-ides) from the last blog post). Instead of a service that exposes observables that our component can consume, we used a [Reactive Controller](https://lit.dev/docs/composition/controllers/). Controllers are a neat feature of Lit — they hook into a component and can request DOM updates on their behalf. This eliminates the need for observable streams and subscriptions while keeping the communication code self-contained. Look at this example:
```ts {% fileName="main.ts" %} ```ts {% fileName="main.ts" %}
@customElement('root-element') @customElement('root-element')
@ -294,11 +294,7 @@ As mentioned earlier, Angular comes with a lot more features out-of-the-box than
We were able to reduce the bundle size (w/o compression) from about 733 kB to 282 kB, which comes out to about a 2,6x decrease. Unlike a website, where the bundle needs to be shipped to users when they load a page, Nx Console users only need to download it once when installing the plugin. This means were not affected by network speeds after installation, which makes the bundle size less critical. We were able to reduce the bundle size (w/o compression) from about 733 kB to 282 kB, which comes out to about a 2,6x decrease. Unlike a website, where the bundle needs to be shipped to users when they load a page, Nx Console users only need to download it once when installing the plugin. This means were not affected by network speeds after installation, which makes the bundle size less critical.
> 💡 Because of a misconfiguration from a few Angular versions ago, the bundle size that we reported in: > 💡 Because of a misconfiguration from a few Angular versions ago, the bundle size that we reported in [this tweet](https://twitter.com/MaxKless/status/1671095858182381569) was overly bloated. We corrected it, but Lit still came out ahead in terms of size and rendering times.
{% tweet url="https://twitter.com/MaxKless/status/1671095858182381569" /%}
was overly bloated. We corrected it, but Lit still came out ahead in terms of size and rendering times.
### Build Time ### Build Time

View File

@ -0,0 +1,237 @@
---
title: 'Nx 16.5 Release!!!'
slug: 'nx-16-5-release'
authors: ['Zack DeRose']
cover_image: '/blog/images/2023-07-06/1*Gm3s_wLWrAf_uH2AzfJvvQ.png'
tags: [nx, release]
---
We have launched SO MANY features since our last release blog on Nx 16.0, so were covering the major features in this blog!
{% youtube src="https://youtu.be/7XLoLOc3afY" /%}
Be sure to mark your calendars for our Nx 16.5 livestream as well! Well highlight the features you see here AND field any questions live! Follow the link to schedule a notification for when we go live:
{% youtube src="https://youtu.be/EYgkKmYbRNI" /%}
## Targetting Tasks By Tags
Our first major feature actually comes to us from the community. Nx has supported a tags property in your project.json file for awhile now — and its main purpose has been to be used in conjuncture with the [Nx Module Boundary lint rule](/features/enforce-module-boundaries) to define which projects in your Nx workspace can depend on what — for example, you dont want your frontend applications to depend on any backend-specific code.
With this new feature, you can add the `--tag` option to the [`nx affected`](/nx-api/nx/documents/affected) and [`nx run-many`](/nx-api/nx/documents/run-many) commands to specify to Nx to only run commands for projects that match the given tags.
{% youtube src="https://youtu.be/enQDQmFquGU" /%}
## NextJS 13 Support
React Server Components and the new NextJS app router are here, and Nx is here to support them. Weve added support for the latest versions of Next — complete with generators and executors. Weve also made sure that our [`withNx` NextJS plugin](/recipes/next/next-config-setup), which allows you to import from your other projects in your workspace while still working with the NextJS build scripts, works both for workspaces using our executors in an Integrated Monorepo approach, as well as for those using a Package-Based approach that are simply using the `next dev` command directly to start their dev server.
Theres also built-in support for the new turbopack builder option via the `--turbo` command, for example: `nx serve webapp --turbo`
Weve also launched a new preset for `npx create-nx-workpace` for a standalone NextJS app. Checkout it out using the command: `npx create-nx-workspace@latest --preset=nextjs-standalone` or use the interactive prompts to find it:
![](/blog/images/2023-07-06/0*EZrDq742M_PZZhgn.avif)
Weve added a couple videos specifically on Next development in an Nx workspace in the past month, so if youre looking for more on Next, be sure to check them out!
{% youtube src="https://youtu.be/RupxGAQ3fBY" /%}
{% youtube src="https://youtu.be/X3WfXAZZH7s" /%}
## New Nx Recipes!!!
Did you know that we maintain [a set of Nx workspaces](https://github.com/nrwl/nx-recipes) designed to serve as examples for different Nx Workspaces?
Weve recently added examples repos for:
- fastify + mongo
- fastify + postgres
- fastify + redis
- nextjs + trpc
- remix
- serverless + fastify + planetscale
Go check it out at [https://github.com/nrwl/nx-recipes](https://github.com/nrwl/nx-recipes) and let us know in the comments if there are more recipes youd like to see or if you want to see videos made from any of the existing recipes!
## Angular 16 Support And Migrations
Angular is continuing their pattern of releasing new and exciting features — and in Nx 16.1, we added support for Angular 16, including updates to our NgRx generators and cypress support.
As usual, we provide migrations to the most recent Angular version to cover your codebase for any breaking changes going to Angular 16.
And in case you missed it, Nx is no longer tied to your Angular version — the most recent version of Nx will now always [support all currently LTS versions of Angular](/nx-api/angular/documents/angular-nx-version-matrix), meaning you DONT have to upgrade your Angular version in order to get all these latest Nx Features. Be sure to use the `--interactive` flag to take advantage of this feature: `nx migrate latest --interactive`. You can find more details in [our docs for choosing optional packages to apply](/recipes/tips-n-tricks/advanced-update).
{% youtube src="https://youtu.be/AQV4WFldwlY" /%}
## New `verdaccio` support!
The `@nx/js` package now includes a new `setup-verdaccio` generator as well as a `verdaccio` executor!
{% youtube src="https://youtu.be/t1c925TzrzE" /%}
Running `nx g setup-verdaccio` will now add a new `local-registry` target to your workspace, that will use the new `verdaccio` executor.
To start your local registry, run the command `nx local-registry` in one terminal, and then you can publish via commands like `npm publish` as you normally would, but rather than publish packages to the npm registry, this will only publish those packages to your locally-running registry!
While the `local-registry` process is running, you will also be able to install packages published to your local registry as well.
These tools should help in particular with local testing of publishing packages to help support both manual and automated testing!
## Create your own CLI with Nx
The use of command-line interfaces (CLIs) to create new workspaces is common in various technologies. React has one, so does Angular, Vue, Vite and many more. Maintaining a good CLI experience can be tedious though, especially because framework authors would rather want to focus on the library or framework itself.
For a while now, Nx plugin authors had the possibility to create a so-called “preset” to control the entire Nx workspace structure. Once published it can be invoked by using the `--preset` flag:`npx create-nx-workspace myapp --preset=@my/plugin`. [Qwik-Nx](https://github.com/qwikifiers/qwik-nx) is an example of that.
However, many authors would rather want to have a more “branded” experience. Like being able to invoke the previous example as follows:
```shell
npx create-qwik-nx myapp
```
To fulfill this need, in 16.5 we ship with a new `create-package` generator that allows you to add and ship such "CLI package" with your Nx plugin.
You can either create a new Nx plugin workspace immediately with a CLI package using:
```shell
npx create-nx-plugin my-own-cli --create-package-name=create-my-own-cli-app
```
Or alternatively add it to an existing Nx plugin workspace using:
```
nx g @nx/plugin:create-package <cli name> --project=<existing plugin name> --e2eProject e2e
```
## New `externalDependencies` Input Type
Nx now supports a new input type: `externalDependencies` to add to the existing input types: `filesets`, `runtime` inputs, and `env` variables.
By default, Nx will take the defensive stance of assuming that all packages will affect your commands, meaning all external dependencies are taken into account when hashing your tasks dependencies.
The new `externalDependencies` input type allows you to specify a specific set of external dependencies for a given command, so you can configure your tasks to more accurately reflect their inputs.
For example, if you have a `publish-package` target that is using a `command` of `lerna publish` for your publishing, you can specify that the only external dependency for that specific input is `lerna`:
```json
{
"name": "mylib",
// ...
"targets": {
"publish-package": {
"command": "lerna publish",
"inputs": [{ "externalDependencies": ["lerna"] }]
}
}
}
```
This way you are free to change other dependencies that dont affect this task without invalidating your cached run of the task.
{% youtube src="https://youtu.be/FRqgWBmHmAU" /%}
## New `@nx/dependency-checks` EsLint Rule
Weve added a new `@nx/dependency-checks` lint rule to help with detecting any issues when specifying dependencies for your packages.
This rule will analyze your source code to determine any dependencies you are using in this specific package, and will catch any missing dependencies, mismatched versions, and unused dependencies in your projects `package.json` file.
Even better, this rule supports the `--fix` option to automatically fix any issues that are found - making it a great tool for automating your dependencies.
After migrating your Nx workspace, you should have access to this lint rule. To turn it on, youll need to adjust the `lint` targets in your `project.json` files to include your `package.json` files like so:
```json
{
"name": "webapp",
// ...
"targets": {
// ...
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"apps/webapp/**/*.{ts,tsx,js,jsx}",
"apps/webapp/package.json" // here!
]
}
}
}
}
```
Then in “webapp” projects `.eslintrc.json` file you'll want to turn the rule on for your json files:
```json
{
...
"overrides": [
// ...
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}
```
Now you should be able to run the linter via `nx run-many --target=lint` to catch any errors across any of your packages, and you can `nx run-many --target=lint --fix` to automatically fix all errors as well.
## Nx Goes Brrrrrr
Nx has continued to get faster!
Our biggest speed increase has come from moving our task hashing into the Nx Daemon. A daemon process refers to a process that runs continuously in the background.
Because the daemon persists between command runs, we are able to have more of the work that goes into hashing a task cached, which we added in Nx 16.3!
In Nx 16.4 we also moved to a rust-based watcher to further improve performance. We had already began the migration of some of the more performance-intensive computation of Nx to Rust in prior version, but were excited to bring more of the core of Nx into Rust and see more of these performance gains!
Since our last benchmarking of Nx in October of last year where we clocked Nx at 276.2ms per command, these speed boosts have now gotten us down to 149.3ms, nearly doubling our speed!!
You can see our results and the details of the benchmark — and even run the benchmarks for yourself in [this repo](https://github.com/vsavkin/large-monorepo).
## Nx Console Revamped
Nx Console got a new coat of paint in both the VsCode and JetBrains (IntelliJ/Webstorm) IDEs!
![](/blog/images/2023-07-06/0*5nr7ReGoDTIEw5kl.avif)
_New Nx Console Coat of Paint in VsCode_
![](/blog/images/2023-07-06/0*Uox5jg4O4DEM4kAJ.avif)
_New Nx Console Coat of Paint in IntelliJ_
As part of the redesign, we also moved our webviews to the Lit framework — checkout all the latest updates in this video:
{% youtube src="https://youtu.be/p455D4W7330" /%}
## Nx Changelog Launched
Last but CERTAINLY not least, weve launched [a new changelog](/changelog) to our docs site!
![](/blog/images/2023-07-06/0*-RewMSU5fPazv_fn.avif)
This changelog includes links to all the release notes for all major and minor versions, as well as links to patch versions. We made sure to also include any deprecations or breaking changes brought about by each version as well.
## Wrap Up
Thats all for now folks! Were just starting up a new iteration of development on Nx, so be sure to subscribe to [our YouTube channel](https://youtube.com/@nxdevtools) to get updates when new features land! Until next time, KEEP WORKING HARD!
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
- 🚀 [Speed up your CI](/nx-cloud)
## More Nx Release Notes:
- [Nx 16.0](/blog/nx-16-is-here)
- [Nx 15.8](/blog/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook)
- [Nx 15.7](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning)
- [Nx 15.4](/blog/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more)
- [Nx 15.3](/blog/nx-15-3-standalone-projects-vite-task-graph-and-more)

View File

@ -0,0 +1,202 @@
---
title: 'Evergreen Tooling — More than Just CodeMods'
slug: 'evergreen-tooling-more-than-just-codemods'
authors: ['Juri Strumpflohner']
cover_image: '/blog/images/2023-07-26/1*CPiI60mSguYXJzPfAHMbEQ.png'
tags: [nx]
---
As developers we always want to use the latest shiny tools. Theres a new bundler? Lets try! A new code editor, Im in! For your side-project: for sure! At work: nah, not really. Keeping your tooling up to date with the rather fast moving JS ecosystem can be a major challenge. Nx provides a mechanism that can help mitigate that, by providing a command to upgrade your tooling automatically:
```shell
npx nx migrate latest
```
**Prefer a video? Ive got you covered!**
{% youtube src="https://www.youtube.com/watch?v=Ss6MfcXi0jE" /%}
## TL;DR
You can run the following command to automatically upgrade your Nx workspace to the latest version:
```shell
npx nx migrate latest
```
## The Balancing Act: Updating Tooling vs Shipping Features
If youre anything like me, youve probably found that discussions about updating tooling tend to fall to the bottom of the priority list when talking to your product owner. Its understandable — their primary goal is to ship features. However, sticking with outdated tooling can impact our ability to deliver these features swiftly (not to speak about potential security concerns due to outdated libraries).
Dont get me wrong, Im not suggesting that we should always be on the bleeding edge of technological innovation — especially in an enterprise environment.
> _Jason Lengstorf has some opinions there as well:_ [_“The Hidden Danger of Switching Tech Stacks in 2023_](https://youtu.be/u0j-DlsimZ4)_?)._
Its wise to let security patches land and initial bugs get fixed before jumping on the upgrade bandwagon. But heres the catch — dont wait too long. The **longer you delay upgrading, the more challenging and time-consuming** it becomes. And the more effort it requires, the harder it is to sell the idea to your product owner.
## The Key: Making Updates Easy(ier)!
Updating tooling is never easy, but the Nx team aims at making it “easier” at least. We try to embrace the concept of “evergreen tooling”, a strategy thats been around since Google decided to automatically update Chrome for all users. The Angular team adopted this approach for their Angular CLI, and Nx has followed suit. But what exactly is it, and how does it work?
> _What if I told you Nx users have been_ **_automatically_** _updating their React applications from Webpack 4 to Webpack 5!_
The “why” is pretty straightforward. From the perspective of an open-source project, you want users to adopt the latest version as quickly as possible. This minimizes the maintenance work involved in supporting older versions, which can be a real headache. Looking at how Nx manages it, it seems to be successful in this regard ([Source](https://www.craigory.dev/npm-burst/?package=nx)):
![](/blog/images/2023-07-26/0*M7X1nddld2oBJ736.avif)
The distribution of Nx installs by version demonstrates the effectiveness of this approach. For instance, v16.5, which accounts for 19.7% of all versions, has already been adopted by many users, despite [its recent release](/changelog). The latest major accounts for 34.7% already and 41.4% are on the previous v15, a large majority of which is on the latest 15.9 minor. Hence, v16 & v15 make up 3/4 of all Nx installs.
## How? Database Migration Scripts for Code?
If you know what “database migration scripts” are, then yes, its the same concept but applied at the code level. A series of small functions invoked to bring your workspace from version X to version Y (usually the latest). That includes:
- update `nx` itself
- update all Nx plugins and the technology they are responsible for (for example: `@nx/react` will upgrade React as well, `@nx/webpack` is upgrading Webpack)
- automatically adjust relevant config files and source code (e.g., adjusting imports, functions etc..)
Everything that is required to get you to the latest version and still have a running code, even if there have been breaking changes.
**How?!** Because the **Nx team (and plugin authors) do the work for you**! Nx has a built-in mechanism where you can define so-called “migrations” for each Nx package. Heres an excerpt of the `@nx/webpack`'s migration file.
```json
{
“generators”: {
"add-babel-inputs": {
“cli”: “nx”,
“version”: “15.0.0-beta.0”,
“description”: “Adds babel.config.json to the hash of all tasks”,
"factory": "./src/migrations/update-15-0-0/add-babel-inputs"
},
"remove-es2015-polyfills-option": {
“cli”: “nx”,
“version”: “15.4.5-beta.0”,
“description”: “Removes es2015Polyfills option since legacy browsers are no longer supported.”,
"factory": "./src/migrations/update-15-4-5/remove-es2015-polyfills-option"
},
"webpack-config-setup": {
“cli”: “nx”,
“version”: “15.6.3-beta.0”,
“description”: “Creates or updates webpack.config.js file with the new options for webpack.”,
"factory": "./src/migrations/update-15-6-3/webpack-config-setup"
},
"add-babelUpwardRootMode-flag": {
“cli”: “nx”,
“version”: “15.7.2-beta.0”,
“description”: “Add the babelUpwardRootMode option to the build executor options.”,
"factory": "./src/migrations/update-15-7-2/add-babelUpwardRootMode-flag"
},
"update-16-0-0-add-nx-packages": {
“cli”: “nx”,
“version”: “16.0.0-beta.1”,
"description": "Replace @nrwl/webpack with @nx/webpack",
"implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages"
}
},
...
}
```
They are defined in a `migrations.json` config file within the NPM package. Each entry defines a `version` for which the entry should be run, a `description` (just for humans to read) and a `factory` property which points to a TypeScript file.
Example: if youre on Nx 15.5 and you run `nx migrate latest` it would run the corresponding “factory functions” for:
- `webpack-config-setup`
- `add-babelUpwardRootMode-flag`
- `update-16-0-0-add-nx-packages`
Depending on the nature of the update, these functions can be as simple as performing text replacements to more complex AST parsing and TypeScript source file manipulations. Lets have a look at the `add-babelUpwardRootMode-flag` migration:
```
import {
formatFiles,
readProjectConfiguration,
Tree,
updateProjectConfiguration,
} from '@nx/devkit';
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
import { WebpackExecutorOptions } from '../../executors/webpack/schema';
export default async function (tree: Tree) {
forEachExecutorOptions<WebpackExecutorOptions>(
tree,
@nrwl/webpack:webpack,
(
options: WebpackExecutorOptions,
projectName,
targetName,
_configurationName
) => {
if (options.babelUpwardRootMode !== undefined) {
return;
}
typconst projectConfiguration = readProjectConfiguration(tree, projectName);
projectConfiguration.targets[targetName].options.babelUpwardRootMode =
true;
updateProjectConfiguration(tree, projectName, projectConfiguration);
}
);
await formatFiles(tree);
}
```
It leverages the utility functions provided by the `@nx/devkit` package to read the various `projects.json` files to adjust the `babelupwardRootMode` property.
Nxs modular design helps as each plugin is responsible for a particular area and can thus contribute according migration scripts. To give you some context. There is the [nx package](https://www.npmjs.com/package/nx) at the core — which you can use nicely in combination with a [PNPM workspaces repo](/blog/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx) to speed things up — and then there are plugins built on top.
![](/blog/images/2023-07-26/0*LNYWLmdgxQ07bqyt.avif)
_(Source:_ [_/getting-started/why-nx_](/getting-started/why-nx)_)_
These plugins are usually technology-specific, like a plugin to help you manage React, Next, Remix, or Angular projects and tooling like ESLint, Cypress, Playwright, Vite, Jest, and so on. There are no limits as you can [create your own](/extending-nx/intro/getting-started). They are **optional**, in that you can use Nx and React and set everything up on your own. But it might be worth relying on them for some better DX and automation, such as the update mechanism were currently looking at.
Plugins are helpful here, because each plugin has a clearly defined responsibility. Like the `@nx/webpack` we looked at earlier, handles everything related to Webpack. So itll be responsible for updating the `webpack` NPM package and adjusting config Webpack-related files.
## Performing the Update
Alright, weve learned how these updates work behind the scenes. Lets look at what the experience looks like as a developer performing the update on your codebase.
> _Note, it is highly recommended to start with a clean Git workspace s.t. you can quickly revert the update._
To run the update, use the following command:
```shell
npx nx migrate latest
```
Note `latest` stands for the target version. You can also provide a specific Nx version if you cannot update to the latest one for some reason.
At this point, Nx
- analyzes your workspace and finds all the plugins youre using
- downloads the version of the plugins specified in the migrate command above
- collects all the `migration.json` files from these plugins
- picks out the relevant ones based on your current workspace version
- creates a `migrations.json` at the root of your workspace
- updates the `package.json` to point to the matching NPM package versions (without performing an install just yet)
You can now inspect the `migration.json` and the `package.json` before you run the following command to run the migrations on your codebase.
```shell
npx nx migrate —-run-migrations
```
After that, your codebase should have been updated. Run your (ideally automated) sanity checks and fix the remaining issues that couldnt be adjusted automatically.
## Wrapping Up
Thats it! If you want to dive deeper, here are some potentially helpful links:
- [Watch our YT video about Code Migrations](https://youtu.be/Ss6MfcXi0jE)
- [/features/automate-updating-dependencies](/features/automate-updating-dependencies)
Also, if you havent already, give us a ⭐️ on Github: [https://github.com/nrwl/nx](https://github.com/nrwl/nx). Wed appreciate it 😃.
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -0,0 +1,73 @@
---
title: 'Storybook Interaction Tests in Nx'
slug: 'storybook-interaction-tests-in-nx'
authors: ['Katerina Skroumpelou']
cover_image: '/blog/images/2023-08-03/1*NfJA7VBZvDwyyZHmV8qsiw.png'
tags: [nx]
---
In Nx 16.6 we are introducing our new generators for [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing)! These new generators replace the default Cypress tests we used to generate along with a projects Storybook configuration, particularly for those already using Storybook. The intention is that if a user chooses to use Storybook and generate Storybook configuration, to integrate in that experience Storybook Interaction testing, and skip generating Cypress tests, to keep everything in one place, in an integrated experience.
**Prefer a video walkthrough? Weve got you covered**
{% youtube src="https://www.youtube.com/watch?v=SaHoUx-TUs8" /%}
## Understanding Storybook Interaction Tests
Interaction tests allow users to verify the functional aspects of UIs. This is done by supplying the initial state of a component, simulating user behavior such as clicks and form entries, and finally checking if the UI and component state update correctly. Very much like e2e tests are doing.
In Storybook, this workflow occurs in your browser, which makes it easier to debug failures since youre running tests in the same environment you develop components.
## How it works
You write a story to set up the components initial state, simulate user behavior using the [play function](https://storybook.js.org/docs/react/writing-stories/play-function), and then use the [test runner](https://storybook.js.org/docs/react/writing-tests/test-runner) to confirm that the component renders correctly and that your interaction tests with the play function pass. [Storybooks Test runner](https://storybook.js.org/docs/react/writing-tests/test-runner) is a standalone utility — powered by Jest and Playwright — that executes all of your interaction tests, and runs parallel to your Storybook.
## Setting Up Storybook Interaction Tests on Nx
You can read our detailed guide on how to set up Storybook interaction tests on Nx, here: [/recipes/storybook/storybook-interaction-tests](/recipes/storybook/storybook-interaction-tests).
## Writing Interaction Tests in Storybook
An interaction test is defined inside a play function connected to a story. The story simulates the users behavior once it loads in the UI and verifies the underlying logic.
Under the hood, Storybooks [@storybook/addon-interactions](https://storybook.js.org/addons/@storybook/addon-interactions) mirrors [Testing Library](https://testing-library.com/)s user-events API. So, you can use the same queries and assertions that you would use for Testing Library, like we already do with our unit tests.
For complex flows, it can be worthwhile to group sets of related interactions using the step function. This allows you to provide a custom label that describes a set of interactions.
## Debugging and Reproducing Errors
Storybook provides an interactive debugger that displays the step-by-step flow of your interactions, and provides UI controls to pause, resume, rewind, and step through each interaction.
![](/blog/images/2023-08-03/0*ZhrFxCwtYkO3gLaU.avif)
_Interaction test for the click of a button._
If an error occurs during a storys play function, itll be shown in the interaction addon panel to help with debugging. And since Storybook is a web app, anyone with the URL can reproduce the error with the same detailed information without any additional environment configuration or tooling required.
## Executing and Automating Tests
Storybook only runs the interaction test when youre viewing a story. Therefore, as a Storybook grows, it becomes unrealistic to review each change manually. The Storybook test-runner automates the process by running all tests for you. This can be executed via the command line or on CI environment.
## What should I choose? Interaction tests or E2E tests?
Setting up interaction tests with Nx and Storybook provides an extra layer of confidence in the functionality of your components. It ensures that they not only look right but also behave correctly in response to user interactions.
Storybook interaction tests provide a unique advantage over traditional e2e tests, especially when considering the development setup. With Storybook already in place, you essentially have a controlled environment set up for each of your components. This allows you to write interaction tests almost immediately, without the overhead of setting up and navigating through a full application environment, as is the case with e2e tests.
Moreover, since Storybook isolates each component, you can ensure that the tests are solely focused on individual component behavior rather than application-level concerns. This results in faster test execution, easier debugging, and more granular feedback during the development process. In essence, with Storybooks interaction tests, you get many of the benefits of e2e tests but with a setup thats quicker, more focused, and integrated right into your component development workflow.
## Screenshare
{% youtube src="https://www.youtube.com/embed/QvD3hJDa_1Q" /%}
## Useful Links
- [https://storybook.js.org/docs/react/writing-tests/interaction-testing](https://storybook.js.org/docs/react/writing-tests/interaction-testing)
- [/recipes/storybook/storybook-interaction-tests](/recipes/storybook/storybook-interaction-tests)
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -0,0 +1,646 @@
---
title: 'Create Your Own create-react-app CLI'
slug: 'create-your-own-create-react-app-cli'
authors: ['Emily Xiong']
cover_image: '/blog/images/2023-08-10/1*j2QU-hjxt-1krFST8CGFiA.png'
tags: [nx]
---
Most technologies have a CLI to create a new workspace. In fact, it is so prevalent that NPM and other package managers support it natively. For example:
- Nx has [create-nx-workspace](/getting-started/installation)
- React has, well, had [create-react-app](https://create-react-app.dev/)
- Angular has [Angular CLI](https://angular.io/cli)
- Vite has [create-vite](https://vitejs.dev/guide/#scaffolding-your-first-vite-project)
Having a CLI to quickly scaffold a starting project is great for onboarding new people, but it can also be a burden for framework authors as they want to rather focus on building the framework. Additionally, building **and supporting** a good CLI is another beast to tackle. And this is where Nx comes in.
Nx has had support for [creating custom “presets”](/extending-nx/recipes/create-preset) for a while, allowing plugin authors to fully customize the workspace structure from the ground up. To use them you had to go via the `create-nx-workspace` command though, passing the name of your plugin as the `--preset` . This works, but you might want to have a more “branded command” experience, like `npx create-my-own-app` .
And this is exactly what were going to explore in this article. We will write our own CLI. And out of nostalgia, lets build our own version of Create-React-App.
If you want to check out the final result, heres the corresponding Github repo: [https://github.com/nrwl/nx-recipes/tree/main/nx-devkit-create-own-cli](https://github.com/nrwl/nx-recipes/tree/main/nx-devkit-create-own-cli)
**Prefer a video? We got you covered!**
{% youtube src="https://www.youtube.com/watch?v=ocllb5KEXZk" /%}
## What is Nx and what is an Nx plugin?
But before we jump right into the topic, what is Nx? And more specifically, what are Nx Plugins?
Nx is an open-source build system that provides tools and techniques to enhance developer productivity. [Check out this 10 min video overview](https://youtu.be/-_4WMl-Fn0w) of Nx if you want to learn more.
Our example, in particular, uses Nx as a dev tool for creating a CLI and plugin. Nx plugins are npm packages that provide integrations between Nx and other technologies. You can use Nx without them, but they can provide great value if applied properly. `my-own-react` is the plugin to integrate React and Nx.
## Step 1: Create a CLI workspace
Create a new Nx workspace that is preconfigured for plugin development, using the below command:
```shell
npx create-nx-plugin my-own-react --create-package-name=create-my-own-react-app
```
Note, if you already have an existing Nx plugin workspace, instead of creating a new workspace, you can simply run the following in your plugin repository to generate the create CLI:
```
nx g @nx/plugin:create-package <cli name> --project=<existing plugin name> --e2eProject e2e
```
![](/blog/images/2023-08-10/1*dL5XHPOGCtfFyTHhloaYcQ.avif)
_Project graph of the workspace_
The resulting workspace contains 2 projects: a CLI and an Nx plugin.
- **create-my-own-react-app:** The CLI project. It contains the code to run when developers invoke `npx create-my-own-react-app`. This will set up a workspace for the developer.
- **my-own-react:** Nx plugin to integrate react with Nx. It will contain the code for creating and serving an app. It is under the src folder. This will be installed in the users workspace.
### CLI Package Structure
Lets focus on the `create-my-own-react-app` project which is our CLI.
![](/blog/images/2023-08-10/1*00F7H_Z13uonZiflZSQd8Q.avif)
The `index.ts` file is the key part here. It is the one that gets invoked when someone runs `npx create-my-own-react-app` later once we publish it.
```
#!/usr/bin/env node
import { createWorkspace } from 'create-nx-workspace';
async function main() {
const name = process.argv\[2\]; // TODO: use libraries like yargs or enquirer to set your workspace name
if (!name) {
throw new Error('Please provide a name for the workspace');
}
console.log(`Creating the workspace: ${name}`);
// This assumes "my-own-react" and "create-my-own-react-app" are at the same version
// eslint-disable-next-line @typescript-eslint/no-var-requires
const presetVersion = require('../package.json').version;
// TODO: update below to customize the workspace
const { directory } = await createWorkspace(`my-own-react@${presetVersion}`, {
name,
nxCloud: false,
packageManager: 'npm',
});
console.log(`Successfully created the workspace: ${directory}.`);
}
main();
```
The main chunk of code is `` createWorkspace(`my-own-react@${presetVersion}`) ``. This function creates an Nx workspace with the `my-own-react` plugin installed.
2. `createWorkspace` will also generate the preset generator defined by `my-own-react` located at `src/generators/preset/generator.ts`. This is the logic which scaffolds a project which uses your technology.
## Step 2: Run the CLI Locally
To properly test your CLI you can either publish it to NPM as a beta version or use a local npm registry like [Verdaccio](https://verdaccio.org/). Luckily our Nx workspace already comes with a feature to make that a seamless process.
1. First, start a local Verdaccio-based npm registry using the following command:
```shell
npx nx local-registry
```
This will start the local registry on port 4873 and configure npm to use it instead of the real npm registry.
2\. In the second terminal, run the command to publish all the projects:
```shell
npx nx run-many --targets publish --ver 1.0.0 --tag latest
```
_(Note,_ `_publish_` _is a target defined in the_ `_project.json_` _of our projects.)_
This command will publish both `my-own-react` and `create-my-own-react-app` packages to your local registry. If open the running Verdaccio registry at [http://localhost:4873](http://localhost:4873) you should see the published packages.
![](/blog/images/2023-08-10/1*_D72hvW4nrl_DSYyMQU0DQ.avif)
3\. Now, you can run `npx create-my-own-react-app` just like a developer using our CLI would. For example, go to the tmp directory and create a `my-own-react` workspace named `test`:
```shell
cd tmp
npx create-my-own-react-app@1.0.0 test
```
What youll get is an Nx workspace with the base setup and a `test` library project with a single TS file. Because thats exactly what our current `preset` generator does.
![](/blog/images/2023-08-10/1*v70qP_BS6LJm3NMAYkv2KQ.avif)
Lets fix that in the next step.
### Step 3: Change the CLI to Setup a React App
In this step, we dive a bit more into the actual Nx plugin development to create our CRA replica.
Well go rather quickly but if you want a slower walkthrough you might be interested in this video that leverages a generator for automating the creation of projects. Exactly what were going to do in our preset now.
{% youtube src="https://youtu.be/myqfGDWC2go" /%}
To do this, we will fill in the preset generator under `src/generators/preset`
A generator is a function that makes modifications to a file system representation known as the `Tree`. These modifications will then be applied to the real file system. In our case, the preset generator will create the files for a React app.
Currently, the file at `src/generators/preset/generator.ts` looks like:
```
import {
addProjectConfiguration,
formatFiles,
generateFiles,
Tree,
} from '@nx/devkit';
import * as path from 'path';
import { PresetGeneratorSchema } from './schema';
export async function presetGenerator(
tree: Tree,
options: PresetGeneratorSchema
) {
const projectRoot = `libs/${options.name}`;
addProjectConfiguration(tree, options.name, {
root: projectRoot,
projectType: 'library',
sourceRoot: `${projectRoot}/src`,
targets: {},
});
generateFiles(tree, path.join(__dirname, 'files'), projectRoot, options);
await formatFiles(tree);
}
export default presetGenerator;
```
The preset generator does 2 things:
- Create an Nx project using the`addProjectConfiguration` function. This creates a `project.json` file which allows Nx to run commands on it.
- Generates files in the project using the`generateFiles` function. This uses the templates under `src/generators/preset/files` which are interpolated to become the files that are generated for the user.
- Format the generated files with `prettier` with the`formatFiles` function
![](/blog/images/2023-08-10/1*38RvkLIwUAvVDDrEp5sFPQ.avif)
_preset generator_
The `addProjectConfiguration` and `generateFiles` functions are from [@nx/devkit](/nx-api/devkit/documents/nx_devkit), a library that contains utility functions for writing plugins for Nx. For the future, see the [complete list of utility functions](/nx-api/devkit/documents/nx_devkit).
1. Change the project which is created with `addProjectConfiguration`:
```
const projectRoot = '.';
addProjectConfiguration(tree, options.name, {
root: projectRoot,
projectType: 'application',
targets: {}
});
```
- The `projectRoot` will be ., the root of a workspace
- The `projectType` changes to `application`
2\. Next, change the files generated into the project under `src/generators/preset/files`. We will use the same template as `create-react-app` .
Rename the existing `index.ts.template` to `src/generators/preset/files/src/index.tsx.template` and add the following content:
```
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<div className="App">
<header className="App-header">
<svg className="App-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
<p>
Welcome <%= name %>!
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
</React.StrictMode>
);
```
Add another file to generate a CSS template at `src/generators/preset/files/src/index.css.template`:
```
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
```
And finally, another file to host the actual HTML template: `src/generators/preset/files/public/index.html.template`:
```shell
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
```
3\. Our application uses some npm dependencies so add those to the workspace as well with the [addDependenciesToPackageJson](/nx-api/devkit/documents/nx_devkit) function to the end of the export default function in `src/generators/preset/generator.ts`:
```
import {
addDependenciesToPackageJson,
...
} from '@nx/devkit';
...
export default async function (tree: Tree, options: PresetGeneratorSchema) {
...
return addDependenciesToPackageJson(
tree,
{
react: 'latest',
'react-dom': 'latest',
'react-scripts': 'latest',
},
{
"@types/react": "latest",
"@types/react-dom": "latest",
}
);
}
```
This line will add the latest `react`, `react-dom`, `react-scripts`, and their types to the `package.json` in the generated workspace.
### Final Preset Generator
Now `src/generators/preset/generator.ts` should look like this:
```
import {
addDependenciesToPackageJson,
addProjectConfiguration,
formatFiles,
generateFiles,
Tree,
} from '@nx/devkit';
import * as path from 'path';
import { PresetGeneratorSchema } from './schema';
export default async function (tree: Tree, options: PresetGeneratorSchema) {
const projectRoot = `.`;
addProjectConfiguration(tree, options.name, {
root: projectRoot,
projectType: 'application',
targets: {},
});
generateFiles(tree, path.join(__dirname, 'files'), projectRoot, options);
await formatFiles(tree);
return addDependenciesToPackageJson(
tree,
{
react: 'latest',
'react-dom': 'latest',
'react-scripts': 'latest',
},
{
"@types/react": "latest",
"@types/react-dom": "latest",
}
);
}
```
## Step 4: Run the New Version that Creates the React App
Now you can publish a new version of `my-own-react` and `create-my-own-react-app` and run it again:
```shell
cd ..
npx nx run-many --targets publish --ver 1.0.1 --tag latest
cd tmp
npx create-my-own-react-app@1.0.1 test2
```
The CLI now creates a workspace with the dependencies we want and the code for the react application just like `create-react-app`:
![](/blog/images/2023-08-10/1*gZ7ocdR49soEahM8TlGA4A.avif)
## Step 5: Add a Serve Target
The workspace setup is done, what were missing though is a way to easily serve our app. To stick to what CRA does we simply need to run `react-scripts start` , but ideally, we want to make that more convenient for the developer by pre-generating that script into the workspace.
We have two possibilities:
- add the script to the root-level`package.json` using the `updateJson` function exposed by `@nx/devkit`
- add a target to the `project.json` using the `addProjectConfiguration` function exposed by `@nx/devkit`
Nx can use both. The `project.json` is Nxs variant of a more evolved package.json scripts declaration, that allows to specify metadata in a structured way.
To keep things simple, lets just generate a new script for the root-level `package.json`. We need to modify our `src/generators/preset/generator.ts` as follows:
```shell
import {
updateJson,
...
} from '@nx/devkit';
...
export default async function (tree: Tree, options: PresetGeneratorSchema) {
...
addProjectConfiguration(...);
updateJson(tree, 'package.json', (json) => {
json.scripts = json.scripts || {};
// generate a start script into the package.json
json.scripts.start = 'npx react-scripts start';
return json;
});
...
}
```
Note, we want to keep our `project.json` file even though it doesnt have any targets defined. That way Nx recognizes it as a proper project and applies caching and other optimization strategies.
### Adding the target to the `project.json` rather than `package.json`
Alternatively, we could have adjusted the already present `addProjectConfiguration` function to add the `react-scripts` command:
```shell
import {
...
addProjectConfiguration,
...
} from '@nx/devkit';
...
export default async function (tree: Tree, options: PresetGeneratorSchema) {
...
addProjectConfiguration(tree, options.name, {
root: projectRoot,
projectType: 'application',
targets: {
serve: {
command: "npx react-scripts start",
}
},
});
...
}
```
## Step 6: Run it Again to Get a React App That Can Be Served
To test our changes, lets publish a new version and run it again.
```shell
npx nx run-many --targets publish --ver 1.0.2 --tag latest
```
Once we generate a new workspace with the new preset version (npx create-my-own-react-app@1.0.2 test3), we should now see our `package.json` `start`script being generated.
![](/blog/images/2023-08-10/1*Rb6xWqUiK51DsZsAGdtNbQ.avif)
To run the app we either run
- `npm start`
- or `npx nx start` which would automatically pick up the `start` script in the `package.json`
![](/blog/images/2023-08-10/1*qVf6zEOndAgYkIRgZxTYZA.avif)
![](/blog/images/2023-08-10/1*K7YZDNyIWp0Bu9tLl5VixA.avif)
_serve output_
## Step 7: Add a Prompt to the CLI to Customize the Starter App
Now, you have a CLI that creates a workspace that users can use to get started with React. But thats not all. Lets take it a step further and make it interactive by adding a prompt that can let different users customize the kind of workspace that they want to create.
Take a look at the CLI code at `create-my-own-react-package/bin/index.ts`, you will notice it is pretty barebone. It reads the`name` from the commands arguments.
You can use libraries like [enquirer](https://github.com/enquirer/enquirer) (or even fancier ones like [Clack](https://www.npmjs.com/package/@clack/prompts)) to prompt developers for options. For this example, prompt developers to select a light or dark theme for the starter app.
1. Install `enquirer` with `npm i enquirer`
2. Change `create-my-own-react-package/bin/index.ts` to import `enquirer` and prompt developers to enter the mode option:
```
#!/usr/bin/env node
import { createWorkspace } from 'create-nx-workspace';
import { prompt } from 'enquirer';
async function main() {
let name = process.argv[2];
if (!name) {
const response = await prompt<{ name: string }>({
type: 'input',
name: 'name',
message: 'What is the name of the workspace?',
});
name = response.name;
}
let mode = process.argv[3];
if (!mode) {
mode = (
await prompt<{ mode: 'light' | 'dark' }>({
name: 'mode',
message: 'Which mode to use',
initial: 'dark' as any,
type: 'autocomplete',
choices: [
{ name: 'light', message: 'light' },
{ name: 'dark', message: 'dark' },
],
})
).mode;
}
console.log(`Creating the workspace: ${name}`);
// This assumes "my-own-react" and "create-my-own-react-app" are at the same version
// eslint-disable-next-line @typescript-eslint/no-var-requires
const presetVersion = require('../package.json').version;
// TODO: update below to customize the workspace
const { directory } = await createWorkspace(`my-own-react@${presetVersion}`, {
name,
nxCloud: false,
packageManager: 'npm',
mode,
});
console.log(`Successfully created the workspace: ${directory}.`);
}
main();
```
You can assemble options for `createWorkspace`; however, youd like and they will be passed to the `my-own-react` preset.
3\. Change `src/generators/preset` to accept this option and apply it.
In `src/generators/preset/schema.d.ts`, add it to the type for the options:
```
export interface PresetGeneratorSchema {
name: string;
mode: 'light' | 'dark';
}
```
Also, change the CSS for `.App-header` in the CSS template file`src/generators/preset/files/src/index.css.template`:
```
.App-header {
background-color: <%= mode === 'dark' ? '#282c34' : 'white' %>;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: <%= mode === 'dark' ? 'white' : '#282c34' %>;
}
```
Now if you republish the projects and regenerate an app with the light mode, you should see the background color and text color of the header got changed:
![](/blog/images/2023-08-10/1*tifthl0LFTk1i3PcZWUo_A.avif)
![](/blog/images/2023-08-10/1*ruXAwt1cxeZsdN2AkZqPzA.avif)
_serve output_
## Step 8: E2E Testing
This is how users start using your technology so you should write e2e tests to ensure this does not break. This workspace was also generated with a testing file `packages/my-own-react-e2e/tests/create-my-own-react-app.spec.ts`.
You can modify this e2e test to test your CLI. Then, run it using the command `npx nx e2e my-own-react-e2e`. Before the tests run, as a global setup, a local registry is started and the packages are published.
The default test works like this:
1. Creates a test workspace at `tmp/`using the `create-my-own-react-app` CLI
2. Runs `npm ls my-own-react` to validate that the plugin is installed in the test workspace
3. Cleans up the test workspace
Make sure `dark` is passed into `create-my-own-react-app` :
```
exec1-app ${projectName} dark`, {
cwd: dirname(projectDirectory),
stdio: 'inherit',
});
```
Add to a test to check `react` and `react-dom` are installed:
```
it('react and react-dom should be installed', () => {
projectDirectory = createTestProject('dark');
// npm ls will fail if the package is not installed properly
execSync('npm ls react', {
cwd: projectDirectory,
stdio: 'inherit',
});
execSync('npm ls react-dom', {
cwd: projectDirectory,
stdio: 'inherit',
});
});
```
## Recap and next steps
Recap:
- We learned about what an Nx Plugin is and generated a new plugin workspace
- We generated a new CLI package into the workspace: `create-my-own-react-app` . This allows our users to easily scaffold a new workspace
- We adjusted the preset generator to setup a CRA-like React setup
- We wrote some e2e tests to ensure that things do not break
This should give you a good insight into how to get started. But theres more to explore:
- We could provide more [generators](/plugins/recipes/local-generators\) to our users that help with setting up new components, adding unit tests, configuring the React Router etc.
- Add a generator to add other Nx plugins such as Jest, ESLint, or Cypress
- We could also include “[executors](/extending-nx/recipes/local-executors)”, which are wrappers around tasks to abstract the lower-level details of it
- etc.
Now clearly this was a simple example of how you could build your own CRA using Nx. If you want to see a real-world React setup powered by Nx, check out our React Tutorial: [/getting-started/tutorials/react-standalone-tutorial](/getting-started/tutorials/react-standalone-tutorial)
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -49,7 +49,7 @@ npx create-nx-workspace@latest qwik-todo-app
> You can also use the `preset` created by the `qwik-nx` plugin by running `npx create-qwik-nx` or `npx -y create-nx-workspace@latest --preset=qwik-nx`. This will skip a few of the next steps by installing the appropriate dependencies and generating your Qwik app. > You can also use the `preset` created by the `qwik-nx` plugin by running `npx create-qwik-nx` or `npx -y create-nx-workspace@latest --preset=qwik-nx`. This will skip a few of the next steps by installing the appropriate dependencies and generating your Qwik app.
> >
> The `create-qwik-nx` package is an example of creating an Install Package with Nx. You can learn more here: [https://nx.dev/extending-nx/recipes/create-install-package](/extending-nx/recipes/create-install-package) > The `create-qwik-nx` package is an example of creating an Install Package with Nx. You can learn more here: [/extending-nx/recipes/create-install-package](/extending-nx/recipes/create-install-package)
Next, navigate into the workspace and install the `qwik-nx` plugin. Next, navigate into the workspace and install the `qwik-nx` plugin.

View File

@ -0,0 +1,368 @@
---
title: 'Step-by-Step Guide to Creating an Expo Monorepo with Nx'
slug: 'step-by-step-guide-to-creating-an-expo-monorepo-with-nx'
authors: ['Emily Xiong']
cover_image: '/blog/images/2023-08-24/1*IpM0kZdUNXoDWV4r8J5xXQ.png'
tags: [nx, tutorial]
---
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.
![](/blog/images/2023-08-24/1*ZObpn_5XsfYX-My6d9n4Zw.avif)
![](/blog/images/2023-08-24/1*S6bzPlLbnM_Li_0Rh7mmWw.avif)
_Left: cats, right: dogs_
As shown in the above screenshots, these two apps have the same branding and reuse all components.
This blog will go through:
- How to create a monorepo workspace with Nx
- How to share a React Native library
- How to build an Expo app
- How to submit an Expo app to the app store
Github repo: [xiongemi/nx-expo-monorepo](https://github.com/xiongemi/nx-expo-monorepo)
## Creating an Nx Workspace
To create a new Nx workspace, run the command `npx create-nx-workspace <workspace name>` in the terminal. In this example, lets name it `nx-expo-monorepo`:
```
✔ 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
```
This will create an [integrated](/deprecated/integrated-vs-package-based) repo. What is an integrated repo?
> An integrated repo contains projects that depend on each other through standard import statements. There is typically a [single version of every dependency](/concepts/decisions/dependency-management) defined at the root.
> [/deprecated/integrated-vs-package-based](/deprecated/integrated-vs-package-based)
Now, your Nx workspace should have cats and cats-e2e under the `apps` folder and an empty libs folder:
![](/blog/images/2023-08-24/1*9yWjfR4oV5B0KFSdNgCH0g.avif)
### Existing Nx Workspace
If you already have an Nx workspace, you need to install the @nx/expo package:
```shell
\# npm
npm install @nx/expo --save-dev
\# yarn
yarn add @nx/expo --dev
\# pnpm
pnpm add @nx/expo --save-dev
```
To create an Expo app, run:
```shell
npx nx generate @nx/expo:app cats
```
Alternatively, if you use Visual Studio Code as your code editor, you can also create apps using [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console):
![](/blog/images/2023-08-24/1*WB17bHQ4p3nXJYWJ_IHGaw.avif)
## Install Tech Stacks
Here are the tech stacks this example is going to use:
- Material design library: [react-native-paper](https://callstack.github.io/react-native-paper/)
```shell
\# 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
```
- Routing: [@react-navigation/native](https://reactnavigation.org/)
```shell
\# 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
```
## Create a Shareable UI Library
With all the required libraries installed, you need to create a sharable UI library:
```shell
npx nx generate @nx/expo:lib ui
```
Now under the `libs` folder, a `ui` folder has been created:
![](/blog/images/2023-08-24/1*evR014EchmXEWHJfJnbJRg.avif)
_ui folder_
To create a component in the `ui` library, run:
```shell
npx nx generate @nx/expo:component carousel --project=ui --export
```
You can see that a `carousel` folder has been created in the `libs/ui/src/lib` folder:
![](/blog/images/2023-08-24/1*s_zYPQv0QVg5-juNRXmedw.avif)
_carousel folder_
Next, modify this component to display the content with props passed in:
```tsx
import React from 'react';
import { Card, Title, Paragraph } from 'react-native-paper';
export interface CarouselProps {
imageUri?: string;
title?: string;
content: string;
}
export function Carousel({ imageUri, title, content }: CarouselProps) {
return (
<Card>
{imageUri && <Card.Cover source={{ uri: imageUri }} />}
<Card.Content>
{title && <Title>{title}</Title>}
<Paragraph>{content}</Paragraph>
</Card.Content>
</Card>
);
}
export default Carousel;
```
Now you can use this component in your app directly using an import:
```
import { Carousel } from '@nx-expo-monorepo/ui';
```
## Add Navigation
This project is going to use the [stack navigator](https://reactnavigation.org/docs/stack-navigator) from [@react-navigation/native](https://reactnavigation.org/). So the app needs to import from @react-navigation/stack. In `apps/cats/src/app/App.tsx`, you can change the UI to have one screen displaying a carousel with mock data:
```tsx
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Carousel } from '@nx-expo-monorepo/ui';
const App = () => {
const Stack = createNativeStackNavigator();
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Cat Facts"
component={() => (
<Carousel
title="title"
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec porta leo justo, id posuere urna tempor convallis. Nulla finibus, dolor sit amet facilisis pellentesque, velit nisi tempor ipsum, nec interdum libero felis a risus. Pellentesque bibendum, dolor vel varius pulvinar, tortor leo ultrices nisi, non sodales dui quam vitae nulla. Integer sed rhoncus dui. Vestibulum bibendum diam ut leo tempus, vel vulputate magna iaculis. Suspendisse tempus magna libero, sed facilisis tellus aliquet ac. Morbi at velit ornare, posuere tortor vitae, mollis erat. Donec maximus mollis luctus. Vivamus sodales sodales dui pellentesque imperdiet. Mauris a ultricies nibh. Integer sed vehicula magna."
/>
)}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
```
Run the app with`nx start cats`, and you should be able to see the app on the simulator:
![](/blog/images/2023-08-24/1*1hFA_7uBgU2GpFofNtHBiQ.avif)
_Page on the simulator (left: iOS, right: Android)_
## Add Another App
In this example, there is already a `Cats` app. To create the `Dogs` app, run the command:
```shell
npx nx generate @nx/expo:app dogs
```
Alternatively, if you use Visual Studio Code as your code editor, you can also create apps using [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console):
![](/blog/images/2023-08-24/1*8ut9KSAOn-UBBNxHJMtVXQ.avif)
Under the apps folder, there should be `cats/`, `dogs/` and their e2es.
![](/blog/images/2023-08-24/1*juth4jstENJ4h1AvIibujA.avif)
_apps folder_
You can reuse the UI library in the Dogs app in `apps/dogs/src/app/App.tsx` with the below code:
```tsx
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Carousel } from '@nx-expo-monorepo/ui';
const App = () => {
const Stack = createNativeStackNavigator();
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Dog Facts"
component={() => (
<Carousel
title="title"
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec porta leo justo, id posuere urna tempor convallis. Nulla finibus, dolor sit amet facilisis pellentesque, velit nisi tempor ipsum, nec interdum libero felis a risus. Pellentesque bibendum, dolor vel varius pulvinar, tortor leo ultrices nisi, non sodales dui quam vitae nulla. Integer sed rhoncus dui. Vestibulum bibendum diam ut leo tempus, vel vulputate magna iaculis. Suspendisse tempus magna libero, sed facilisis tellus aliquet ac. Morbi at velit ornare, posuere tortor vitae, mollis erat. Donec maximus mollis luctus. Vivamus sodales sodales dui pellentesque imperdiet. Mauris a ultricies nibh. Integer sed vehicula magna."
/>
)}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
```
## Build Expo Apps
[EAS Build](https://docs.expo.dev/build/introduction/) is a hosted service for building app binaries for your Expo and React Native projects. To set up EAS locally:
### 1. Install EAS CLI
EAS CLI is the command-line app to interact with EAS services in the terminal. To install it, run the command:
```
npm install -g eas-cli
```
### 2. Login To EAS
If you are not logged in, run the command:
```
eas login
```
### 3. Build the Apps
After the EAS setup, you can build apps by running the command:
```shell
npx nx build cats
npx nx build dogs
```
There are different options you can specify with the build command. For example, you can specify the platform you want to build:
```shell
npx nx build cats --platform=all
npx nx build cats --platform=android
npx nx build cats --platform=ios
```
Alternatively, if you want to create a build to run on a simulator/emulator, you can run:
```shell
npx nx build cats --profile=preview
```
You can view your build status at [https://expo.dev/](https://expo.dev/):
![](/blog/images/2023-08-24/1*pQxTgypzL10_SmI71jaWVQ.avif)
If you want to create a build locally using your own infrastructure:
```shell
npx nx build cats --local
```
Here is the complete list of flags for the build command: [/nx-api/expo/executors/build](/nx-api/expo/executors/build).
## Submit to the App Store
Before you submit, you need to have paid developer accounts for iOS and Android.
- iOS: You need to create an Apple Developer account on the Apple [Developer Portal](https://developer.apple.com/account/).
- Android: You need to create a Google Play Developer account on the [Google Play Console sign-up page](https://play.google.com/apps/publish/signup/). You also need to manually create an app on [Google Play Console](https://play.google.com/apps/publish/) and upload your app for the first time.
### 1\. Run the production build
To submit to the app store, you can build the app by running:
```shell
npx nx build cats --profile=production
```
### 2\. Submit the Build
You can manually upload the build bundle binary to the app store, or you can submit it through EAS.
First, in `app.json` under the project `apps/cats/app.json`, you need to make sure`ios.bundleIdentifier` and `android.package` keys are correct:
![](/blog/images/2023-08-24/1*j9TAZZgqplZCcjD4hiWNpg.avif)
_app.json_
To submit your app to the app stores, run:
```shell
npx nx submit cats
```
Nx will prompt you to choose the platform to which you want to submit:
![](/blog/images/2023-08-24/1*PcBvY1SJCHZyOnJI1hskAQ.avif)
Or you can also specify the platform directly in the initial command:
```shell
npx nx submit cats --platform=all
npx nx submit cats --platform=android
npx nx submit cats --platform=ios
```
It will then ask you to choose which binary to submit from one of the following options:
- The latest finished Android build for the project on EAS servers.
- Specific build ID. It can be found on the [builds dashboard](https://expo.dev/builds).
- Path to an .apk or .aab or .ipa archive on your local filesystem.
- URL to the app archive.
Alternatively, you can submit your app on the [expo.dev](https://expo.dev/) site. Go to your build, under options, choose “Submit to an app store”:
![](/blog/images/2023-08-24/1*yQlEmKOy3TXdWPCk9ILiZA.avif)
## Summary
In this article, you have learned how to:
- Create multiple apps in a monorepo using @nx/expo
- Create a shared library
- Build your app using EAS
- Submit your app to the App Store
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.
## Learn more
- [Unit Testing Expo Apps With Jest](/blog/unit-testing-expo-apps-with-jest)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](https://nx.app/)

View File

@ -0,0 +1,376 @@
---
title: 'Nx 16.8 Release!!!'
slug: 'nx-16-8-release'
authors: ['Zack DeRose']
cover_image: '/blog/images/2023-09-06/1*16gTRcKon8B4IKYQAY9V8w.png'
tags: [nx, release]
---
As always, the Nx Team has been hard at work, and were here to launch our latest release: Nx 16.8! And its absolutely bursting with new features. Well go into all these in depth below, but be sure to check out our latest release video on YouTube!
If you have more questions — be sure to stop by our latest Nx Live to ask them there! You can sign up for a notification from the link below!
{% youtube src="https://youtu.be/wj-gb6jqyzA" /%}
## Nx Community News!
Before we jump into the features, be sure to get plugged in to get the most out of Nx in [our NEW discord server](https://discord.gg/Pzz9BW62gD)!
Be sure to checkout our livestream with Jay Bell (Nx Champion, former Nx Community Slack admin, and current Nx Discord Admin) all about the news:
{% youtube src="https://youtu.be/yBsXB8xuTog" /%}
Nx is also coming up on 20k Github stars [please help us get there!](https://github.com/nrwl/nx)
![](/blog/images/2023-09-06/0*MyOG_Cxg_EkhULxq.avif)
**Table of Contents**
· [NEW PROJECT GENERATOR BEHAVIOR: Project Creation Paths and Names in Nx Generators](#new-project-generator-behavior-project-creation-paths-and-names-in-nx-generators)
· [Packaging TypeScript Libraries — Secondary Entrypoints, ESM, CJS](#packaging-typescript-libraries-secondary-entrypoints-esm-cjs)
· [High Performance TypeScript Compilation: Introducing Batch Mode & Rust-based Dependency Resolution](#high-performance-typescript-compilation-introducing-batch-mode-rustbased-dependency-resolution)
· [NEW Nx PLUGIN: Playwright](#new-nx-plugin-playwright)
· [NEW INTEGRATION: Netlifys Improved Monorepo Experience](#new-integration-netlifys-improved-monorepo-experience)
· [NEW Nx CONSOLE FEATURE: Interactive Graph Functionality](#new-nx-console-feature-interactive-graph-functionality)
· [ENHANCEMENT: Storybook Support for Interaction Testing](#enhancement-storybook-support-for-interaction-testing)
· [NEW GENERATOR: convert-to-monorepo](#new-generator-converttomonorepo)
· [DOCS ENHANCEMENT: Third-Party Plugin Quality Indicators](#docs-enhancement-thirdparty-plugin-quality-indicators)
· [DOCS ENHANCEMENT: Redesigned Intro & Examples](#docs-enhancement-redesigned-intro-examples)
· [NEW GENERATOR: ESLint Flat Config](#new-generator-eslint-flat-config)
· [New Nx Cloud Overview Video](#new-nx-cloud-overview-video)
· [Nx Conf Coming Up](#nx-conf-coming-up)
## NEW PROJECT GENERATOR BEHAVIOR: Project Creation Paths and Names in Nx Generators
Alright, getting into the newest updates from Nx, the biggest change is coming in the form of Nx project generators.
Originally, all Nx workspaces had a directory structure where applications were always held in an `apps/` directory, while libraries were held in the `libs/` directory.
Over the years, we found this to be much too rigid, so we made these locations more configurable. We added a `workspaceLayout` category to the `nx.json` file, where you could set `appDir` and `libDir` options to customize the names of these directories.
We also simplified the definition of Nx projects to be any directory that had a `project.json` file in it, allowing for the ability to nest projects in your filesytem and also forego app or lib directories altogether!
With Nx 16.8, were introducing an all-new option in this `workspaceLayout` category: `projectNameAndRootFormat` where you can chose either the option to apply project names `as-provided` or `derived`.
![](/blog/images/2023-09-06/0*U5gxfZXk8pwgOXCE.avif)
If you dont set this option in your `nx.json` file, our generators will now prompt you as to how we should set:
- the name of your project (as in the projects `project.json` file)
- where to put the project in your filesystem
![](/blog/images/2023-09-06/0*eBwA23cwcMv8V5zF.avif)
You can avoid the extra prompt above by setting the `projectNameAndRootFormat` in the `workspaceLayout` category of your `nx.json` file, or by providing it in in your generate command:
```
> nx g app my-app --projectNameAndRootFormat=as-provided
```
This will change some of the default behaviors of our generators and for new Nx workspaces. By default, new workspaces will be set to `as-provided`, so longtime Nx users might notice that if they create a new workspace and start generating apps or libs, that they will now get generated at the root of the workspace instead of inside the `apps/` or `libs/` directory like they used to.
To get the legacy behavior, be sure to change the `projectNameAndRootFormat` to `derived` and/or use the `name` option to set the name of the project, and the `directory` option to set the full path of the target directory for your new projects:
```
> nx g app --name=my-app --directory=apps/my-app
```
## Packaging TypeScript Libraries — Secondary Entrypoints, ESM, CJS
{% youtube src="https://youtu.be/Vy4d0-SF5cY" /%}
Nx has always had first-class TypeScript support from the very beginning. You never really had to worry about Type Definition files being properly included or setting up TS support in the first place. But there are some aspects that can be tricky, like defining and properly exporting secondary entry points or packaging in multiple formats (ESM and CJS). Thats why we did some research to help make it easier.
The `package.json` format supports an [export field](https://nodejs.org/api/packages.html#package-entry-points) which is a modern alternative to the `main` property, allowing to have multiple such entry points.
```json
{
"exports": {
"./package.json": "./package.json",
".": "./src/index.js",
"./foo": "./src/foo.js",
"./bar": "./src/bar.js"
}
}
```
To make it easier to maintain these, weve added two new options to the `@nx/js` package: `additionalEntryPoints` and `generateExportsField`. Here's an example:
```
// packages/my-awesome-lib/project.json
{
"name": "my-awesome-lib",
"targets": {
"build": {
"executor": "@nx/js:tsc",
...
"options": {
"main": "packages/my-awesome-lib/src/index.ts",
...
"additionalEntryPoints": ["packages/my-awesome-lib/src/foo.ts"],
"generateExportsField": true
},
},
...
}
}
```
When building the library, the `@nx/js:tsc` executor automatically adds the correct `exports` definition to the resulting `package.json`.
This makes it easy to maintain the `exports` field, something that becomes even more relevant if we **want to add add multiple formats**. By switching to the `@nx/rollup:rollup` executor, we can also add the `format` option and define `esm` and `cjs` as the target formats we want to have. Note we still keep the `additionalEntryPoints` and `generateExportsField`.
```
// packages/my-awesome-lib/project.json
{
"name": "my-awesome-lib",
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
...
"options": {
"main": "packages/my-awesome-lib/src/index.ts",
...
"format": ["esm", "cjs"],
"additionalEntryPoints": ["packages/my-awesome-lib/src/foo.ts"],
"generateExportsField": true
},
},
...
}
}
```
After compiling our package using `nx build my-awesome-lib` we'll get the following output in our `dist` folder.
```
my-awesome-lib
└─ .
├─ README.md
├─ foo.cjs.d.ts
├─ foo.cjs.js
├─ foo.esm.js
├─ index.cjs.d.ts
├─ index.cjs.js
├─ index.esm.js
├─ package.json
└─ src
├─ foo.d.ts
├─ index.d.ts
└─ lib
└─ my-awesome-lib.d.ts
```
And our `package.json` will look as follows:
```json
{
"name": "my-awesome-lib",
"version": "0.0.1",
...
"type": "commonjs",
"main": "./index.cjs.js",
"typings": "./src/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": "./index.esm.js",
"default": "./index.cjs.js"
},
"./foo": {
"import": "./foo.esm.js",
"default": "./foo.cjs.js"
}
},
"module": "./index.esm.js"
}
```
## High Performance TypeScript Compilation: Introducing Batch Mode & Rust-based Dependency Resolution
Speed is in our DNA! And TypeScript compilation can be slow which is mostly due to `tsc` being a costly operation. You feel this in particular in a monorepo where you have multiple projects that are being compiled independently, thus launching dozens of processes of the `tsc` compiler.
To help with this, the TypeScript team introduced [Project References](https://www.typescriptlang.org/getting-started/intro/handbook/project-references.html) which performs incremental compilation by caching intermediate results. However this comes with some [caveats you need to be aware of](https://www.typescriptlang.org/getting-started/intro/handbook/project-references.html#caveats-for-project-references) and it can be intense to maintain by hand on a large codebase.
We wanted to make it transparent though and not something the user needs to worry about. Thats why we introduced [“Batch Mode”](/showcase/benchmarks/tsc-batch-mode). Batch mode is still experimental, and you can enable it for any project using the `@nx/js:tsc` executor by adding the environment variable `NX_BATCH_MODE=true`:
```
> NX_BATCH_MODE=true nx run-many --target=build
```
When enabling batch mode, Nx leverages the underlying [project graph](/features/explore-graph) to generate TypeScript project references behind the scenes for you, to fully leverage TS incremental building. The results are amazing. According to [our benchmarks](https://github.com/nrwl/large-ts-monorepo), batch mode has the potential to speed up Typescript compilation by up to 5x for large monorepos.
![](/blog/images/2023-09-06/0*givRGKA05v55ICoC.avif)
In addition to batch mode, the processing of Typescript dependencies is **now using a faster and more accurate Rust implementation**. This should be transparent to most users — aside from your monorepo becoming even faster!
## NEW Nx PLUGIN: Playwright
A new Nx plugin has appeared!!
![](/blog/images/2023-09-06/0*QBwv5NKpT9tp2-8E.avif)
Nx now supports Playwright as an e2e option alongside our long-standing support for Cypress!
First off, this means weve added Playwright as an option when generating new frontend applications:
![](/blog/images/2023-09-06/0*kvqmp9n2pkivb8ba.avif)
If you want to add playwright to an existing project in your workspace you can also do that now by installing the plugin (here using `npm`):
```
npm add -D @nx/playwright
```
Then running our new generator to add playwright to your project (here Im adding it to my application called `my-app`):
```
nx g @nx/playwright:configuration --project=my-app
```
This will setup playwright for you, and add an `e2e` target to your project using playwright!
## NEW INTEGRATION: Netlifys Improved Monorepo Experience
On Netlifys enterprise tier, approximately 46% of builds are monorepos, with the majority leveraging Nx and [Lerna](https://lerna.js.org/). Recognizing this trend, Netlify has focused on enhancing the setup and deployment experiences for monorepo projects. In particular they worked on an “automatic monorepo detection” feature. When you connect your project to GitHub, Netlify automatically detects if its part of a monorepo, reads the relevant settings, and pre-configures your project. This eliminates the need for manual setup. This feature also extends to local development via the Netlify CLI.
[Juri Strumpflohner](https://twitter.com/juristr) from the Nx team sits down with [Lukas Holzer](https://twitter.com/luka5c0m) from Netlify to discuss what monorepos are, when you might need them, their challenges and benefits, and the tooling support Nx provides. But its not just talk; they also walk you through setting up a new Nx monorepo, adding Netlify Edge functions, and deploying it all to Netlify — both via the website and locally through the newly improved Netlify CLI.
{% youtube src="https://youtu.be/KL7PCwf-mtM" /%}
If you prefer the blog post, check out [“Elevating enterprise deployment: Introducing an enhanced monorepo experience on Netlify”](https://www.netlify.com/blog/elevating-enterprise-deployment-introducing-an-enhanced-monorepo-experience-on-netlify/) on the Netlify blog.
## NEW Nx CONSOLE FEATURE: Interactive Graph Functionality
If youre not familiar — Nx Console is our IDE enhancement for [VsCode (1.4 million installations!!)](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) and [JetBrains Products (Intellij/WebStorm/etc — 52 thousand downloads!)](https://plugins.jetbrains.com/plugin/21060-nx-console).
Nx Console provides a Graphical User Interface for running tasks and generating code for your Nx Monorepos, and it also provides the ability to view your project graph
![](/blog/images/2023-09-06/0*uPA0E0HseySqzwPu.avif)
and task graph
![](/blog/images/2023-09-06/0*r3d7xr7yI1CPERKg.avif)
within your IDE!
As of our latest release, Nx Console has added the new feature of adding buttons inside the project graph to take you directly to the selected project in the project graph:
![](/blog/images/2023-09-06/0*NZdpBJ59gO-HdsV5.avif)
And gives you a “play button” to run any task within your task graph:
![](/blog/images/2023-09-06/0*AEht-0Pq7rdr-Uso.avif)
## ENHANCEMENT: Storybook Support for Interaction Testing
Storybook 7 introduces new [Interaction Testing](https://storybook.js.org/getting-started/intro/react/writing-tests/interaction-testing) to their platform!
![](/blog/images/2023-09-06/0*b7d1uLylXFjA4lU1.avif)
The Nx Storybook plugin has now been enhanced with a new `interactionTests` option on the `storybook-configuration` generator, that will automate setting up these interaction tests for you when you use Nx to generate stories for your components!
You can checkout everything about Storybook Interaction tests and our Nx support for it in this video:
{% youtube src="https://youtu.be/SaHoUx-TUs8" /%}
Nx has always provided similar functionality via our Storybook + Cypress integrations, where you can setup cypress tests to test your storybook showcases, and while you can use interaction testing to replace this integration, we will continue to support our Storybook + Cypress integrations going forward!
## NEW GENERATOR: convert-to-monorepo
Towards the start of the year, we added support for Nx standalone applications. These were designed as a way of using Nx features in a way where you didnt need to opt into a monorepo setup.
Ever since we introduced these, weve had requests from the community to add a generator to convert your standalone workspace to a monorepo setup — to support repos that grew to emcompass more than just the 1 application.
This is where our new [`convert-to-monorepo` generator](/nx-api/workspace/generators/convert-to-monorepo) comes into play!
```shell
nx g convert-to-monorepo
```
This will identify all library projects in currently in your repo and place them in the `libs/` directory that you might expect of a typical Nx monorepo. It will also hoist your application project from the root of your workspace into the `apps/` directory.
When all is said and done, you should be able to now add additional applications to your repo now!
## DOCS ENHANCEMENT: Third-Party Plugin Quality Indicators
One of the great things about Nx is the extensibility, and the wide range of plugins that are available for supporting languages, frameworks, and tools that the core Nx team does not directly support.
Our docs site has hosted [a registry of these plugins](/plugin-registry) for awhile now, but weve recently added npm downloads, github stars, release dates, and compatible Nx versions to this registry:
![](/blog/images/2023-09-06/0*f74VOjpr7u9RTmDE.avif)
We expect that these will be valuable signals to users as to the quality of the plugin.
Weve also added the ability to sort the registry by these metrics as a way of surfacing the higher quality plugins to the top!
![](/blog/images/2023-09-06/0*f0AhdlWaIcC96LXK.avif)
Go [check it out now](/plugin-registry) live on our docs site!
## DOCS ENHANCEMENT: Redesigned Intro & Examples
Our mission to improve Nx docs continues: this edition with some major updates to our [Docs intro page](/getting-started/intro).
We improved the messaging around Nx and more prominently emphasizing the [core features](/features) that distinguish Nx from other tools out there. We also linked a new “What is Nx” video. You should check it out 🐐
{% youtube src="https://youtu.be/-_4WMl-Fn0w" /%}
The core part of the intro page now has a dedicated section for “Learning Nx”, surfacing some of our Nx, Nx Cloud and Monorepo videos as well as our in-depth tutorial about monorepos and single-project Nx workspaces. And we already have more in the works, so stay tuned.
![](/blog/images/2023-09-06/0*VwG57cMDy9fGGI8l.avif)
Were also proud of all the new examples weve added in the last months. We have a brand new [Nx Recipe](https://github.com/nrwl/nx-recipes) repo with a variety of example projects that showcase Nx in combination with different technologies, even outside the JS ecosystem (e.g. with Rust, Go and .Net).
Go pick the ones youre most interested in!
![](/blog/images/2023-09-06/0*pMTW9GzZjRNrlyRH.avif)
You can find all of the examples and more on our “Showcase” section: [/showcase](/showcase).
## NEW GENERATOR: ESLint Flat Config
ESLint has announced a new config system — nicknamed “flat config” — whose intent is to be be familiar and much simpler than the current config system. You can read more about this [in their blog post](https://eslint.org/blog/2022/08/new-config-system-part-2/).
As part of our continued support for ESLint, weve introduced [a new generator](/nx-api/eslint/generators/convert-to-flat-config) to convert your Nx monorepo to this new system:
```
> nx g convert-to-flat-config
```
Flat config is still experimental, so you can use this as a way of easily previewing the new config system now. Just be sure not to mix the original configuration with this new configuration system!
## New Nx Cloud Overview Video
Weve been working hard on our premium product: Nx Cloud, and part of that has been this awesome video from our own Rares Matei on what exactly Nx Cloud is!
{% youtube src="https://youtu.be/NZF0ZJpgaJM" /%}
Be sure to checkout the [Nx Cloud landing site](/nx-cloud) for more details on all the additional features you unlock with the power of the cloud!
## Nx Conf Coming Up
Last but definitely not least, [Nx Conf 2023](/conf) is fast approaching! Well be coming to you live from New York City on September 26!
Be sure to [register to attend online FOR FREE](https://ti.to/nx-conf/nxconf2023online) and be sure to checkout our [lineup of talks](/conf#speakers) and [speakers](/conf#agenda)!
## Wrap Up
Thats all for now folks! Were just starting up a new iteration of development on Nx, so be sure to subscribe to our YouTube channel to get updates when new features land! Until next time, KEEP WORKING HARD!
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🥚 [Free Egghead course](https://egghead.io/courses/scale-react-development-with-nx-4038)
- 🚀 [Speed up your CI](/nx-cloud)
## More Nx Release Notes:
- [Nx 16.5](/blog/nx-16-5-release)
- [Nx 16.0](/blog/nx-16-is-here)
- [Nx 15.8](/blog/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook)
- [Nx 15.7](/blog/nx-15-7-node-support-angular-lts-lockfile-pruning)
- [Nx 15.4](/blog/nx-15-4-vite-4-support-a-new-nx-watch-command-and-more)
- [Nx 15.3](/blog/nx-15-3-standalone-projects-vite-task-graph-and-more)

View File

@ -0,0 +1,310 @@
---
title: 'Introducing Playwright Support for Nx'
slug: 'introducing-playwright-support-for-nx'
authors: ['Emily Xiong']
cover_image: '/blog/images/2023-09-18/1*_589bVpPTJ4D4IACBePXWQ.png'
tags: [nx, release, tutorial]
---
We are very excited to announce our support for Playwright with our new plugin `@nx/playwright`.
This blog will show you:
- What is Playwright
- How to create a new Nx workspace with Playwright support
- How to add Playwright to an existing Nx workspace
{% youtube src="https://youtu.be/k1U3PuBrZFQ?si=AVyXfyMJz4q6OJ70" /%}
## What is Playwright?
Before we start, lets answer this question: what is Playwright and why should we use it?
From [playwright.dev](https://playwright.dev/), it says: “Playwright is end-to-end testing for modern web apps”. It sounds good, what does it do for us developers? What developer experience does it provide?
### Multiple Browsers
It is easy to run e2e test suites across multiple browsers. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. It also supports branded browsers and mobile viewports. For example, we can simply add the below code to the playwright configuration file to run the same test across these browsers:
```
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
/* Test against desktop browsers */
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
/* Test against mobile viewports. */
{
name: 'Mobile Chrome',
use: { ...devices['Pixel 5'] },
},
/* Test against branded browsers. */
{
name: 'Google Chrome',
use: { ...devices['Desktop Chrome'], channel: 'chrome' }, // or 'chrome-beta'
},
],
});
```
### Auto Waiting
Playwright automatically waits for the relevant checks to pass, then performs the request action. What does it mean? For example, lets say we have a sign-up form where:
- while the app checks that the user name is unique, the submit button is disabled.
- after checking with the server, the submit button becomes enabled.
How do we write tests in the Playwright? Playwright performs a range of actionability checks on the elements before making actions to ensure these actions behave as expected. So we dont need to wait for the button to be enabled. Playwright will check it. We can simply write:
```
await page.getByTestId('submit-button').click();
```
### HTML Test Report
Playwright creates a nice HTML test report that allows filtering tests by browsers, passed tests, failed tests, skipped tests, and flaky tests.
![](/blog/images/2023-09-18/1*28KM1laCSbq9OwLYFaq8BQ.avif)
_HTML Test Report_
Clicking on the individual test shows more detailed errors along with each step of the test:
![](/blog/images/2023-09-18/1*slGx_vh9CQAD3er6XaNsjw.avif)
_Test error_
It also has other features like recording [screenshots](https://playwright.dev/docs/screenshots) and [videos](https://playwright.dev/docs/videos), [test generation](https://playwright.dev/docs/codegen), and [visual comparisons](https://playwright.dev/docs/test-snapshots). Read more about Playwright at [https://playwright.dev](https://playwright.dev/)
Next, lets write and run some Playwright tests.
## Create a new Nx Workspace with Playwright
In this example, we will create a React app using Playwright as its end-to-end testing framework. In the terminal, run the below command:
```shell
npx create-nx-workspace
✔ Where would you like to create your workspace? · nx-react-playwright
✔ Which stack do you want to use? · react
✔ What framework would you like to use? · none
✔ Integrated monorepo, or standalone project? · standalone
✔ Which bundler would you like to use? · vite
✔ Test runner to use for end to end (E2E) tests · playwright
✔ Default stylesheet format · css
✔ Enable distributed caching to make your CI faster · No
```
We get a standalone Nx React app named `nx-react-playwright`:
![](/blog/images/2023-09-18/1*-czlvgB1lLaIHb9uuRj9Ig.avif)
_nx repo created_
What is a [standalone application](/deprecated/integrated-vs-package-based)? It is like an integrated monorepo setup but with just a single, root-level application. The repo has the same file structure as an app created from Create-React-App, but we can still leverage all the generators and executors and structure your application into libraries or submodules.
### Run E2E
The default e2e test is located in `e2e/src/example.spec.ts`:
```
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('/');
// Expect h1 to contain a substring.
expect(await page.locator('h1').innerText()).toContain('Welcome');
});
```
The test verifies the `h1` header contains the text `Welcome`:
![](/blog/images/2023-09-18/1*ehJZTRfHfFF6hmSh3eJ-qA.avif)
_Page served up_
To run the e2e tests, run the below command:
```shell
npx nx e2e e2e
```
In the terminal, it shows the following log:
```shell
nx run nx-react-playwright:serve:development
➜ Local: http://localhost:4200/
3 passed (11.8s)
To open last HTML report run:
npx playwright show-report dist/.playwright/e2e/playwright-report
```
So the test passed and it also generated a report at `dist/.playwright/e2e/playwright-report/index.html`:
![](/blog/images/2023-09-18/1*xWKkHUozvDtk0Q9ihjDZbw.avif)
### Add Another Test
Let's add another test to check the Documentation button works:
![](/blog/images/2023-09-18/1*yTeWAR-3vE6Vdb6Cc6C5RA.avif)
_Documentation_
In `src/app/nx-welcome.tsx`, we need to add a test id to the link:
```
<a
href="/getting-started/intro?utm_source=nx-project"
target="_blank"
rel="noreferrer"
className="list-item-link"
data-testid="documentation-link"
>
```
Then in `e2e/src/example.spec.ts`, the test file will become:
```
import { test, expect } from '@playwright/test';
test.describe('navigation', () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto('/');
});
test('has title', async ({ page }) => {
// Expect h1 to contain a substring.
expect(await page.locator('h1').innerText()).toContain('Welcome');
});
test('should go to documentation site', async ({ page, context }) => {
await page.getByTestId('documentation-link').click();
// Opening a new tab and waiting for the page to render
const pagePromise = context.waitForEvent('page');
const newPage = await pagePromise;
await newPage.waitForLoadState();
expect(await newPage.title()).toContain('Intro to Nx');
});
});
```
Now run `npx nx e2e e2e`, the test would still pass:
```shell
nx run nx-react-playwright:serve:development
➜ Local: http://localhost:4200/
6 passed (3.1s)
To open last HTML report run:
npx playwright show-report dist/.playwright/e2e/playwright-report
```
Now we have created a new Nx workspace with Playwright. However, if you already have an Nx repo, how do you add Playwright E2E configuration to an existing app?
## How to add Playwright to an existing Nx workspace
For this example, I am going to add Playwright e2e tests to this repo: [nrwl/nx-examples](https://github.com/nrwl/nx-examples)
We are going to focus on the cart app in this example. In the terminal, run `npx nx serve cart` and it should serve up the app at [http://localhost:4200/cart](http://localhost:4200/cart).
![](/blog/images/2023-09-18/1*F8KLtNUJvKtsZtUSU13vgQ.avif)
_Cart App_
### Install @nx/playwright
To install, run:
```shell
#npm
npm install @nx/playwright --save-dev
#yarn
yarn add @nx/playwright --dev
#pnpm
pnpm i -D @nx/playwright
```
### Apply Playwright Configuration
There are 2 ways to apply the E2E Playwright configuration.
1. **Apply directly on the cart app**
We can set up Playwright directly on the cart app:
```shell
npx nx generate @nx/playwright:configuration --project=cart ---webServerCommand="npx nx serve cart" --webServerAddress="http://localhost:4200"
```
It adds:
- an e2e target in `apps/cart/project.json`
- an e2e folder at `apps/cart/e2e` containing e2e tests
- `playwright.config.ts` containing Playwright configuration
![](/blog/images/2023-09-18/1*IEwONcILNaIYHmjTyhF3Bw.avif)
_new cart folder_
Let's update the default test `apps/cart/e2e/example.spec.ts` to check whether the header exists:
```
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('/cart');
await expect(page.locator('nx-example-header')).toBeVisible()
});
```
Now we can run `npx nx e2e cart` and it should pass.
**2\. Add a separate E2E Project**
The second way is to create a separate E2E project folder and apply configuration there.
Create a folder e2e at the workspace root and a project.json file inside it:
![](/blog/images/2023-09-18/1*nF2bZhQb1CZ4Kc8btsxzRw.avif)
Add name in `e2e/project.json`:
```json
{
"name": "e2e"
}
```
Now apply the Playwright configuration to the e2e project:
```shell
npx nx generate @nx/playwright:configuration --project=e2e ---webServerCommand="npx nx serve cart" --webServerAddress="http://localhost:4200"
```
Now I created an e2e folder at the workspace root:
![](/blog/images/2023-09-18/1*nZXrAKzg4krYx6fouDefpw.avif)
_e2e folder_
Now we can run `npx nx e2e e2e` to run the Playwright e2e tests.
## Summary
In this blog, we have:
- Created a new Nx react repo with Playwright
- Written our own Playwright tests
- Used Nx to run Playwright tests
- Set up a Playwright configuration for an existing Nx app
Hopefully, this gives you good insight into how to get started with Playwright. The Playwright configuration in this example is pretty simple, to learn more about `@nx/playwright` plugin, check out the Nx documentation: [/nx-api/playwright](/nx-api/playwright).
## Learn more
- 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](/nx-cloud)

View File

@ -7,7 +7,7 @@ tags: [nx]
Victor and I are excited to announce that Nx has raised another $16M in a Series A funding round with Nexus Venture Partners and a16z! See our announcement video for more, and be sure to check out the [live stream of Nx Conf 2023](https://youtube.com/live/IQ5YyEYZw68?feature=share) tomorrow to see what were up to! Victor and I are excited to announce that Nx has raised another $16M in a Series A funding round with Nexus Venture Partners and a16z! See our announcement video for more, and be sure to check out the [live stream of Nx Conf 2023](https://youtube.com/live/IQ5YyEYZw68?feature=share) tomorrow to see what were up to!
{% youtube src="https://www.youtube.com/embed/KuyYhC4ClW8?si=qoZL6i6X1E7wjChD" %} {% youtube src="https://www.youtube.com/embed/KuyYhC4ClW8?si=qoZL6i6X1E7wjChD" /%}
--- ---

View File

@ -205,10 +205,6 @@ An interesting part is also how they perform the repository synching (from polyr
- has rules to run that produce actionable feedback about what is needed to sync/align the polyrepo repository s.t. it can be merged into the monorepo - has rules to run that produce actionable feedback about what is needed to sync/align the polyrepo repository s.t. it can be merged into the monorepo
- it also allows to track progress and produce according reporting of where the company is at - it also allows to track progress and produce according reporting of where the company is at
Sounds interesting? Watch the full talk below:
{% youtube src="https://www.youtube.com/watch?v=i0UdoImryJQ" /%}
## Redefining Projects with Nx: A Dive into the New Inference API ## Redefining Projects with Nx: A Dive into the New Inference API
**Speaker:** [Craigory Coppola](https://twitter.com/enderagent) **Speaker:** [Craigory Coppola](https://twitter.com/enderagent)

View File

@ -3,7 +3,7 @@ title: 'Nx 17 has Landed'
slug: 'nx-17-release' slug: 'nx-17-release'
authors: ['Juri Strumpflohner', 'Zack DeRose'] authors: ['Juri Strumpflohner', 'Zack DeRose']
cover_image: '/blog/images/2023-10-20/featured_img.png' cover_image: '/blog/images/2023-10-20/featured_img.png'
tags: [nx, design] tags: [nx, release]
--- ---
Were excited to announce the release of Nx version 17! Were excited to announce the release of Nx version 17!
@ -17,13 +17,15 @@ Heres a Table of Contents so you can skip straight to the updates you care ab
- [More Consistent Generator Paths](#more-consistent-generator-paths) - [More Consistent Generator Paths](#more-consistent-generator-paths)
- [The NEW Nx AI Chatbot](#the-new-nx-ai-chatbot) - [The NEW Nx AI Chatbot](#the-new-nx-ai-chatbot)
- [More Seamless Integration With Nx Cloud](#more-seamless-integration-with-nx-cloud) - [More Seamless Integration With Nx Cloud](#more-seamless-integration-with-nx-cloud)
- [`nx.json` Simplification](#simplification) - [`nx.json` Simplification](#nxjson-simplification)
- [Nx Repo Begins Dog-Fooding Nx Workflows](#nx-repo-dogfooding-nx-workflows) - [Nx Repo Begins Dog-Fooding Nx Workflows](#nx-repo-dogfooding-nx-workflows)
- [Task Graphing Improvements](#task-graphing-improvements) - [Task Graphing Improvements](#task-graphing-improvements)
- [`@nx/linter` Renames to `@nx/eslint`](#renamed-to) - [`@nx/linter` Renames to `@nx/eslint`](#renamed-to)
- [New Experimental Feature: Nx Release](#new-experimental-feature-nx-release) - [New Experimental Feature: Nx Release](#new-experimental-feature-nx-release)
- [Experimental: Nx Project Inference API v2](#experimental-nx-project-inference-api-v2) - [Experimental: Nx Project Inference API v2](#experimental-nx-project-inference-api-v2)
- [20k Github Stars!!](#20k-github-stars) - [20k Github Stars!!](#20k-github-stars)
- [How to update Nx](#how-to-update-nx)
- [Wrapping up](#wrapping-up)
**Prefer a video?** **Prefer a video?**
@ -42,7 +44,7 @@ The first place you might notice this new support is in the `create-nx-workspace
This option will create a new Nx workspace with a fresh Vue application, all set up and ready to develop! To add new Vue projects to your existing Nx workspaces, add our new @nx/vue package as a dev dependency to your workspace, e.g.: This option will create a new Nx workspace with a fresh Vue application, all set up and ready to develop! To add new Vue projects to your existing Nx workspaces, add our new @nx/vue package as a dev dependency to your workspace, e.g.:
```shell ```shell
> npm add -D @nx/vue npm add -D @nx/vue
``` ```
And youll have access to Nx generators so that you can generate Vue applications, libraries, components, and more in your workspace: And youll have access to Nx generators so that you can generate Vue applications, libraries, components, and more in your workspace:
@ -134,13 +136,13 @@ And a `Home.tsx` file will be added in the `apps/my-app/src/app` directory.
Finally, generators will now factory in your current working directory, so you can also create this “Home” component via: Finally, generators will now factory in your current working directory, so you can also create this “Home” component via:
```shell ```shell
> cd apps/my-app/src/app cd apps/my-app/src/app
> nx g component Home nx g component Home
``` ```
## The NEW Nx AI ChatBot ## The NEW Nx AI ChatBot
Weve added a new AI ChatBot to our docs site. You can access it now at [https://nx.dev/ai-chat](/ai-chat). Weve added a new AI ChatBot to our docs site. You can access it now at [/ai-chat](/ai-chat).
![](/blog/images/2023-10-20/bodyimg4.gif) ![](/blog/images/2023-10-20/bodyimg4.gif)
@ -200,7 +202,7 @@ There have been some difficulties in determining precisely which files were incl
You can open this graph using the command: You can open this graph using the command:
```shell ```shell
> nx graph nx graph
``` ```
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: 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:
@ -240,7 +242,7 @@ Interestingly, v2 includes support for dynamic targets as well. This opens up ex
For most developers, the main thing you need to know is that plugins may now add additional targets that you wont see in your `project.json` file. To see your actual project configuration, you can now use the command: For most developers, the main thing you need to know is that plugins may now add additional targets that you wont see in your `project.json` file. To see your actual project configuration, you can now use the command:
```shell ```shell
> nx show project <project_name> nx show project <project_name>
``` ```
For plugin authors, check out the [v2 documentation](/extending-nx/recipes/project-graph-plugins) to see how you can take advantage of the new API to deliver a better experience to your users. For plugin authors, check out the [v2 documentation](/extending-nx/recipes/project-graph-plugins) to see how you can take advantage of the new API to deliver a better experience to your users.
@ -256,13 +258,13 @@ Nx is SOOO CLOSE to 20,000 stars on github! If Nx has been helpful to you, [plea
Nx is known to [help you automatically migrate](/features/automate-updating-dependencies) to the new version (including potentially breaking changes). To update simply run: Nx is known to [help you automatically migrate](/features/automate-updating-dependencies) to the new version (including potentially breaking changes). To update simply run:
```shell ```shell
> npx nx migrate latest npx nx migrate latest
``` ```
This will update your Nx workspace dependencies, configuration and code to the latest version. After updating your dependencies, run any necessary migrations: This will update your Nx workspace dependencies, configuration and code to the latest version. After updating your dependencies, run any necessary migrations:
```shell ```shell
> npx nx migrate --run-migrations npx nx migrate --run-migrations
``` ```
## Wrapping up ## Wrapping up

View File

@ -2,7 +2,7 @@
title: State Management Nx React Native/Expo Apps with TanStack Query and Redux title: State Management Nx React Native/Expo Apps with TanStack Query and Redux
slug: 'state-management-nx-react-native-expo-apps-with-tanstack-query-and-redux' slug: 'state-management-nx-react-native-expo-apps-with-tanstack-query-and-redux'
authors: [Emily Xiong] authors: [Emily Xiong]
image: '/blog/images/2023-11-08/featured_img.webp' cover_image: '/blog/images/2023-11-08/featured_img.webp'
tags: [nx, React Native] tags: [nx, React Native]
--- ---
@ -96,7 +96,7 @@ If you open my Expo app on the web by running `nx start cats` and choose the opt
![](/blog/images/2023-11-08/bodyimg2.webp) ![](/blog/images/2023-11-08/bodyimg2.webp)
Or you can run npx nx serve cats to launch the app in a web browser and debug from there. Or you can run `npx nx serve cats` to launch the app in a web browser and debug from there.
### Create a Query ### Create a Query
@ -160,7 +160,7 @@ Invalid hook call. Hooks can only be called inside of the body of a function com
To solve this, you need to wrap your component inside the renderHook function from `@testing-library/react-native` library: To solve this, you need to wrap your component inside the renderHook function from `@testing-library/react-native` library:
1. **Install Library to Mock Fetch** **1\. Install Library to Mock Fetch**
Depending on which library you use to make HTTP requests. (e.g. fetch, axios), you need to install a library to mock the response. Depending on which library you use to make HTTP requests. (e.g. fetch, axios), you need to install a library to mock the response.
@ -185,7 +185,7 @@ import fetchMock from 'jest-fetch-mock';
fetchMock.enableMocks(); fetchMock.enableMocks();
``` ```
2. **Create Mock Query Provider** **2\. Create Mock Query Provider**
In order to test out `useQuery` hook, you need to wrap it inside a mock `QueryClientProvider`. Since this mock query provider is going to be used more than once, lets create a library for this wrapper: In order to test out `useQuery` hook, you need to wrap it inside a mock `QueryClientProvider`. Since this mock query provider is going to be used more than once, lets create a library for this wrapper:
@ -227,7 +227,7 @@ export function TestWrapper({ children }: TestWrapperProps) {
export default TestWrapper; export default TestWrapper;
``` ```
3. **Use Mock Responses in Unit Test** **3\. Use Mock Responses in Unit Test**
Then this is what the unit test for my query would look like: Then this is what the unit test for my query would look like:
@ -516,8 +516,104 @@ This state has 3 actions:
Then you have to add the root store and create a transform function to stringify the redux state: Then you have to add the root store and create a transform function to stringify the redux state:
```html ```typescript {% fileName="persist-transform.ts" %}
<script src="https://gist.github.com/xiongemi/5f364d84f89b647dcaaf7e5437ea789c.js"></script> import { EntityState } from '@reduxjs/toolkit';
import { createTransform } from 'redux-persist';
import { LIKES_FEATURE_KEY } from '../likes/likes.slice';
const transformEntityStateToPersist = createTransform(
// transform state on its way to being serialized and persisted.
(
entityState: EntityState<any>
): {
ids: string;
entities: any;
} => {
return {
...entityState,
ids: JSON.stringify(entityState.ids),
entities: JSON.stringify(entityState.entities),
};
},
// transform state being rehydrated
(entityState: { ids: string; entities: string }): EntityState<any> => {
return {
...entityState,
ids: JSON.parse(entityState.ids),
entities: JSON.parse(entityState.entities),
};
},
// define which reducers this transform gets called for.
{ whitelist: [LIKES_FEATURE_KEY] }
);
export { transformEntityStateToPersist };
```
```typescript {% fileName="root-state.initial.ts" %}
import { initialLikesState } from '../likes/likes.slice';
import { RootState } from './root-state.interface';
export const initialRootState: RootState = {
likes: initialLikesState,
};
```
```typescript {% fileName="root-state.interface.ts" %}
import { LikesState } from '../likes/likes.slice';
export interface RootState {
likes: LikesState;
}
```
```typescript {% fileName="root-reducer.ts" %}
import { combineReducers } from '@reduxjs/toolkit';
import { likesReducer } from '../likes/likes.slice';
import { RootState } from './root-state.interface';
export const createRootReducer = combineReducers<RootState>({
likes: likesReducer,
});
```
```typescript {% fileName="root.store.ts" %}
import { configureStore } from '@reduxjs/toolkit';
import logger from 'redux-logger';
import { persistStore, persistReducer, PersistConfig } from 'redux-persist';
import { initialRootState } from './root-state.initial';
import { RootState } from './root-state.interface';
import { createRootReducer } from './root.reducer';
declare const process: any;
export const createRootStore = (persistConfig: PersistConfig<RootState>) => {
const isDevelopment = process.env.NODE_ENV === 'development';
const rootReducer = createRootReducer;
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) => {
const defaultMiddleware = getDefaultMiddleware({
serializableCheck: false,
});
return isDevelopment
? defaultMiddleware.concat(logger)
: defaultMiddleware;
},
devTools: isDevelopment,
preloadedState: initialRootState,
});
const persistor = persistStore(store);
return { store, persistor };
};
``` ```
### Connect Redux State with UI ### Connect Redux State with UI

View File

@ -3,10 +3,10 @@ title: Unit Testing Expo Apps With Jest
slug: 'unit-testing-expo-apps-with-jest' slug: 'unit-testing-expo-apps-with-jest'
authors: [Emily Xiong] authors: [Emily Xiong]
cover_image: '/blog/images/2023-11-22/featured_img.webp' cover_image: '/blog/images/2023-11-22/featured_img.webp'
tags: [nx, unit testing] tags: [nx, tutorial]
--- ---
In my latest [blog](https://dev.to/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17), I successfully navigated through the steps of setting up an Expo Monorepo with [Nx](). The next challenge? Testing! This blog dives into: In my latest [blog](/blog/step-by-step-guide-to-creating-an-expo-monorepo-with-nx), I successfully navigated through the steps of setting up an Expo Monorepo with [Nx](). The next challenge? Testing! This blog dives into:
- Crafting effective unit tests for Expo components utilizing Jest - Crafting effective unit tests for Expo components utilizing Jest
- Addressing common issues encountered during unit testing - Addressing common issues encountered during unit testing
@ -69,20 +69,20 @@ You can find more options for querying elements on the official React Native Tes
However, unit tests do not always pass. Here are some common errors I ran into and how to resolve them. However, unit tests do not always pass. Here are some common errors I ran into and how to resolve them.
### **Error: AsyncStorage is null.** ### Error: AsyncStorage is null.
I am using the library `@react-native-async-storage/async-storage`, and I got the below error when running unit testing: I am using the library `@react-native-async-storage/async-storage`, and I got the below error when running unit testing:
```shell ```shell
\[@RNC/AsyncStorage\]: NativeModule: AsyncStorage is null. [@RNC/AsyncStorage]: NativeModule: AsyncStorage is null.
To fix this issue try these steps: To fix this issue try these steps:
• Rebuild and restart the app. • Rebuild and restart the app.
• Run the packager with \`--reset-cache\` flag. • 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 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 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
@ -136,14 +136,14 @@ Then I can create a mock store using this library like the below code:
```typescript ```typescript
import configureStore, { MockStoreEnhanced } from 'redux-mock-store'; import configureStore, { MockStoreEnhanced } from 'redux-mock-store';
const mockStore = configureStore<any>(\[\]); const mockStore = configureStore<any>([]);
let store: MockStoreEnhanced<any>; let store: MockStoreEnhanced<any>;
beforeEach(() => { beforeEach(() => {
store = mockStore({}); store = mockStore({});
store.dispatch = jest.fn(); store.dispatch = jest.fn();
}); });
``` ```
For example, one of my stateful components unit test will become: For example, one of my stateful components unit test will become:
@ -158,7 +158,7 @@ import { RootState, initialRootState } from '@nx-expo-monorepo/states/cat';
import Bookmarks from './bookmarks'; import Bookmarks from './bookmarks';
describe('Bookmarks', () => { describe('Bookmarks', () => {
const mockStore = configureStore<RootState>(\[\]); const mockStore = configureStore<RootState>([]);
let store: MockStoreEnhanced<RootState>; let store: MockStoreEnhanced<RootState>;
@ -236,11 +236,11 @@ jest.mock('@react-navigation/native', () => {
### SyntaxError: Unexpected token export ### SyntaxError: Unexpected token export
I got this error when using a library with ECMAScript Module (ESM), such as `[udid](https://github.com/uuidjs/uuid)`: I got this error when using a library with ECMAScript Module (ESM), such as [`udid`](https://github.com/uuidjs/uuid):
``` ```
/Users/emilyxiong/Code/nx-expo-monorepo/node\_modules/uuid/dist/esm-browser/index.js:1 /Users/emilyxiong/Code/nx-expo-monorepo/node_modules/uuid/dist/esm-browser/index.js:1
({"Object.<anonymous>":function(module,exports,require,\_\_dirname,\_\_filename,jest){export { default as v1 } from './v1.js'; ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
^^^^^^ ^^^^^^
SyntaxError: Unexpected token 'export' SyntaxError: Unexpected token 'export'
@ -286,12 +286,12 @@ I got this error when I was importing from a library such as [react-native-vecto
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration. 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. By default "node_modules" folder is ignored by transformers.
Here's what you can do: 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 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 • 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. • 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 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. • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
@ -310,9 +310,9 @@ By default, Jest will ignore all the files under node_modules and only transform
However, some libraries such as `react-native-paper` or `react-native-svg`, the library files are in `.ts` or `.tsx`. These files are not compiled to `js`. So I need to add these libraries' names to `transformIgnorePatterns`, so these libraries will be transformed by Babel along with my project. source file. The default generated `jest.config.js` already has: However, some libraries such as `react-native-paper` or `react-native-svg`, the library files are in `.ts` or `.tsx`. These files are not compiled to `js`. So I need to add these libraries' names to `transformIgnorePatterns`, so these libraries will be transformed by Babel along with my project. source file. The default generated `jest.config.js` already has:
``` ```
transformIgnorePatterns: \[ 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)', '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)',
\] ]
``` ```
If I have an error related to a library with an unexpected token, I need to check whether they are compiled or not. If I have an error related to a library with an unexpected token, I need to check whether they are compiled or not.
@ -328,9 +328,8 @@ With Nx, you do not need to explicitly install any testing library, so you can d
## Learn more ## Learn more
- [Add Cypress, Playwright, and Storybook to Nx Expo Apps](https://medium.com/@emilyxiong/add-cypress-playwright-and-storybook-to-nx-expo-apps-1d3e409ce834)
- 🧠 [Nx Docs](/getting-started/intro) - 🧠 [Nx Docs](/getting-started/intro)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx) - 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 💬 [Nx Community Discord](https://go.nx.dev/community) - 💬 [Nx Community Discord](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools) - 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- 🚀 [Speed up your CI](https://nx.app/) - 🚀 [Speed up your CI](/nx-cloud)

View File

@ -124,7 +124,7 @@ nx migrate --run-migrations
You can also use the `--interactive` flag if you want to migrate your workspace to the latest version of Nx while staying on your current version of Angular: You can also use the `--interactive` flag if you want to migrate your workspace to the latest version of Nx while staying on your current version of Angular:
```shell ```shell
> nx migrate latest --interactive nx migrate latest --interactive
✔ Do you want to update to TypeScript v5.2? (Y/n) · true ✔ 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 ✔ Do you want to update the Angular version to v17? (Y/n) · false

View File

@ -32,7 +32,7 @@ It is that time again: getting flooded by Year of Review blog posts. We did it l
## Top 10 Nx Highlights of 2023 ## Top 10 Nx Highlights of 2023
We shipped a ton of features in 2023. You can find all our release blog posts and release-related info here: [https://nx.dev/changelog](/changelog) or check out our [Dev.to collection](https://dev.to/nx). We shipped a ton of features in 2023. You can find all our release blog posts and release-related info here: [/changelog](/changelog).
We've picked out 10 highlights for you. We've picked out 10 highlights for you.
@ -40,7 +40,7 @@ We've picked out 10 highlights for you.
At Nx, weve heavily embraced Typescript from the beginning and weve been very happy with that decision. Nx also stands as the [fastest JS monorepo tool](https://github.com/vsavkin/large-monorepo) available, demonstrating that adopting TypeScript does not necessarily compromise speed. However, we dont 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. At Nx, weve heavily embraced Typescript from the beginning and weve been very happy with that decision. Nx also stands as the [fastest JS monorepo tool](https://github.com/vsavkin/large-monorepo) available, demonstrating that adopting TypeScript does not necessarily compromise speed. However, we dont 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.
Our initial focus was on [rewriting the task hasher](https://dev.to/nx/nx-158-rust-hasher-nx-console-for-intellij-deno-node-and-storybook-27ng#rustifying-the-nx-hasher), 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. Our initial focus was on [rewriting the task hasher](/blog/nx-15-8-rust-hasher-nx-console-for-intellij-deno-node-and-storybook), 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.
Following this, we revamped the TypeScript dependency resolution, observing an almost 5x speed increase with our Rust-based approach over the traditional TSC method. Following this, we revamped the TypeScript dependency resolution, observing an almost 5x speed increase with our Rust-based approach over the traditional TSC method.
@ -97,7 +97,7 @@ Nx Console has evolved from an experimental side project of the Nx team to a cor
This year we not only added a lot of new features to Nx Console, but also rewrote its [internals](/blog/nx-console-gets-lit) which paved the way to expand Nx Console to other code editors: **JetBrains IDEs.** This year we not only added a lot of new features to Nx Console, but also rewrote its [internals](/blog/nx-console-gets-lit) which paved the way to expand Nx Console to other code editors: **JetBrains IDEs.**
Yes, this means you can now use the latest Nx Console directly in your [Webstorm IDE](https://www.jetbrains.com/webstorm/). Read the [announcement blog post](https://blog.nrwl.io/expanding-nx-console-to-jetbrains-ides-8a5b80fff2d7) for all the details or go ahead and install Nx Console if you didnt already: Yes, this means you can now use the latest Nx Console directly in your [Webstorm IDE](https://www.jetbrains.com/webstorm/). Read the [announcement blog post](/blog/expanding-nx-console-to-jetbrains-ides) for all the details or go ahead and install Nx Console if you didnt already:
- [Nx Console for VSCode](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) - [Nx Console for VSCode](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)
- [Nx Console for IntelliJ](https://plugins.jetbrains.com/plugin/21060-nx-console) - [Nx Console for IntelliJ](https://plugins.jetbrains.com/plugin/21060-nx-console)
@ -116,7 +116,7 @@ Generally, Playwright fits in the Nx ecosystem as a tool that developers can use
```shell ```shell
$ npx create-nx-workspace@latest $ npx create-nx-workspace@latest
> NX Let's create a new workspace [https://nx.dev/getting-started/intro] > NX Let's create a new workspace [/getting-started/intro]
✔ Which stack do you want to use? · react ✔ Which stack do you want to use? · react
✔ What framework would you like to use? · none ✔ What framework would you like to use? · none
✔ Integrated monorepo, or standalone project? · integrated ✔ Integrated monorepo, or standalone project? · integrated
@ -144,7 +144,7 @@ TypeScript has won. It has become the prevalent way of writing modern JavaScript
} }
``` ```
So in [v16.8](https://blog.nrwl.io/nx-16-8-release-e38e3bb503b5#7b41) we added the ability to automatically have these generated for you by defining the `additionalEntryPoints` and `generateExportsField` when using the `@nx/js` plugin. So in [v16.8](/blog/nx-16-8-release) we added the ability to automatically have these generated for you by defining the `additionalEntryPoints` and `generateExportsField` when using the `@nx/js` plugin.
``` ```
// packages/my-awesome-lib/project.json // packages/my-awesome-lib/project.json
@ -261,7 +261,7 @@ Where in the example above your host application is named “host-application”
Throughout 2023, weve continued to increase Nxs support and general dev experience around Module Federation, including [adding a generator to federate an existing module](/recipes/module-federation/federate-a-module), improving the local developer experience by improving local webserver performance, and introducing the concept of [Dynamic Module Federation](/recipes/angular/dynamic-module-federation-with-angular#advanced-angular-micro-frontends-with-dynamic-module-federation) which will allow you to dynamically specify the location of your remote applications via a “module-federation.manifest.json” file! Throughout 2023, weve continued to increase Nxs support and general dev experience around Module Federation, including [adding a generator to federate an existing module](/recipes/module-federation/federate-a-module), improving the local developer experience by improving local webserver performance, and introducing the concept of [Dynamic Module Federation](/recipes/angular/dynamic-module-federation-with-angular#advanced-angular-micro-frontends-with-dynamic-module-federation) which will allow you to dynamically specify the location of your remote applications via a “module-federation.manifest.json” file!
At Nx, were excited about the Module Federation support we offer for our users, and think that it has many interesting applications when paired with Nxs CI capabilities, in particular allowing for [much shorter build times](/concepts/module-federation/faster-builds-with-module-federation#faster-builds-with-module-federation) especially for larger Angular applications. At Nx, were excited about the Module Federation support we offer for our users, and think that it has many interesting applications when paired with Nxs CI capabilities, in particular allowing for [much shorter build times](/concepts/module-federation/faster-builds-with-module-federation) especially for larger Angular applications.
## Many OSS repos adopt Nx ## Many OSS repos adopt Nx
@ -270,7 +270,7 @@ By simply installing the `nx` package (or initializing with `nx init` in any pro
- Advanced task scheduling, including task pipelines and parallel execution. - Advanced task scheduling, including task pipelines and parallel execution.
- Efficient caching mechanisms. - Efficient caching mechanisms.
> If you want to learn more about such setup, make sure to check out our blog post on [how to adopt Nx on a npm/yarn/pnpm workspace](https://dev.to/nx/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-1eem) or the corresponding [video version](https://www.youtube.com/watch?si=0XH6Sp025xM3Rru5&v=ngdoUQBvAjo&feature=youtu.be). > If you want to learn more about such setup, make sure to check out our blog post on [how to adopt Nx on a npm/yarn/pnpm workspace](/blog/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx) or the corresponding [video version](https://www.youtube.com/watch?si=0XH6Sp025xM3Rru5&v=ngdoUQBvAjo&feature=youtu.be).
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. 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.
@ -327,8 +327,6 @@ You can also browse them in the [nx-recipes](https://github.com/nrwl/nx-recipes)
{% tweet url="https://twitter.com/juristr/status/1736023402933318011" /%} {% tweet url="https://twitter.com/juristr/status/1736023402933318011" /%}
{% tweet url="https://twitter.com/juristr/status/1726977598218199302" /%}
And obviously, we jumped on the AI train as well. A couple of months ago, we added the [Nx Assistant](/ai-chat). A ChatGPT-powered interface trained on our docs. [Katerina](https://twitter.com/psybercity) wrote about it [on our blog](/blog/nx-docs-ai-assistant). The AI chat allows to interactively ask questions about Nx and will give you relevant answers from our docs (including linking to the sources). And obviously, we jumped on the AI train as well. A couple of months ago, we added the [Nx Assistant](/ai-chat). A ChatGPT-powered interface trained on our docs. [Katerina](https://twitter.com/psybercity) wrote about it [on our blog](/blog/nx-docs-ai-assistant). The AI chat allows to interactively ask questions about Nx and will give you relevant answers from our docs (including linking to the sources).
## New Tagline: Smart Monorepos — Fast CI ## New Tagline: Smart Monorepos — Fast CI
@ -337,11 +335,11 @@ Nx stands out for its flexibility, accommodating for both monorepo and non-monor
However, Nxs true strength becomes most apparent at scale, typically within a monorepo setup. We wanted to capture it in our new tagline: **Smart Monorepos — Fast CI**. However, Nxs true strength becomes most apparent at scale, typically within a monorepo setup. We wanted to capture it in our new tagline: **Smart Monorepos — Fast CI**.
{% twitter url="https://twitter.com/juristr/status/1734558895547568634" /%} {% tweet url="https://twitter.com/juristr/status/1734558895547568634" /%}
Setting up an efficient and maintainable CI process for monorepos can be a complex task, so weve 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. Were publicly launching [Nx Agents](/ci/features/distribute-task-execution) to add seamless distribution to your CI pipeline, and more are coming in 2024. Setting up an efficient and maintainable CI process for monorepos can be a complex task, so weve 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. Were publicly launching [Nx Agents](/ci/features/distribute-task-execution) to add seamless distribution to your CI pipeline, and more are coming in 2024.
As part of that, we also restructured our docs to have a section entirely dedicated to CI: [https://nx.dev/ci](/ci/intro/ci-with-nx). As part of that, we also restructured our docs to have a section entirely dedicated to CI: [/ci](/ci/intro/ci-with-nx).
## Nx Conf ## Nx Conf

View File

@ -43,7 +43,7 @@ You can add Nx to an existing npm/yarn/pnpm monorepo quite straightforwardly. Yo
npx nx@latest init npx nx@latest init
``` ```
Youll get an `nx` package installed and an `nx.json` allowing you to define [task dependencies](/recipes/running-tasks/defining-task-pipeline) and caching. With that, you're now able to run commands like `nx build <your project>` or nx `run-many -t build test` to run all `build` and `test` targets in your workspace in parallel. Nx will read and use your existing `package.json` scripts. I've written an in-depth [blog post about adopting Nx in such a scenario](https://dev.to/nx/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-1eem). Youll get an `nx` package installed and an `nx.json` allowing you to define [task dependencies](/recipes/running-tasks/defining-task-pipeline) and caching. With that, you're now able to run commands like `nx build <your project>` or nx `run-many -t build test` to run all `build` and `test` targets in your workspace in parallel. Nx will read and use your existing `package.json` scripts. I've written an in-depth [blog post about adopting Nx in such a scenario](/blog/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx).
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. 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.

View File

@ -178,13 +178,20 @@ and see the structure of your projects:
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. 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.
--- ## Nx Live With Nuxt Maintainer Daniel Roe
Dont miss Nx team members Zack and Katerina with Nuxts maintainer, Daniel Roe — live!
{% youtube src="https://www.youtube.com/watch?v=uHwUxFYX2DY" %}
## Learn more ## Learn more
Check out the [example repo](https://github.com/mandarini/my-nx-nuxt-workspace) used in this blog post or one of the links below to learn more:
- [Nx Docs](/getting-started/intro) - [Nx Docs](/getting-started/intro)
- [X / Twitter](https://twitter.com/nxdevtools) - [LinkedIn](https://www.linkedin.com/company/nrwl)
- [Nx GitHub](https://github.com/nrwl/nx) - [Nx GitHub](https://github.com/nrwl/nx)
- [Nx Community Discord](https://go.nx.dev/community) - [Nx Community Discord](https://go.nx.dev/community)
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools) - [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Speed up your CI](https://nx.app) - [Speed up your CI](/nx-cloud)
Also, if you liked this, make sure to follow [Katerina](https://twitter.com/psybercity) and [Nx](https://twitter.com/nxdevtools) on Twitter for more!

View File

@ -64,7 +64,7 @@ Zack explains Nuxt and how to use the new plugin in this video:
To add @nx/nuxt to your codebase, use the command: To add @nx/nuxt to your codebase, use the command:
```shell ```shell
> nx add @nx/nuxt nx add @nx/nuxt
``` ```
Huge thanks to [Katerina](https://twitter.com/psybercity) for her work on the plugin, and Nuxt maintainer, [Daniel Roe](https://twitter.com/danielcroe), for helping to guide the project! Huge thanks to [Katerina](https://twitter.com/psybercity) for her work on the plugin, and Nuxt maintainer, [Daniel Roe](https://twitter.com/danielcroe), for helping to guide the project!
@ -83,7 +83,7 @@ Were very excited about Nx Agents because we think that in its current state,
Be sure to also checkout the [blog post from Isaac on Nx Agents](/blog/fast-effortless-ci), including explanations of exclusive features like auto-detection and retrying for flaky tasks and automatically splitting lengthy end-to-end tests! Be sure to also checkout the [blog post from Isaac on Nx Agents](/blog/fast-effortless-ci), including explanations of exclusive features like auto-detection and retrying for flaky tasks and automatically splitting lengthy end-to-end tests!
You can [signup for Nx Agents NOW](https://nx.app/products/agents#content), and find out [more of the details in our docs](/ci/features/distribute-task-execution)! You can find out [more of the details in our docs](/ci/features/distribute-task-execution)!
Rares and Altan are on the team building Nx Cloud, and during the conference, they dove deeper into some of these topics: Rares and Altan are on the team building Nx Cloud, and during the conference, they dove deeper into some of these topics:
@ -117,7 +117,7 @@ Tusky will also be able to provide organizational-level insights to your codebas
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! 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!
For a long time, Nx has been purposefully versioning and publishing agnostic, but given our time spent as [stewards of Lerna](https://blog.nrwl.io/lerna-is-dead-long-live-lerna-61259f97dbd9) (the OG Javascript monorepo tool), weve been able to take alot of that experience and finally feel confident creating our own versioning and publishing implementation. For a long time, Nx has been purposefully versioning and publishing agnostic, but given our time spent as [stewards of Lerna](/blog/lerna-is-dead-long-live-lerna) (the OG Javascript monorepo tool), weve been able to take alot of that experience and finally feel confident creating our own versioning and publishing implementation.
Therefore, weve been working on a new command to the Nx CLI: [nx release](/recipes/nx-release/get-started-with-nx-release#get-started-with-nx-release). We launched this on Friday of our Launch Nx week! Therefore, weve been working on a new command to the Nx CLI: [nx release](/recipes/nx-release/get-started-with-nx-release#get-started-with-nx-release). We launched this on Friday of our Launch Nx week!

View File

@ -32,7 +32,7 @@ But lets see all the extra things we did this past year to make everything fa
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 [this repo](https://github.com/vsavkin/large-monorepo) 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. 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 [this repo](https://github.com/vsavkin/large-monorepo) 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.
### **Task Hasher and archive file innovations** ### Task Hasher and archive file innovations
The introduction of a task hasher written in Rust, alongside the use of an archive file to store workspace file hashes (`.nx/cache`), 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. The introduction of a task hasher written in Rust, alongside the use of an archive file to store workspace file hashes (`.nx/cache`), 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.
@ -48,7 +48,7 @@ Nx Replay enables caching and reusing of task results. Its our well known Nx
With Nx Replay, you can see significant speed improvements in your CI pipelines for modified PRs. Whats 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. With Nx Replay, you can see significant speed improvements in your CI pipelines for modified PRs. Whats 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.
### **Nx Agents** ### Nx Agents
![](/blog/images/2024-03-20/bodyimg2.avif) ![](/blog/images/2024-03-20/bodyimg2.avif)
@ -64,13 +64,13 @@ With Nx Replay, you can see significant speed improvements in your CI pipelines
You can read more about Nx Agents [here](https://nx.app/products/agents#content). You can read more about Nx Agents [here](https://nx.app/products/agents#content).
### **Atomizer** ### Atomizer
The [Atomizer](/ci/features/split-e2e-tasks) 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. The [Atomizer](/ci/features/split-e2e-tasks) 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.
{% youtube src="https://www.youtube.com/watch?v=0YxcxIR7QU0" /%} {% youtube src="https://www.youtube.com/watch?v=0YxcxIR7QU0" /%}
### **Addressing flaky tests with test deflaking** ### Addressing flaky tests with test deflaking
Flaky tests can be a significant bottleneck in the CI process. Nx tackles this issue head-on by intelligently [re-running only the flaky tasks](/ci/features/flaky-tasks), rather than the entire pipeline. This approach not only saves time but also provides developers with more confidence in their CI pipeline's reliability. Flaky tests can be a significant bottleneck in the CI process. Nx tackles this issue head-on by intelligently [re-running only the flaky tasks](/ci/features/flaky-tasks), rather than the entire pipeline. This approach not only saves time but also provides developers with more confidence in their CI pipeline's reliability.
@ -102,4 +102,4 @@ Nx provides an unparalleled toolkit for developers and teams looking to optimize
- [Nx GitHub](https://github.com/nrwl/nx) - [Nx GitHub](https://github.com/nrwl/nx)
- [Nx Community Discord](https://go.nx.dev/community) - [Nx Community Discord](https://go.nx.dev/community)
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools) - [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Speed up your CI](https://nx.app) - [Speed up your CI](/nx-cloud)

View File

@ -171,11 +171,9 @@ The spirit of this post is similar to Alan Kay's quote, "A change of perspective
--- ---
You can learn more about Nx Cloud on [nx.app](https://nx.app) and Nx open source on [nx.dev](). You can learn more about Nx Cloud on [our docs](/nx-cloud).
**Nx Cloud Pro includes a 2-month free trial** that is definitely worth trying out if you're curious what Cloud Pro can do for your CI. You can try out Nx Agents, e2e test splitting, deflaking and more. [Learn more about Nx Cloud Pro.](https://nx.app/campaigns/pro) **Nx Cloud Pro includes a 2-month free trial** that is definitely worth trying out if you're curious what Cloud Pro can do for your CI. You can try out Nx Agents, e2e test splitting, deflaking and more. [Learn more about Nx Cloud Pro.](/pricing)
We also have a **Pro for Startups** plan which offers agents that are 3.5x cheaper than analogous VMs on CircleCI or Github Actions. [Learn more about Nx Pro for Startups.](https://nx.app/campaigns/pro-for-startups)
--- ---
@ -187,4 +185,4 @@ We also have a **Pro for Startups** plan which offers agents that are 3.5x cheap
- [Nx GitHub](https://github.com/nrwl/nx) - [Nx GitHub](https://github.com/nrwl/nx)
- [Nx Community Discord](https://go.nx.dev/community) - [Nx Community Discord](https://go.nx.dev/community)
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools) - [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Speed up your CI](https://nx.app) - [Speed up your CI](/nx-cloud)

View File

@ -24,7 +24,7 @@ Here's the rundown of the major things we'll cover in this update:
- [Nx Atomizer Enhancements](#nx-atomizer-enhancements) - [Nx Atomizer Enhancements](#nx-atomizer-enhancements)
- [Associated Technologies Added To Tasks](#associated-technologies-added-to-tasks) - [Associated Technologies Added To Tasks](#associated-technologies-added-to-tasks)
- [Generators to Convert to Project Crystal](#generators-to-convert-to-project-crystal) - [Generators to Convert to Project Crystal](#generators-to-convert-to-project-crystal)
- [BREAKING CHANGE: Updating Bundled Environment Variables: `NX_` to `NX_PUBLIC_`](#breaking-change-updating-bundled-environment-variables-to) - [BREAKING CHANGE: Updating Bundled Environment Variables: `NX_` to `NX_PUBLIC_`](#breaking-change-updating-bundled-environment-variables-nx-to-nxpublic)
- [General Crystal Polishing](#general-crystal-polishing) - [General Crystal Polishing](#general-crystal-polishing)
- [Nx Cloud Updates!](#nx-cloud-updates) - [Nx Cloud Updates!](#nx-cloud-updates)
- [More Miscellaneous Updates!](#more-miscellaneous-updates) - [More Miscellaneous Updates!](#more-miscellaneous-updates)
@ -170,9 +170,9 @@ In addition - we are adding more process to make the triage of these issues more
## Nx Cloud Updates! ## Nx Cloud Updates!
[![The Nx Cloud Dashboard](/blog/images/2024-05-08/nx-cloud-dashboard.webp)](https://nx.app/#deep-understanding) [![The Nx Cloud Dashboard](/blog/images/2024-05-08/nx-cloud-dashboard.webp)](/nx-cloud#deep-understanding)
We've got some cool stats to share from our users regarding the benefits of [Nx Cloud](https://nx.app), our premium CI service. The three areas we've identified as the critical aspects of a CI provider are: speed, cost, and reliablity. In these areas we've seen: We've got some cool stats to share from our users regarding the benefits of [Nx Cloud](/nx-cloud), our premium CI service. The three areas we've identified as the critical aspects of a CI provider are: speed, cost, and reliablity. In these areas we've seen:
- **speed**: Reported 30% - 70% faster CI - **speed**: Reported 30% - 70% faster CI
- **cost**: Reported 40% - 75% reduction in CI costs - **cost**: Reported 40% - 75% reduction in CI costs
@ -186,7 +186,7 @@ Since then, the Atomizer has received a nice UI update (as we had seen earlier):
Since February, we also revamped our task distribution algorithms. This has resulted in a 5-20% (depending on the repo) increase in both speed and cost efficiency for our users. Since February, we also revamped our task distribution algorithms. This has resulted in a 5-20% (depending on the repo) increase in both speed and cost efficiency for our users.
If you are interested in trying Nx Cloud, go to [https://nx.app](https://nx.app). If you are interested in trying Nx Cloud, go to [https://cloud.nx.app](https://cloud.nx.app).
## More Miscellaneous updates! ## More Miscellaneous updates!

View File

@ -0,0 +1,97 @@
---
title: Better security with Personal Access Tokens
slug: personal-access-tokens
authors: ['Philip Fulcher']
tags: [nx-cloud]
cover_image: /blog/images/2024-09-05/personal-access-tokens-header.avif
---
Today, Nx Cloud gets a huge upgrade to managing access to your cached artifacts
using [Nx Replay](/ci/features/remote-cache). Previously, workspaces
were limited to defining access tokens with read or read/write permissions for an entire workspace. With the
introduction of _personal access tokens_, you gain much more control over access. This is a feature request we've heard
from many customers, especially our [Enterprise](/enterprise) customers, and we're happy to be able to deliver this
enhancement.
## Access Tokens and the problem of revoking access
Our previous implementation of access tokens required you to commit the access token to your `nx.json` file. Typically,
service providers don't recommend committing any kind of API token like this, and we've fielded a lot of questions about
this practice in the past. It is safe to commit this token, as access to the cached artifacts of Nx Cloud rely on both
the access token and the source code itself. Without access to both, you can't access the cache.
However, this did present the following problem: revoking someone's access to the cache became difficult as long as they
had the source code. Imagine a scenario where someone has left an organization. As long as they have a clone of the
repo, they have everything they need to access the cache, even if their credentials have been
revoked. To fully revoke
their access would require cycling the access token, which could interrupt the work of other developers and CI
pipelines.
## Access Tokens become CI Access Tokens
What we previously called "access tokens" will now be called "[CI access tokens](/ci/recipes/security/access-tokens)."
They are still defined at the workspace
level, but are designed for use in CI. These tokens should be set as environment variables or secrets on your CI
platform so that they're no longer committed to your repo.
## What are personal access tokens?
[Personal access tokens](/ci/recipes/security/personal-access-tokens) are a new type of access token that is scoped to
an individual user. This means that this token lives and dies with that member's access to your Nx Cloud workspace.
Users must log in to Nx Cloud and they are a member of a workspace before a personal access token can be created.
Once created, we validate that token for access each time you use the distributed cache. As soon as a user loses access,
the personal access token no
longer works, and access to the cache is removed.
This gets even more powerful when combined with the GitHub VCS integration. When a user's GitHub access is removed from
a GitHub-connected organization, their access to Nx Cloud is removed, and their personal access token is invalidated.
This means that Nx Cloud can fit into existing user de-provisioning processes you already have.
Open source teams also benefit from personal access tokens. You can configure your access to allow anonymous users to
read from the cache, but limit read/write access to core contributors.
## Controlling default access
![Personal access token settings in Nx Cloud workspace](/blog/images/2024-09-05/workspace-settings.avif)
By default, a workspace that opts in to personal access tokens will allow anonymous users (users without a personal
access token defined) read-only access. This can be changed to disallow access to the cache for anonymous users
in your workspace settings.
Users with personal access tokens will have read-only access to the cache. This can be changed to enable read-write
access in the workspace settings.
## Converting existing workspaces to use personal access tokens
Personal access tokens can be enabled with _Nx versions 13+_. These steps will get you started, but you
can [find more details in our docs](/ci/recipes/security/personal-access-tokens).
1. **Convert to using `nxCloudId` by running `npx nx-cloud convert-to-nx-cloud-id`** - Previously, your `nx.json` had a
CI
access token defined in the `nxCloudAccessToken` property. This command will replace that with `nxCloudId`, a generic
id that references your workspace but no longer provides access to the cache.
2. **Generate a personal access token by running `npx nx-cloud login`** - Follow the directions in your terminal to log
in
to Nx Cloud. Each contributor with access to the workspace will need to complete this step.
3. **Move CI access tokens to environment variables** - Now that the access token is no longer committed to your
`nx.json`,
you'll need to provide that CI access token via the
`NX_CLOUD_ACCESS_TOKEN` [environment variable](/ci/reference/env-vars#nxcloudaccesstoken).
4. **_Optional_ Disable anonymous access** - By default, anyone without a personal access token will have read-only
access
to your cached artifacts. Once everyone has a personal access token defined, you can disable this anonymous access in
your Nx Cloud workspace settings.
[Learn more about using personal access tokens](/ci/recipes/security/personal-access-tokens)
## Learn more
- [Nx Docs](/getting-started/intro)
- [Nx Cloud Cache Security](/ci/concepts/cache-security)
- [Nx Cloud Personal Access Tokens](/ci/recipes/security/personal-access-tokens)
- [Nx Cloud CI Access Tokens](/ci/recipes/security/access-tokens)
- [X/Twitter](https://twitter.com/nxdevtools) -- [LinkedIn](https://www.linkedin.com/company/nrwl/)
- [Nx GitHub](https://github.com/nrwl/nx)
- [Nx Official Discord Server](https://go.nx.dev/community)
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Speed up your CI](https://nx.app/)

View File

@ -56,7 +56,6 @@
{ {
"name": "Philip Fulcher", "name": "Philip Fulcher",
"image": "/blog/images/Philip Fulcher.jpeg", "image": "/blog/images/Philip Fulcher.jpeg",
"twitter": "philipjfulcher",
"github": "philipjfulcher" "github": "philipjfulcher"
}, },
{ {
@ -64,5 +63,77 @@
"image": "/blog/images/Mike Hartington.png", "image": "/blog/images/Mike Hartington.png",
"twitter": "mhartington", "twitter": "mhartington",
"github": "mhartington" "github": "mhartington"
},
{
"name": "Benjamin Cabanes",
"image": "/blog/images/Benjamin Cabanes.jpeg",
"twitter": "bencabanes",
"github": "bcabanes"
},
{
"name": "Brandon Roberts",
"image": "/blog/images/Brandon Roberts.jpeg",
"twitter": "brandontroberts",
"github": "brandontroberts"
},
{
"name": "Chau Tran",
"image": "/blog/images/Chau Tran.jpeg",
"twitter": "Nartc1410",
"github": "nartc"
},
{
"name": "Daniel Muller",
"image": "/blog/images/Daniel Muller.jpeg",
"twitter": "the_meku",
"github": "mrmeku"
},
{
"name": "Jack Hsu",
"image": "/blog/images/Jack Hsu.jpeg",
"twitter": "jay_soo",
"github": "jaysoo"
},
{
"name": "Jo Hanna Pearce",
"image": "/blog/images/Jo Hanna Pearce.jpeg",
"github": "jdpearce",
"twitter": "jhannapearce"
},
{
"name": "Leosvel Pérez Espinosa",
"image": "/blog/images/Leosvel Pérez Espinosa.jpeg",
"twitter": "leosvelperez_",
"github": "leosvelperez"
},
{
"name": "Miroslav Jonaš",
"image": "/blog/images/Miroslav Jonaš.jpeg",
"twitter": "meeroslav",
"github": "meeroslav"
},
{
"name": "Nicholas Cunningham",
"image": "/blog/images/Nicholas Cunningham.jpeg",
"twitter": "ndcunningham",
"github": "ndcunningham"
},
{
"name": "Torgeir Helgevold",
"image": "/blog/images/Torgeir Helgevold.jpeg",
"twitter": "helgevold",
"github": "thelgevold"
},
{
"name": "Jason Jean",
"image": "/blog/images/Jason Jean.jpeg",
"twitter": "FrozenPandaz",
"github": "FrozenPandaz"
},
{
"name": "Nx",
"image": "/blog/images/Nx.jpeg",
"twitter": "NxDevTools",
"github": "nrwl"
} }
] ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Some files were not shown because too many files have changed in this diff Show More