today, we're going to talk about library and Nx (...and much more)
A task runner
A task runner
that can orchestrates and executes tasks efficiently
A task runner
that can orchestrates and executes tasks efficiently
A task runner
that can orchestrates and executes tasks efficiently
because it knows about your projects
It is also a collection of tools
It is also a collection of tools
1. The demo is in Nx 19. What about Nx 20?
1. The demo is in Nx 19. What about Nx 20?
2. The demo uses Angular. Why?
twitter.com/@nartc1410
github.com/nartc
npx create-nx-workspace <name_of_workspace>
npx create-nx-workspace <name_of_workspace>
--package-manager=npm,yarn,pnpm
npx create-nx-workspace <name_of_workspace>
npm i -D @nx/angular
npx nx generate @nx/angular:library libs/core
--publishable
--import-path="@js-day-demo/core"
--standalone
Demo
npx nx generate @nx/angular:app apps/playground
Demo
@angular/core
@angular/core
@angular/core/testing
@angular/core
@angular/core/testing
https://unpkg.com/browse/msw@2.5.1/package.json
npx nx generate @nx/angular:entry-point
Demo
npx ng add <name-of-library>
npm i -D @nx/plugin
npx nx generate @nx/plugin:plugin libs/plugin
npx nx generate @nx/plugin:generator
Demo
A smart release tool because it has information about the Project Graph
Demo
Demo
Angular Package Format
https://angular.dev/tools/libraries/angular-package-format
Ensure seamless integration with other tools
Ensure seamless integration with other tools
Secondary Entry Points
Ensure seamless integration with other tools
Secondary Entry Points
@angular/core -- @angular/core/testing
@angular/material -- @angular/material/button
Ensure seamless integration with other tools
Secondary Entry Points
Optimization w/ Partial Compilation
Ensure seamless integration with other tools
Secondary Entry Points
Optimization w/ Partial Compilation
Ensure seamless integration with other tools
Secondary Entry Points
Optimization w/ Partial Compilation
Ensure seamless integration with other tools
Secondary Entry Points
Optimization w/ Partial Compilation
ng new my-workspace --no-create-application
https://angular.dev/tools/libraries/creating-libraries/
ng new my-workspace --no-create-application
ng new my-workspace --no-create-application
cd my-workspace
ng new my-workspace --no-create-application
cd my-workspace
ng generate library my-library
ng build my-library
ng build my-library
Secondary Entry Points
karma
karma
Scalability
Scalability
Other details like docs, storybook, e2e ...
Schematics
Monorepo
Monorepo
nx build
nx serve
nx test
CLI
Monorepo
nx build
nx serve
nx test
CLI
Performance
npx create-nx-workspace@latest my-nx-workspace
npx create-nx-workspace@latest my-nx-workspace
--preset=apps # we'll set up Angular later
npx create-nx-workspace@latest my-nx-workspace
--preset=apps # we'll set up Angular later
--workspace-type=integrated # we'll use apps/libs convention
npx create-nx-workspace@latest my-nx-workspace
--preset=apps # we'll set up Angular later
--workspace-type=integrated # we'll use apps/libs convention
npm install --save-dev @nx/angular
npx nx generate @nx/angular:library my-library
npx nx generate @nx/angular:library my-library --help
npx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
npx nx generate @nx/angular:library my-library
--publishable
--import-path=@my-library/core
npx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
npx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
--unit-test-runner=jest
npx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
--unit-test-runner=jest
--directory=libs/my-library
npx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
--unit-test-runner=jest
--directory=libs/my-library
npx nx test my-library
npx nx test my-library
npx nx test my-library
Secondary Entry Points
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-library
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-library
Secondary Entry Points
npx nx build my-library
Secondary Entry Points
npx nx build my-library
Secondary Entry Points
npx nx build my-library
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
npx nx graph
Secondary Entry Points
npx nx graph
Secondary Entry Points
Secondary Entry Points
Each entry point should be a Nx "project"
Secondary Entry Points
Each entry point should be a Nx "project"
with their own lint and test targets
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-library
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-library
the plugin name
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-library
the generator
Secondary Entry Points
npx nx generate my-workspace-plugin:entry-point first-entry-point
--library=my-library
What if?
Secondary Entry Points
npm i --save-dev @nx/plugin
Secondary Entry Points
npx nx generate plugin my-workspace-plugin
--directory=libs/my-workspace-plugin
Secondary Entry Points
npx nx generate plugin my-workspace-plugin
--directory=libs/my-workspace-plugin
Secondary Entry Points
npx nx generate generator entry-point
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/entry-point
Secondary Entry Points
npx nx generate generator entry-point
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/entry-point
Secondary Entry Points
npx nx generate generator entry-point
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/entry-point
Secondary Entry Points
npx nx generate generator convert-to-project
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/convert-to-project
Secondary Entry Points
Project == project.json exists
Secondary Entry Points
export async function convertToProjectGenerator(
tree: Tree,
options: ConvertToProjectGeneratorSchema
) {
await formatFiles(tree);
}
export default convertToProjectGenerator;
Secondary Entry Points
export async function convertToProjectGenerator(
tree: Tree,
options: ConvertToProjectGeneratorSchema
) {
const projectRoot = `libs/my-library/${options.name}`;
if (!tree.exists(projectRoot)) {
return logger.error(`Entry point ${options.name} does not exist`);
}
const isProjectJsonExist = tree.exists(`${projectRoot}/project.json`);
if (isProjectJsonExist) {
return logger.info(`Entry point ${options.name} is already a Project`);
}
await formatFiles(tree);
}
export default convertToProjectGenerator;
Secondary Entry Points
export async function convertToProjectGenerator(
tree: Tree,
options: ConvertToProjectGeneratorSchema
) {
const projectRoot = `libs/my-library/${options.name}`;
if (!tree.exists(projectRoot)) {
return logger.error(`Entry point ${options.name} does not exist`);
}
const isProjectJsonExist = tree.exists(`${projectRoot}/project.json`);
if (isProjectJsonExist) {
return logger.info(`Entry point ${options.name} is already a Project`);
}
const projectConfiguration = readProjectConfiguration(tree, 'my-library');
addProjectConfiguration(tree, `my-library/${options.name}`, {
root: projectRoot,
projectType: 'library',
sourceRoot: `${projectRoot}/src`,
targets: {
test: {
executor: '@nx/jest:jest',
outputs: [`{workspaceRoot}/coverage/{projectRoot}/${options.name}`],
options: {
jestConfig: `${projectConfiguration.root}/jest.config.ts`,
testPathPattern: [options.name],
passWithNoTests: true,
},
},
lint: {
executor: '@nx/eslint:lint',
outputs: ['{options.outputFile}'],
},
},
});
await formatFiles(tree);
}
export default convertToProjectGenerator;
Secondary Entry Points
import {librarySecondaryEntryPointGenerator} from '@nx/angular/generators';
import {formatFiles, Tree,} from '@nx/devkit';
import convertToProjectGenerator from "../convert-to-project/generator";
import {EntryPointGeneratorSchema} from './schema';
export async function entryPointGenerator(
tree: Tree,
options: EntryPointGeneratorSchema
) {
await librarySecondaryEntryPointGenerator(tree, {
name: options.name,
library: 'my-library'
});
await convertToProjectGenerator(tree, {
name: options.name
})
await formatFiles(tree);
}
export default entryPointGenerator;
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
npx nx generate convert-to-project first-entry-point
npx nx generate convert-to-project second-entry-point
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
npx nx graph --affected
Secondary Entry Points
npx nx graph --affected
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
Applications
Applications
Applications
Application to test your UI components
Applications
Application to test your UI components
An e2e application to test your test application
Applications
Application to test your UI components
An e2e application to test your test application
Applications
Application to test your UI components
An e2e application to test your test application
An application for your documentation
Applications
Application to test your UI components
An e2e application to test your test application
Applications
Application to test your UI components
An e2e application to test your test application
npx nx generate app test-app
--directory=apps/test-app
--bundler=esbuild
--e2e-test-runner=playwright
--style=css # you can pick whatever
# --...other options...
Applications
Application to test your UI components
An e2e application to test your test application
Applications
Application to test your UI components
An e2e application to test your test application
Applications
Application to test your UI components
An e2e application to test your test application
Applications
An application for your documentation
Applications
An application for your documentation
https://starlight.astro.build/
Applications
An application for your documentation
npm create astro@latest -- --template starlight
Applications
An application for your documentation
Applications
An application for your documentation
Applications
An application for your documentation
npx nx dev docs
Applications
An application for your documentation
npx nx dev docs
Applications
An application for your documentation
npx nx dev docs
Schematics
Schematics
ng add, ng update
Schematics
Schematics
npx nx generate plugin my-plugin --directory=libs/my-plugin
Schematics
npx nx generate plugin my-plugin --directory=libs/my-plugin
npx nx generate generator init
--project=my-plugin
--directory=libs/my-plugin/src/generators/init
Schematics
npx nx generate plugin my-plugin --directory=libs/my-plugin
npx nx generate generator init
--project=my-plugin
--directory=libs/my-plugin/src/generators/init
Schematics
touch libs/my-plugin/src/generators/init/compat.ts
Schematics
touch libs/my-plugin/src/generators/init/compat.ts
Schematics
{
"generators": {
"init": {
"factory": "./src/generators/init/generator",
"schema": "./src/generators/init/schema.json",
"description": "init generator"
}
}
}
Schematics
{
"generators": {
"init": {
"factory": "./src/generators/init/generator",
"schema": "./src/generators/init/schema.json",
"description": "init generator"
}
},
"schematics": {
"ng-add": {
"factory": "./src/generators/init/compat",
"schema": "./src/generators/init/schema.json",
"description": "Init generator"
}
}
}
Schematics
npx nx generate migration rename-first-entry-point
--project=my-plugin
--directory=libs/my-plugin/src/migrations/rename-first-entry-point
Schematics
npx nx generate migration rename-first-entry-point
--project=my-plugin
--directory=libs/my-plugin/src/migrations/rename-first-entry-point
Schematics
{
"name": "my-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/my-plugin/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/my-library",
...
}
},
"test": {
...
}
}
}
Schematics
{
"name": "my-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/my-plugin/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/my-library/plugin",
...
}
},
"test": {
...
}
}
}
Schematics
{
"name": "my-library",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^17.3.0",
"@angular/core": "^17.3.0"
},
"sideEffects": false
}
Schematics
{
"name": "my-library",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^17.3.0",
"@angular/core": "^17.3.0"
},
"sideEffects": false,
"generators": "./plugin/generators.json",
"schematics": "./plugin/generators.json",
"nx-migrations": {
"migrations": "./plugin/migrations.json"
},
"ng-update": {
"migrations": "./plugin/migrations.json"
}
}
Schematics
{
"name": "my-library",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/my-library/src",
"prefix": "lib",
"projectType": "library",
"tags": [],
"targets": {
"build": {
...
},
"test": {
...
},
"lint": {
...
}
}
}
Schematics
{
"name": "my-library",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/my-library/src",
"prefix": "lib",
"projectType": "library",
"tags": [],
"targets": {
"package": {
"executor": "nx:run-commands",
"options": {
"commands": [
"nx build my-library",
"nx build my-plugin"
],
"parallel": false
}
},
"build": {
...
},
"test": {
...
},
"lint": {
...
}
}
}
Schematics
Release
Release
{
...,
"release": {
"projects": [
"my-library"
],
"version": {
"preVersionCommand": "nx package my-library"
},
"releaseTagPattern": "{version}",
"conventionalCommits": {}
}
}
Release
{
...,
"release": {
"version": {
"generatorOptions": {
"packageRoot": "dist/{projectRoot}",
"currentVersionResolver": "git-tag"
}
}
},
"targets": {...}
}
Release
npx nx release --first-releast
Release
npx nx release --first-releast
Release
npx nx release --first-releast
Release
npx nx release --first-releast
https://monorepo.tools/conf
https://monorepo.tools/conf
https://github.com/ngxtension/ngxtension-platform
nx g @nx/angular:lib ngxtension
nx g @nx/angular:lib ngxtension
nx g @nx/plugin:plugin local-plugin
nx g @nx/plugin:plugin plugin
nx g @nx/angular:lib ngxtension
nx g @nx/plugin:plugin local-plugin
nx g @nx/plugin:plugin plugin
nx g @nx/plugin:plugin local-plugin
nx g @nx/angular:lib ngxtension
nx g @nx/plugin:plugin local-plugin
nx g @nx/plugin:plugin plugin
nx g @nx/plugin:plugin local-plugin
npm create astro --template=starlight
nx g @nx/angular:entry-point
nx g @nx/angular:entry-point