Implicit Libraries
Project Crystal
Since version 18 (and actually a little before that), Nx has been able to infer tasks based on the project structure. This means that Nx plugins can automagically add new targets (e.g. implicitly add a test
target with the right configuration when it detects a Vitest configuration file). This is called Project Crystal.
Implicit Libraries
Implicit Libraries are a way to leverage Project Crystal to make an Nx library nothing more than a new folder in your workspace with an index.ts
file at its root.
Here is an example of what a workspace looks like with Implicit Libraries compared to Explicit Libraries.
- Explicit Libs
- Implicit Libs
libs
└── web
├── cart
│ └── ui
│ ├── .eslintrc.json
│ ├── README.md
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ └── lib
│ │ ├── cart.spec.ts
│ │ └── cart.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ ├── tsconfig.spec.json
│ ├── vite.config.ts
│ └── vitest.config.ts
└── catalog
└── ui
├── .eslintrc.json
├── README.md
├── project.json
├── src
│ ├── index.ts
│ └── lib
│ ├── catalog.spec.ts
│ └── catalog.ts
├── tsconfig.json
├── tsconfig.lib.json
├── tsconfig.spec.json
├── vite.config.ts
└── vitest.config.ts
libs
└── web
├── .eslintrc.json
├── cart
│ └── ui
│ ├── README.md
│ ├── cart.spec.ts
│ ├── cart.ts
│ └── index.ts
├── catalog
│ └── ui
│ ├── README.md
│ ├── catalog.spec.ts
│ ├── catalog.ts
│ └── index.ts
├── tsconfig.json
├── tsconfig.lib.json
├── tsconfig.spec.json
└── vite.config.ts
The Boilerplate Problem
A common drawback when creating libraries is the boilerplate. Even though they are generally generated and taken care of by Nx (using generators and migrations), it can clutter the workspace and add some cognitive load.
Here is a typical non-buildable library structure:
libs/web/catalog/ui
├── .eslintrc.json
├── README.md
├── project.json
├── src
│ ├── index.ts
│ ├── lib
│ │ ├── my-lib.spec.ts
│ │ └── my-lib.ts
│ └── test-setup.ts
├── tsconfig.json
├── tsconfig.lib.json
├── tsconfig.spec.json
└── vite.config.ts
Step 1: Shared Configuration Files
You will notice that many libraries share similar configuration files. The similarities are often per platform, but there could be other groupings.
Interestingly, most tools provide options that allow us to target specific folders and files (e.g. eslint [dir]
, vitest --root [dir]
, ...). This means that we could provide configurations that are shared by multiple libraries but use different options to target specific libraries.
For example, if you group your libraries per platform, you could move the configuration files to the common platform folder:
libs/web
├── .eslintrc.json 👈
├── catalog/ui
│ ├── README.md
│ ├── project.json
│ └── src
│ ├── index.ts
│ └── lib
│ ├── catalog.spec.ts