Π˜ΠΌΠΏΠ»Π΅ΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡ ΠΌΠΎΠ½ΠΎΡ€Π΅ΠΏΡ‹

БСйчас Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ создания Ρ‚Ρ€Ρ‘Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ ΠΈ Π΄Π²ΡƒΡ… Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ

  • Π”Π²Π° прилоТСния React: клиСнтскоС ΠΈ административноС.
  • Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° React с ΠΈΠΌΠ΅Π½Π΅ΠΌ common-components, которая Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°ΠΌΠΈ React
  • А Node.js сСрвСр с ΠΈΠΌΠ΅Π½Π΅ΠΌ backend
  • Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° TypeScript с ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ сСрвСрной Ρ‡Π°ΡΡ‚ΡŒΡŽ

Установка

Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ с NX, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ workspace, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Ρƒ нас Π±ΡƒΠ΄ΡƒΡ‚ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρ‹

npx create-nx-workspace@latest <project>

Π£ нас Π² процСссС создания ΠΌΠΎΠ½ΠΎΡ€Π΅ΠΏΡ‹ Π±ΡƒΠ΄Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ установку для ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ для ΠΌΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ монорСпозитория. Π‘Ρ€Π΅Π΄Π° для ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° скорСС Π½ΡƒΠΆΠ½Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², сборки Π±ΠΈΠ»Π΄ΠΎΠ² ΠΈ CI/CD

Π”Π°Π»Π΅Π΅ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρ‹ с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹ΠΌΠΈ тСхнологиями (установили ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ Π² ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π½ΠΎΠ΄ΠΎΠΉ, экспрСссом, нСстом, нСкстом ΠΈ Ρ€Π΅Π°ΠΊΡ‚). ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· этих ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² прСдоставляСт Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ возмоТности для CLI ΠΏΠΎ установкС Π½ΠΎΠ²Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ.

# Установит nextjs ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
nx add @nx/next
# Π”Ρ€ΡƒΠ³ΠΈΠ΅ популярныС сСтапы
nx add @nx/react
nx add @nx/express
nx add @nx/nest
nx add @nx/node

ПослС Π²Π²ΠΎΠ΄Π° Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΡ‹ создаём Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚. ΠŸΡ€ΠΎΠ΅ΠΊΡ‚Ρ‹ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· Π²Ρ‹Π·ΠΎΠ² установлСнного ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° @nx/react с Ρ„Π»Π°Π³ΠΎΠΌ :app. ПослС этого ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ с React создастся Π² ΠΏΠ°ΠΏΠΊΠ΅ apps/admin, Π° Π² apps/backend ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ с Π½ΠΎΠ΄ΠΎΠΉ

npx nx g @nx/react:app admin
npx nx g @nx/node:app backend

Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ для React-ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ², Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ°ΠΊΠ΅Ρ‚ @nx/react с Ρ„Π»Π°Π³ΠΎΠΌ :lib ΠΏΠ°ΠΏΠΊΡƒ с распространяСмыми ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ. Π€Π»Π°Π³ :lib создаёт ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ с ΡˆΠ΅ΠΉΡ€Π΅Π±Π» ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ прилоТСния ΠΏΠΎΠ΄ Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹ΠΉ стСк ΠΏΠ°ΠΊΠ΅Ρ‚Π°. ΠšΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎ Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚ΡŒ ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ для Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΡΠΎΠ±ΠΈΡ€Π°Ρ‚ΡŒΡΡ ΠΈΠ· ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ находится Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΏΠ°ΠΏΠΊΠΈ lib/common-components

npx nx g @nx/react:lib common-components

Данная ΠΊΠΎΠΌΠ°Π½Π΄Π° создаст ΠΎΠ±Ρ‰ΠΈΠ΅ для всСх ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹

npx nx g @nx/js:lib functions

И Π½Π° Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΌΡ‹ ΠΈΠΌΠ΅Π΅ΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ структуру:

|__ apps
|    |__ admin
|    |__ admin-e2e
|    |__ backend
|    |__ backend-e2e
|    |__ customer
|    |__ customer-e2e
|__ libs
|    |__ custom-components
|    |__ functions

Π’Π°ΠΊ ΠΆΠ΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ΡŒ Π³Ρ€Π°Ρ„ взаимосвязСй Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅

npx nx graph

Π”Π°Π»Π΅Π΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ встроСнным Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ ΠΈΠ· nx ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ react-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ доступСн сразу Π² ΠΎΠ±ΠΎΠΈΡ… Π½Π°ΡˆΠΈΡ… react-ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ…

