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,pnpmnpx 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"
--standaloneDemo
npx nx generate @nx/angular:app apps/playgroundDemo
@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-pointDemo
npx ng add <name-of-library>npm i -D @nx/pluginnpx nx generate @nx/plugin:plugin libs/pluginnpx nx generate @nx/plugin:generatorDemo
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-applicationhttps://angular.dev/tools/libraries/creating-libraries/
ng new my-workspace --no-create-applicationng new my-workspace --no-create-applicationcd my-workspaceng new my-workspace --no-create-applicationcd my-workspaceng generate library my-libraryng build my-libraryng build my-librarySecondary Entry Points
karma
karma
Scalability
Scalability
Other details like docs, storybook, e2e ...
Schematics
Monorepo
Monorepo
nx build
nx serve
nx testCLI
Monorepo
nx build
nx serve
nx testCLI
Performance
npx create-nx-workspace@latest my-nx-workspace
npx create-nx-workspace@latest my-nx-workspace
--preset=apps # we'll set up Angular laternpx create-nx-workspace@latest my-nx-workspace
--preset=apps # we'll set up Angular later
--workspace-type=integrated # we'll use apps/libs conventionnpx create-nx-workspace@latest my-nx-workspace
--preset=apps # we'll set up Angular later
--workspace-type=integrated # we'll use apps/libs conventionnpm install --save-dev @nx/angularnpx nx generate @nx/angular:library my-librarynpx nx generate @nx/angular:library my-library --helpnpx nx generate @nx/angular:library my-library
--publishable
--import-path=my-librarynpx nx generate @nx/angular:library my-library
--publishable
--import-path=@my-library/corenpx nx generate @nx/angular:library my-library
--publishable
--import-path=my-librarynpx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
--unit-test-runner=jestnpx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
--unit-test-runner=jest
--directory=libs/my-librarynpx nx generate @nx/angular:library my-library
--publishable
--import-path=my-library
--unit-test-runner=jest
--directory=libs/my-librarynpx nx test my-librarynpx nx test my-librarynpx nx test my-librarySecondary Entry Points
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-librarySecondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-librarySecondary Entry Points
npx nx build my-librarySecondary Entry Points
npx nx build my-librarySecondary Entry Points
npx nx build my-librarySecondary Entry Points
Secondary Entry Points
Secondary Entry Points
Secondary Entry Points
npx nx graphSecondary Entry Points
npx nx graphSecondary 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-librarySecondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-librarythe plugin name
Secondary Entry Points
npx nx generate @nx/angular:entry-point first-entry-point
--library=my-librarythe generator
Secondary Entry Points
npx nx generate my-workspace-plugin:entry-point first-entry-point
--library=my-libraryWhat if?
Secondary Entry Points
npm i --save-dev @nx/pluginSecondary Entry Points
npx nx generate plugin my-workspace-plugin
--directory=libs/my-workspace-pluginSecondary Entry Points
npx nx generate plugin my-workspace-plugin
--directory=libs/my-workspace-pluginSecondary Entry Points
npx nx generate generator entry-point
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/entry-pointSecondary Entry Points
npx nx generate generator entry-point
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/entry-pointSecondary Entry Points
npx nx generate generator entry-point
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/entry-pointSecondary Entry Points
npx nx generate generator convert-to-project
--project=my-workspace-plugin
--directory=libs/my-workspace-plugin/src/generators/convert-to-projectSecondary 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-pointSecondary 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 --affectedSecondary Entry Points
npx nx graph --affectedSecondary 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 starlightApplications
An application for your documentation
Applications
An application for your documentation
Applications
An application for your documentation
npx nx dev docsApplications
An application for your documentation
npx nx dev docsApplications
An application for your documentation
npx nx dev docsSchematics
Schematics
ng add, ng update
Schematics
Schematics
npx nx generate plugin my-plugin --directory=libs/my-pluginSchematics
npx nx generate plugin my-plugin --directory=libs/my-pluginnpx nx generate generator init
--project=my-plugin
--directory=libs/my-plugin/src/generators/initSchematics
npx nx generate plugin my-plugin --directory=libs/my-pluginnpx nx generate generator init
--project=my-plugin
--directory=libs/my-plugin/src/generators/initSchematics
touch libs/my-plugin/src/generators/init/compat.tsSchematics
touch libs/my-plugin/src/generators/init/compat.tsSchematics
{
"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-pointSchematics
npx nx generate migration rename-first-entry-point
--project=my-plugin
--directory=libs/my-plugin/src/migrations/rename-first-entry-pointSchematics
{
"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-releastRelease
npx nx release --first-releastRelease
npx nx release --first-releastRelease
npx nx release --first-releasthttps://monorepo.tools/conf
https://monorepo.tools/conf
https://github.com/ngxtension/ngxtension-platform
nx g @nx/angular:lib ngxtensionnx g @nx/angular:lib ngxtensionnx g @nx/plugin:plugin local-pluginnx g @nx/plugin:plugin pluginnx g @nx/angular:lib ngxtensionnx g @nx/plugin:plugin local-pluginnx g @nx/plugin:plugin pluginnx g @nx/plugin:plugin local-pluginnx g @nx/angular:lib ngxtensionnx g @nx/plugin:plugin local-pluginnx g @nx/plugin:plugin pluginnx g @nx/plugin:plugin local-pluginnpm create astro --template=starlightnx g @nx/angular:entry-pointnx g @nx/angular:entry-point