
β¨ This workspace has been generated by Nx, a Smart, fast and extensible build system. β¨ for the Sfeir School Nx
-
Create the workspace:
npx --yes [email protected] nx-multi-stacks-monorepo --preset=apps --workspaceType=integrated --nxCloud=false
-
Move into the created repo:
cd nx-multi-stacks-monorepo
and open it inside you IDE of choice -
Add
@nx/[email protected] @nx/[email protected] @nxrocks/nx-spring-boot@latest
plugins as a dev dependencies:npm install -D @nx/[email protected] @nx/[email protected] @nxrocks/nx-spring-boot@latest
πΎ Save the current state!
$ git add --all $ git commit -m 'chore: add angular, react and spring-boot plugins'
-
Generate the angular application:
npx nx generate @nx/angular:application --name=ngapp --directory=frontend/apps/ngapp --routing=true --standalone=true --projectNameAndRootFormat=as-provided --style=scss --prefix=ngapp --port=1200 --backendProject=api --tags="type:app, type:angular, type:frontend" --no-interactive
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(ngapp): generate a basic angular application'
-
Generate the angular library:
npx nx g @nx/angular:library --name=nglib --buildable=true --directory=frontend/libs/nglib --changeDetection=OnPush --prefix=nglib --projectNameAndRootFormat=as-provided --style=scss --tags="type:lib, type:angular, type:frontend" --skipModule=true --no-interactive
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(nglib): generate a basic angular library'
-
Generate a
Welcome
Component inside thenglib
above:npx nx g @nx/angular:component --name=welcome --directory=frontend/libs/nglib/src/components --export=true --standalone=true --changeDetection=OnPush --nameAndDirectoryFormat=as-provided --prefix=nglib
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(nglib): generate a basic `Welcome` component inside `nglib`'
-
Update the generated
Welcome
component above and use it inngapp
as such:frontend/libs/nglib/src/components/welcome.component.html
:
-<p>welcome works!</p> +<div class="welcome"> + <p>Welcome again, from <strong>nglib!</strong></p> + <p>Today is: <strong>{{ today | date}}</strong></p> +</div>
frontend/libs/nglib/src/components/welcome.component.scss
:
+.welcome { + border-radius: 4px; + border: 2px solid red; + padding: 1rem; + margin-top: 0.5rem; + margin-bottom: 0.5rem; +}
frontend/libs/nglib/src/components/welcome.component.ts
:
-export class WelcomeComponent {} +export class WelcomeComponent { + today = new Date(); +}
frontend/apps/ngapp/src/app/nx-welcome.component.ts
:
import { Component, ViewEncapsulation } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { WelcomeComponent } from '@nx-multi-stacks-monorepo/nglib'; @Component({ selector: 'ngapp-nx-welcome', standalone: true, - imports: [CommonModule], + imports: [CommonModule, WelcomeComponent], template: ` <!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * import { CommonModule } from '@angular/common'; <span> Hello there, </span> Welcome ngapp π </h1> + <nglib-welcome></nglib-welcome> </div> <!-- HERO --> <div id="hero" class="rounded">
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(ngapp): update `Welcome` component from `nglib` and use it in `ngapp`'
-
Generate the react application:
npx nx g @nx/react:application --name=reactapp --directory=frontend/apps/reactapp --projectNameAndRootFormat=as-provided --routing=true --style=scss --tags="type:app, type:react, type:frontend" --no-interactive
- Open
frontend/apps/reactapp/project.json
and change default port use to serve the app to2200
(to avoid conflict with other apps):
"serve": { "executor": "@nx/webpack:dev-server", "defaultConfiguration": "development", "options": { "buildTarget": "reactapp:build", - "hmr": true + "hmr": true, + "port": 2200 },
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(reactapp): generate a basic react application'
- Open
-
Generate the react library:
npx nx generate @nx/react:library --name=reactlib --unitTestRunner=jest --directory=frontend/libs/reactlib --component=false --projectNameAndRootFormat=as-provided --style=scss --tags="type:lib, type:react, type:frontend" --no-interactive
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(reactlib): generate a basic react library'
-
Generate a
Welcome
Component inside thereactlib
above:npx nx g @nx/react:component --name=welcome --directory=frontend/libs/reactlib/src/components --export=true --standalone=true --changeDetection=OnPush --nameAndDirectoryFormat=as-provided --prefix=reactlib
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(reactlib): generate a basic `Welcome` component inside `reactlib`'
-
Update the generated
Welcome
component above and use it inreactapp
as such:frontend/libs/reactlib/src/components/welcome.tsx
:
export interface WelcomeProps {} export function Welcome(props: WelcomeProps) { + const today = new Date().toDateString(); return ( - <div className={styles['container']}> - <h1>Welcome to Welcome!</h1> + <div className={styles['welcome']}> + <h1>Welcome again, from <strong>reactlib!</strong></h1> + <p>Today is: <strong>{today}</strong></p> </div> ); }
frontend/libs/reactlib/src/components/welcome.module.scss
:
-/* - * Replace this with your own classes - * - * e.g. - * .container { - * } -*/ +.welcome { + border-radius: 4px; + border: 2px solid red; + padding: 1rem; + margin-top: 0.5rem; + margin-bottom: 0.5rem; +}
frontend/apps/reactapp/src/app/nx-welcome.tsx
:
-/* - * * * * * * * * * * * * * * * * * * * * * * * * * * * * - This is a starter component and can be deleted. - * * * * * * * * * * * * * * * * * * * * * * * * * * * * - Delete this file and get started with your project! - * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ +import { Welcome } from "@nx-multi-stacks-monorepo/reactlib"; + export function NxWelcome({ title }: { title: string }) { return ( <> export function NxWelcome({ title }: { title: string }) { Welcome {title} π </h1> </div> - + <Welcome/> <div id="hero" className="rounded"> <div className="text-container"> <h2>
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(reactapp): update `Welcome` component from `reaclib` and use it in `reactapp`'
-
Generate the common js/ts library:
npx nx generate @nx/js:library --name=commonlib --unitTestRunner=jest --directory=frontend/libs/commonlib --projectNameAndRootFormat=as-provided --tags="type:lib, type:js, type:frontend" --no-interactive
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(commonlib): generate a basic JS/TS library'
-
Update the generated
commonlib
file above (by adding agetTodayDate()
util) and use it innglib
andreactlib
as such:frontend/libs/commonlib/src/lib/commonlib.ts
:
export function commonlib(): string { return 'commonlib'; } + +export function getTodayDate(){ + return new Date(); +}
frontend/libs/nglib/src/components/welcome.component.ts
:
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { getTodayDate } from '@nx-multi-stacks-monorepo/commonlib'; @Component({ selector: 'nglib-welcome', import { CommonModule } from '@angular/common'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class WelcomeComponent { - today = new Date(); + today = getTodayDate(); }
frontend/libs/reactlib/src/components/welcome.tsx
:
+import { getTodayDate } from '@nx-multi-stacks-monorepo/commonlib'; import styles from './welcome.module.scss'; /* eslint-disable-next-line */ export interface WelcomeProps {} export function Welcome(props: WelcomeProps) { - const today = new Date().toDateString(); + const today = getTodayDate().toDateString(); return ( <div className={styles['welcome']}> <h1>Welcome again, from <strong>reactlib!</strong></h1>
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(frontend): update `nglib` and `reactlib` to use utils from `commonlib`'
-
Generate the Spring Boot application inside a parent module
boot-parent
:npx nx g @nxrocks/nx-spring-boot:project --name=bootapp --dependencies="web,jpa,h2,actuator,devtools" --artifactId=bootapp --directory=backend/bootapp --packageName=com.example.bootapp --keepProjectLevelWrapper=false --parentModuleName=boot-parent --transformIntoMultiModule=true --tags="type:api, type:java, type:backend" --projectNameAndRootFormat=as-provided --no-interactive
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(bootapp): generate a spring boot application inside a parent module'
-
Create a
WelcomeController.java
file inbackend/boot-parent/bootapp/src/main/java/com/example/bootapp/controller/
with content:package com.example.bootapp.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController("/api") public class WelcomeController { private static final String WELCOME_TEMPLATE = "Welcome, %s, from '%s'!"; public static record WelcomeMessage(String user, String message) { } @GetMapping("/welcome") public WelcomeMessage welcome(@RequestParam(value = "user", defaultValue = "Sfeir School Nx Attendee") String user) { return new WelcomeMessage(user, String.format(WELCOME_TEMPLATE, user, "bootapp")); } }
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(bootapp): add a `Welcome` REST controller inside `bootapp`'
-
Generate the Spring Boot library inside the
boot-parent
module:npx nx generate @nxrocks/nx-spring-boot:project --name=bootlib --projectType=library --artifactId=bootlib --directory=backend/bootlib --packageName=com.example.bootlib --addToExistingParentModule=true --keepProjectLevelWrapper=false --parentModuleName=boot-parent --tags="type:api, type:java, type:backend" --projectNameAndRootFormat=as-provided --no-interactive
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(bootlib): generate a spring boot library inside a parent module'
-
Update the generated
bootapp
application to use thebootlib
:- Open
backend/boot-parent/bootapp/pom.xml
and update it as such (to use thebootlib
library from above):
</dependency> + <dependency> + <groupId>com.example</groupId> + <artifactId>bootlib</artifactId> + <version>${project.version}</version> + </dependency> +</dependencies>
- Open
backend/boot-parent/bootapp/src/main/java/com/example/bootapp/controller/WelcomeController.java
and update it as such (to use theMyService
from thebootlib
) :
package com.example.bootapp.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.example.bootlib.service.MyService; @RestController("/api") public class WelcomeController { private static final String WELCOME_TEMPLATE = "Welcome, %s, from '%s'!"; public static record WelcomeMessage(String user, String message) { } + private final MyService myService; + public WelcomeController(MyService myService) { + this.myService = myService; + } @GetMapping("/welcome") public WelcomeMessage welcome(@RequestParam(value = "user", defaultValue = "Sfeir School Nx Attendee") String user) { - return new WelcomeMessage(user, String.format(WELCOME_TEMPLATE, user, "bootapp")); + return new WelcomeMessage(user, String.format(WELCOME_TEMPLATE, user, this.myService.message())); } }
- Open
backend/boot-parent/bootapp/src/main/resources/application.properties
and update it as such (to define the property from thebootlib
library from above):
+bootlib.service.message = bootlib
- Open
backend/boot-parent/bootapp/src/main/java/com/example/bootapp/BootappApplication.java
and update it as such (to include beans fromcom.example
package, common to bothbootapp
andbootlib
):
-@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.example") public class BootappApplication {
πΎ Save the current state!
$ git add --all $ git commit -m 'chore(bootapp): update the `bootapp` to use the `bootlib`'
- Open
- Add an implicit link between the backend Spring Boot application (
bootapp
) and the frontend Angular application (ngapp
) that uses its API:npx nx g @nxrocks/nx-spring-boot:link --sourceProjectName=bootapp --targetProjectName=ngapp --no-interactive
Run nx graph
to visualize this workspace
If you happen to use Nx plugins, you can leverage code generators that might come with it.
Run nx list
to get a list of available plugins and whether they have generators. Then run nx list <plugin-name>
to see what generators are available.
Learn more about Nx generators on the docs.
To execute tasks with Nx use the following syntax:
nx <target> <project> <...options>
You can also run multiple targets:
nx run-many -t <target1> <target2>
..or add -p
to filter specific projects
nx run-many -t <target1> <target2> -p <proj1> <proj2>
Targets can be defined in the package.json
or projects.json
. Learn more in the docs.
Have a look at the Nx Console extensions. It provides autocomplete support, a UI for exploring and running tasks & generators, and more! Available for VSCode, IntelliJ and comes with a LSP for Vim users.
Just run nx build demoapp
to build the application. The build artifacts will be stored in the dist/
directory, ready to be deployed.
Nx comes with local caching already built-in (check your nx.json
). On CI you might want to go a step further.