npx nx g @nx/react:component header \
--project=common-components --export

libs/common-components/src/lib/header/header.tsx

import styles from './header.module.css';
 
/* eslint-disable-next-line */
export interface HeaderProps {
  text: string;
}
 
export function Header(props: HeaderProps) {
  return (
    <header>{props.text}</header>
  );
}
 
export default Header;

Π‘Ρ€Π°Π·Ρƒ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ устанавливаСм Π½Π° нСсколько ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π²ΠΎ всСх Π½Π°ΡˆΠΈΡ… прилоТСниях. Π’ΡƒΡ‚ стоит Π°ΠΊΠΊΡƒΡ€Π°Ρ‚Π½Π΅Π΅ Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ зависимости, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ для всСх ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²

npm install axios cors date-fns

Π”Π°Π»Π΅Π΅ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ тСстовоС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ взаимосвязи Π²Π½ΡƒΡ‚Ρ€ΠΈ монорСпозитория

apps/admin/src/app/app.tsx

// eslint-disable-next-line @typescript-eslint/no-unused-vars
import styles from './app.module.css';
 
import { Header } from '@myorg/common-components';
import { useEffect, useState } from 'react';
 
import axios from 'axios';
 
export function App() {
  const [message, setMessage] = useState('');
 
  useEffect(() => {
    axios.get('http://localhost:3000/admin').then((response) => {
      setMessage(response.data);
    });
  }, []);
 
  return (
    <div>
      <Header text="Welcome to admin!" />
      <p>{message}</p>
    </div>
  );
}
 
export default App;

apps/customer/src/app/app.tsx

// eslint-disable-next-line @typescript-eslint/no-unused-vars
import styles from './app.module.css';
 
import { Header } from '@myorg/common-components';
import { useEffect, useState } from 'react';
 
import axios from 'axios';
 
export function App() {
  const [message, setMessage] = useState('');
 
  useEffect(() => {
    axios.get('http://localhost:3000/customer').then((response) => {
      setMessage(response.data);
    });
  }, []);
 
  return (
    <div>
      <Header text="Welcome to customer!" />
      <p>{message}</p>
    </div>
  );
}
 
export default App;

libs/functions/src/lib/functions.ts

import { format } from 'date-fns';
 
export function currentDate(): string {
  return format(new Date(), 'yyyy-MM-dd');
}

apps/backend/src/main.ts

import express from 'express';
import { currentDate } from '@myorg/functions';
import cors from 'cors';
 
const host = process.env.HOST ?? 'localhost';
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
 
const app = express();
app.use(cors({ origin: '*' }));
 
app.get('/customer', (req, res) => {
  res.send(`[ customer ] ${currentDate()}`);
});
 
app.get('/admin', (req, res) => {
  res.send(`[ admin ] ${currentDate()}`);
});
 
app.listen(port, host, () => {
  console.log(`[ ready ] http://${host}:${port}`);
});

И Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΈΠΌΠ΅Π΅ΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ зависимости

Π”Π°Π»Π΅Π΅ Π² Ρ€Π°Π·Π½Ρ‹Ρ… Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»Π°Ρ… ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΡΡ‘Ρ€Π²ΠΈΡ‚ΡŒ наши прилоТСния

npx nx serve backend
npx nx serve admin
npx nx serve customer

ΠœΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ отслСТивания ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π³ΠΈΡ‚Π° выдСляСм измСнСния Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅

git add .
git commit -m "Initial commit"

Π”Π°Π»Π΅Π΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Π³Ρ€Π°Ρ„ΠΎΠΌ, ΠΊΠ°ΠΊΠΈΠ΅ элСмСнты систСмы Π±Ρ‹Π»ΠΈ ΠΏΠΎΠ΄Π²Π΅Ρ€ΠΆΠ΅Π½Ρ‹ измСнСниям

npx nx affected:graph

Данная ΠΊΠΎΠΌΠ°Π½Π΄Π° позволяСт произвСсти тСстированиС Π½Π° Ρ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±Ρ‹Π»ΠΈ ΠΏΠΎΠ΄Π²Π΅Ρ€ΠΆΠ΅Π½Ρ‹ измСнСниям

npx nx affected -t test

Π‘Π°ΠΌΠΎΠ΅ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово affected: выполняСт Π»ΡŽΠ±ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ чисто Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° ΠΈΠ·ΠΌΠ΅Π½Ρ‘Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ…, Π° Π½Π΅ Π½Π° всём ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΈ