https://github.com/tinesoft/nx-multi-stacks-monorepo
Companion project for Sfeir School Nx
https://github.com/tinesoft/nx-multi-stacks-monorepo
angular nx-workspace react spring-boot
Last synced: 5 months ago
JSON representation
Companion project for Sfeir School Nx
- Host: GitHub
- URL: https://github.com/tinesoft/nx-multi-stacks-monorepo
- Owner: tinesoft
- Created: 2023-12-12T23:16:23.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-03T15:29:40.000Z (over 1 year ago)
- Last Synced: 2025-04-11T00:14:26.416Z (about 1 year ago)
- Topics: angular, nx-workspace, react, spring-boot
- Language: TypeScript
- Homepage: https://github.com/sfeir-open-source/sfeir-school-nx
- Size: 807 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Nx Multi Stacks Monorepo
✨ **This workspace has been generated by [Nx, a Smart, fast and extensible build system.](https://nx.dev)** ✨ for the **[Sfeir School Nx](https://github.com/sfeir-open-source/sfeir-school-nx)**
## How to recreate this exact workspace?
### General Instructions
1. Create the workspace: `npx --yes create-nx-workspace@17.0.0 nx-multi-stacks-monorepo --preset=apps --workspaceType=integrated --nxCloud=false`
2. Move into the created repo: `cd nx-multi-stacks-monorepo` and open it inside you IDE of choice
3. Add `@nx/angular@17.0.0 @nx/react@17.0.0 @nxrocks/nx-spring-boot@latest` plugins as a dev dependencies: `npm install -D @nx/angular@17.0.0 @nx/react@17.0.0 @nxrocks/nx-spring-boot@latest`
💾 Save the current state!
> ```shell
> $ git add --all
> $ git commit -m 'chore: add angular, react and spring-boot plugins'
> ```
### Angular Stack Instructions
1. 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(ngapp): generate a basic angular application'
> ```
2. 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(nglib): generate a basic angular library'
> ```
3. Generate a `Welcome` Component inside the `nglib` 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(nglib): generate a basic `Welcome` component inside `nglib`'
> ```
4. Update the generated `Welcome` component above and use it in `ngapp` as such:
* `frontend/libs/nglib/src/components/welcome.component.html` :
```diff
-
welcome works!
+
+ Welcome again, from nglib!
+ Today is: {{ today | date}}
+
```
* `frontend/libs/nglib/src/components/welcome.component.scss` :
```diff
+.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` :
```diff
-export class WelcomeComponent {}
+export class WelcomeComponent {
+ today = new Date();
+}
```
* `frontend/apps/ngapp/src/app/nx-welcome.component.ts` :
```diff
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: `
```
💾 Save the current state!
> ```shell
> $ git add --all
> $ git commit -m 'chore(ngapp): update `Welcome` component from `nglib` and use it in `ngapp`'
> ```
### React Stack Instructions
1. 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 to `2200` (to avoid conflict with other apps):
```diff
"serve": {
"executor": "@nx/webpack:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "reactapp:build",
- "hmr": true
+ "hmr": true,
+ "port": 2200
},
```
💾 Save the current state!
> ```shell
> $ git add --all
> $ git commit -m 'chore(reactapp): generate a basic react application'
> ```
2. 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(reactlib): generate a basic react library'
> ```
3. Generate a `Welcome` Component inside the `reactlib` 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(reactlib): generate a basic `Welcome` component inside `reactlib`'
> ```
4. Update the generated `Welcome` component above and use it in `reactapp` as such:
* `frontend/libs/reactlib/src/components/welcome.tsx` :
```diff
export interface WelcomeProps {}
export function Welcome(props: WelcomeProps) {
+ const today = new Date().toDateString();
return (
-
- Welcome to Welcome!
+
+ Welcome again, from reactlib!
+ Today is: {today}
);
}
```
* `frontend/libs/reactlib/src/components/welcome.module.scss` :
```diff
-/*
- * 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` :
```diff
-/*
- * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- 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} 👋
-
+
```
💾 Save the current state!
> ```shell
> $ git add --all
> $ git commit -m 'chore(reactapp): update `Welcome` component from `reaclib` and use it in `reactapp`'
> ```
### Common JS/TS Stack Instructions
1. 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(commonlib): generate a basic JS/TS library'
> ```
2. Update the generated `commonlib` file above (by adding a `getTodayDate()` util) and use it in `nglib` and `reactlib` as such:
* `frontend/libs/commonlib/src/lib/commonlib.ts` :
```diff
export function commonlib(): string {
return 'commonlib';
}
+
+export function getTodayDate(){
+ return new Date();
+}
```
* `frontend/libs/nglib/src/components/welcome.component.ts` :
```diff
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`:
```diff
+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 (
Welcome again, from reactlib!
```
💾 Save the current state!
> ```shell
> $ git add --all
> $ git commit -m 'chore(frontend): update `nglib` and `reactlib` to use utils from `commonlib`'
> ```
### Spring Boot Stack Instructions
1. 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(bootapp): generate a spring boot application inside a parent module'
> ```
2. Create a `WelcomeController.java` file in `backend/boot-parent/bootapp/src/main/java/com/example/bootapp/controller/` with content:
```java
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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(bootapp): add a `Welcome` REST controller inside `bootapp`'
> ```
3. 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!
> ```shell
> $ git add --all
> $ git commit -m 'chore(bootlib): generate a spring boot library inside a parent module'
> ```
4. Update the generated `bootapp` application to use the `bootlib` :
* Open `backend/boot-parent/bootapp/pom.xml` and update it as such (to use the `bootlib` library from above):
```diff
+
+ com.example
+ bootlib
+ ${project.version}
+
+
```
* Open `backend/boot-parent/bootapp/src/main/java/com/example/bootapp/controller/WelcomeController.java` and update it as such (to use the `MyService` from the `bootlib`) :
```diff
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 the `bootlib` library from above):
```diff
+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 from `com.example` package, common to both `bootapp` and `bootlib`):
```diff
-@SpringBootApplication
+@SpringBootApplication(scanBasePackages = "com.example")
public class BootappApplication {
```
💾 Save the current state!
> ```shell
> $ git add --all
> $ git commit -m 'chore(bootapp): update the `bootapp` to use the `bootlib`'
> ```
### Link Angular and Spring Boot Stacks
1. 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`
## Visualize the workspace
Run `nx graph` to visualize this workspace
## Generate code
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 ` to see what generators are available.
Learn more about [Nx generators on the docs](https://nx.dev/plugin-features/use-code-generators).
## Running tasks
To execute tasks with Nx use the following syntax:
```
nx <...options>
```
You can also run multiple targets:
```
nx run-many -t
```
..or add `-p` to filter specific projects
```
nx run-many -t -p
```
Targets can be defined in the `package.json` or `projects.json`. Learn more [in the docs](https://nx.dev/core-features/run-tasks).
## Want better Editor Integration?
Have a look at the [Nx Console extensions](https://nx.dev/nx-console). 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.
## Ready to deploy?
Just run `nx build demoapp` to build the application. The build artifacts will be stored in the `dist/` directory, ready to be deployed.
## Set up CI!
Nx comes with local caching already built-in (check your `nx.json`). On CI you might want to go a step further.
- [Set up remote caching](https://nx.dev/core-features/share-your-cache)
- [Set up task distribution across multiple machines](https://nx.dev/core-features/distribute-task-execution)
- [Learn more how to setup CI](https://nx.dev/recipes/ci)
## Connect with us!
- [Join the community](https://nx.dev/community)
- [Subscribe to the Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Follow us on Twitter](https://twitter.com/nxdevtools)
