Настроить в Angular ChangeDetectionStrategy.OnPush в качестве стратегии по умолчанию:

ng config schematics.@schematics/angular.component.changeDetection OnPush

Нравится видеть визуальное представление после того, как я разработал схемы в виде кода - для этого я использую prisma-dbml-generator.

Генерирует файл .dbml из схемы Prisma, а затем я использую любой инструмент, например dbDiagram, для их просмотра.

Опять же, лично мне гораздо проще написать prisma-схемы вручную, но презентация выглядит довольно красиво - Prisma Editor.

Пара ссылок на бесплатные инструменты для визаулизации и проектирования баз данных:

Что такое диаграмма взаимосвязи объектов ERD


На официальном сайте Nx я не смог найти готовых примеров конфигурации Nx для развертывания workspace - Angular + Nest.js. После некоторых поисков нашел такой пример на StackOverflow - NX Monorepo (NestJS/Angular).

Ниже привел более подробный вариант описания этого способа.

Первоначальное решение

Устанавливаем Nx глобально в системе - для более удобной последующей работы:

nx globally npm i -g nx

Переходим к процессу развертывания - инициализируем новый workspace командой Installation:

npx create-nx-workspace

Need to install the following packages:
create-nx-workspace@19.2.3
Ok to proceed? (y)

… задаем имя для нового проекта:

Where would you like to create your workspace? ‣ awesome-project 

… на вопрос о выборе предпочтительного стека отвечаем - None - сами наполним workspace нужными стеками чуть позднее:

? Which stack do you want to use? …

None:          Configures a TypeScript/JavaScript project with minimal structure.
React:         Configures a React application with your framework of choice.
Vue:           Configures a Vue application with your framework of choice.
Angular:       Configures a Angular application with modern tooling.
Node:          Configures a Node API application with your framework of choice.

… на вопрос о выборе типа репозитория - выбираем - Integrated Monorepo:

? Package-based monorepo, integrated monorepo, or standalone project? …

Package-based Monorepo:     Nx makes it fast, but lets you run things your way.
Integrated Monorepo:        Nx creates a monorepo that contains multiple projects.
Standalone:                 Nx creates a single project and makes it fast.

… на предложение воспользоваться Nx Cloud отвечаем, что не хотим - Skip for now:

? Do you want Nx Cloud to make your CI fast? …

(it's free and can be disabled any time)
Yes, enable Nx Cloud
Yes, configure Nx Cloud for GitHub Actions
Yes, configure Nx Cloud for Circle CI
Skip for now

… процесс инициализации занимает некоторое время, после чего получаем готовый пустой workspace:

 NX   Creating your v19.2.3 workspace.

✔ Installing dependencies with npm
✔ Successfully created the workspace: awesome-project.

… переходим во вновь созданный проект:

cd awesome-project

… добавляем необходимые Nx-зависимости:

npm i -D @nx/angular @nx/nest @nx/js

… затем генерируем в workspace фронтенд на angular - @nx/angular:

nx g @nx/angular:app frontend-part

… затем генерируем бекенд на nestjs - @nx/nest:

nx g @nx/nest:app backend-part

… генерируем shared library @nx/js:library:

nx g @nx/js:lib shared-lib

С этого момента у нас есть базовая настройка. Мы можете импортировать общую библиотеку следующим образом::

import { sharedLib } from "@my-project/shared-lib";

Если в дальнейшем в проекте планируется использовать Prisma и PostgreSQL, то по дальнейшим шагам можно ознакомиться здесь - Prisma - установка в Nest-проекте.

Дополнительные источники

В процессе общения по текущей теме в Discord (Nx-форум) c пользователем @rujorgensen последний любезно предложил свой вариант готового решения - nx-workspace.

Можно сделать fork репозитория - и попробовать использовать его, как вариант.

Проверка первоначального решения

Как проверка работоспособности первоначального решения - привожу ссылку на учебный проект Task Manager.

На момент написания статьи - проект находится в стадии разработки.


В Ubuntu Gnome имеется утилита gnome-keyring, при помощи которой очень удобно работать с ключами ssh-key под GitHub или GitLab. Удобство работы с gnome-keyring заключается в том, что ssh-ключи подгружаются только один раз и потом в каждой сессии терминальной или в любом редакторе - VSC или WS - подтягиваются и используются под капотом.

В KDE, будь-то Manjaro или Kubuntu - нет пакета gnome-keyring и поэтому в каждой новой терминальной сессии или открытом редакторе при работе с Git - нужно будет авторизоваться и подгружать ssh-ключи при помощи команд:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/awesome_ssh_key

Делать это каждый раз утомительно - отвлекает внимание и занимает лишнее время. Можно немного автоматизировать процесс при помощи конфигурационного файла config.

Делается это таким образом.

В папке .ssh создаем файл конфигурации config:

cd ~/.ssh
touch config

Открываем файл конфигурации config:

nano ~/.ssh/config

Добавляем в него такое содержимое:

IdentityFile ~/.ssh/github_key
IdentityFile ~/.ssh/gitlab_key
IdentityFile ~/.ssh/id_rsa_buhlServer

Как видим, первые две строки - это путь в ssh-ключам, в моем случае под GitHub и GitLab. Третья строка - если често, не знаю что делает. Но - благодаря этим трем строкам оба ssh-ключа теперь автоматически подгружаются и используются в любой терминальной сессии или редакторе кода.

Единственный момент - для подобного случая я генерировал ssh-ключи без пароля, чтобы система или редактор не спрашивали его каждый раз. В принципе, получилась почти полноценная замена gnome-keyring.


Intersection Observer API

Itersection Observer API - это API браузера, позволяющий наблюдать за пересечениями элементов. Например, карточка оплаты на странице оплаты по мере прокрутки страницы пересекает верхнюю и/или нижнюю часть основного контента страницы. Данное API браузера позволяет отследить эти пересечения. В проекте для упрощения работы с ним используется пакет https://www.npmjs.com/package/@ng-web-apis/intersection-observer

Что требуется знать для работы с этой библиотекой

Использование IntersectionObserverAPI можно конфигурировать. Настраиваемые параметры:

  • root - тот элемент, который будет отслеживаться браузером. Если не указан, по дефолту считается viewport’ом браузерного окна.
  • rootMargin - смещение прямоугольника root-элемента. С помощью этого параметра можно сжать root-элемент. Дефолтное значение 0px 0px 0px 0px.
  • thresholds - массив значений, при которых должны срабатывать callback-пересечения. Указывается в процентах (0.15 - 15%, .5 - 50%: означает, что при пересечении целевого элемента вверх или вниз от root-элемента при 15% или 50% будет срабатывать событие callback’а). Важно: событие происходит при примерном пересечении целевого элемента границ root-элемента.

При использовании провайдеров используются следующие токены

INTERSECTION_THRESHOLD

Использование:

{
    provide: INTERSECTION_THRESHOLD,
    useValue: 0.5 // => В качестве значения можно указать и массив чисел [0, 0.5, 1]
}

INTERSECTION_ROOT_MARGIN

Использование:

{
    provide: INTERSECTION_ROOT_MARGIN,
    useValue: '0px 0px 0px 0px' // значение указывается в любом стиле CSS (all), (horizontal, vertical), (top, left, bottom, right)
}

IntersectionObserverService

Данный сервис унаследован Observable<IntersectionObserverEntry[]> и является основной единицей использования при отслеживании пересечения элементов:

@Component({
selector: 'my-component',
providers: [
    SgmDestroyService,
    IntersectionObserverService,
    {
        provide: INTERSECTION_THRESHOLD,
        useValue: 0.5,
    },
    {
        provide: INTERSECTION_ROOT_MARGIN,
        useValue: '10px',
    },
],
})

export class MyComponent {
    constructor(
        private _destroy$: SgmDestroyService,
        @Inject(IntersectionObserverService)
        entries$: IntersectionObserverService
    ) {
        entries$.pipe(
            takeUntil(this._destroy$)
        ).subscribe(entries => {
            console.log(entries);
        });
    }
}

Важно: если элемент при создании содержит высоту, равную 0px - следует оформлять подписку на entries$ в ngAfterViewInit.

Объект IntersectionObserverEntry поставляется из entries$ и имеет следующие свойства:

  • boundingClientRect - Возвращает прямоугольник границ таргет-элемента в виде. Границы вычисляются, как описано в документации для Element.getBoundingClientRect().

  • intersectionRatio - Возвращает отношение intersectionRect к boundingClientRect.

  • intersectionRect - Возвращает границы, представляющие видимую область таргет-элемента.

  • isIntersecting - Булево значение, которое является истинным, если таргет элемент пересекается с root-элементом. Если это значение истинно, то запись IntersectionObserverEntry описывает переход в состояние пересечения; если оно ложно, то переход происходит от пересечения к непересечению.

  • rootBounds - Возвращает границы для root - элемента.

  • target - Таргет - элемент.

  • time - Указывает время, в которое было зарегистрировано пересечение, относительно начала отсчета времени жизни IntersectionObserver.