Definition of a monorepo
How it differs from a traditional multi-repository approach
Common misconceptions about monorepos
Code organization: Single vs. multiple repositories
Dependency management: Shared vs. isolated dependencies
Collaboration: Easier cross-team collaboration vs. independent teams
CI/CD workflows: Shared pipelines vs. separate workflows
Versioning strategies: Single versioning vs. independent versions
Code sharing and reusability
Simplified dependency management
Easier refactoring across multiple projects
Unified build and CI/CD processes
Better visibility and collaboration
Increased complexity for large teams
Tooling challenges (scaling Git, handling build times)
Permissions management can be tricky
Potential for unnecessary coupling between projects
For JavaScript/TypeScript monorepos: Use Nx, Turborepo, or Lerna
For large-scale enterprise builds: Use Bazel or Rush
Managing a monorepo efficiently requires specialized tools for dependency management, builds, CI/CD, and scaling. Below is a list of the most popular monorepo tools categorized by their primary use case.
Managing a monorepo efficiently requires specialized tools for dependency management, builds, CI/CD, and scaling. Below is a list of the most popular monorepo tools categorized by their primary use case.
✅ Best For: Full-stack monorepos (React, Next.js, Angular, NestJS, Express)
✅ Why Use It?
Powerful dependency graph for understanding project structure
Task caching speeds up builds & tests
Supports React, Next.js, Angular, Node.js, NestJS
Plugin ecosystem for different frameworks
🔥 Used By: Google, Airbnb, American Airlines, Cisco
👉 Best for large teams that want maximum automation
✅ Best For: Frontend-heavy monorepos (React, Next.js, Tailwind, Storybook)
✅ Why Use It?
Blazing-fast remote caching
Minimal configuration, works with Yarn, npm, pnpm
Pipeline-based task execution (parallel builds)
Built-in support for Next.js (Vercel’s recommended tool)
🔥 Used By: Vercel, Shopify, Stripe
👉 Best for speed-focused projects, especially for frontend developers
✅ Best For: Managing multiple npm packages in a monorepo
✅ Why Use It?
Simplifies versioning and publishing
Works well with pnpm, Yarn workspaces, npm workspaces
Good for library-based monorepos like Babel, Jest, Webpack
🔥 Used By: Babel, Jest, Webpack
👉 Best for projects with independent packages that need versioning & publishing
🌟 Best All-Around → Nx (Full-stack, scalable, optimized builds)
⚡ Best for Speed → Turborepo (Frontend-focused, ultra-fast caching)
📦 Best for Package Management → Lerna (Independent package versioning)
✅ Easier dependency management → Install dependencies once, and all packages can use them.
✅ Faster installations → Dependencies are deduplicated across all packages.
✅ Automatic linking → Packages inside the monorepo are symlinked instead of installing from npm.
✅ Better developer experience → Run scripts across multiple packages easily.
api/ → A Node.js backendutils/ → A shared utility library
| Feature | npm Workspaces | Yarn Workspaces | pnpm Workspaces |
| Package linking | ✅ Yes | ✅ Yes | ✅ Yes |
| Dependency hoisting | ✅ Yes | ✅ Yes | ✅ Yes |
| Running scripts across workspaces | ✅ Yes (--workspaces) | ✅ Yes (yarn workspaces run) | ✅ Yes (pnpm -r run) |
| Monorepo Performance | 🟡 Medium | 🔵 Good | 🟢 Best |
Using Workspaces + Monorepos together gives you the best setup for managing multiple projects efficiently.
✅ Monorepo → Organizes multiple related projects in one Git repository.
✅ Workspaces → Manages multiple packages within a monorepo using npm, Yarn, or pnpm.
✅ Together, they allow:
✔️ Easy dependency management (automatic linking of internal packages)
✔️ Faster installs (deduplicating shared dependencies)
✔️ Better collaboration (single repo for multiple projects)
✔️ Improved versioning (independent or unified package versions)
Nx is a powerful monorepo tool that helps developers efficiently manage multiple projects (frontend, backend, libraries) in a single repository. It provides smart caching, code sharing, task scheduling, dependency graph visualization, and CI/CD optimizations.
✅ Performance Optimization → Smart caching speeds up builds/tests.
✅ Scalability → Easily manage multiple projects in one repo.
✅ Task Running → Parallel execution of commands (build, test, lint).
✅ Code Sharing → Reuse shared libraries across applications.
✅ Dependency Graph → Visualize relationships between projects.
✅ Works with Any Tech Stack → Supports React, Angular, Next.js, Express, NestJS, and more.
Nx structures your monorepo into:
Nx structures your monorepo into:
apps/ → Contains full-fledged applications (frontend & backend).
libs/ → Reusable libraries (@nx-monorepo/shared for business logic).
nx.json → Defines caching & build strategies.
workspace.json → Manages projects, scripts, and dependencies.
| Feature | Nx | Lerna | Turborepo | pnpm Workspaces |
|---|---|---|---|---|
| Caching | ✅ | ❌ | ✅ | ❌ |
| Code Generation | ✅ | ❌ | ❌ | ❌ |
| Task Runner | ✅ | ✅ | ✅ | ❌ |
| Dependency Graph | ✅ | ❌ | ❌ | ❌ |
| Parallel Execution | ✅ | ✅ | ✅ | ✅ |
| Built-in Support for React, Angular, NestJS | ✅ | ❌ | ❌ | ❌ |
| Nx 🚀 | Dependency graph, task caching, parallel execution, extensibility | JavaScript/TypeScript projects, full-stack apps | |
| Turborepo ⚡ | Remote caching, pipeline-based execution, lightweight | Frontend & Next.js apps, fast builds | |
| Lerna 🔄 | Manages JS/TS packages in a monorepo, versioning | JS/TS package-based monorepos |
Основным понятием выступает селектор — это некоторое имя стиля, для которого добавляются параметры форматирования.
В качестве селектора выступают теги, классы и id.
CSS не чувствителен к регистру, переносу строк, пробелам и символам табуляции, поэтому форма записи зависит от желания разработчика.
<style>
h1 { color: #a6780a; font-weight: normal; }
h2 {
color: green;
border-bottom: 2px solid black;
}
/*я комментик в css*/
</style>1. в одну строку
2. столбиком, каждое свойство с новой строки
это формальное описание того элемента или группы элементов, к которым применяется указанное правило стиля.
<head>
<style>
* {
color:red;
}
</style>
</head>
<body>
<h1>Заголовок</h1>
<p>Параграф</p>
<span>Какой-то текст</span>
</body><head>
<style>
p {
color: green;
}
</style>
</head>
<body>
<div>
<h1>Заголовок</h1>
<p>Параграф</p>
</div>
<div>
<p>Какой-то текст</p>
<span>Важная информация</span>
</div>
</body><head>
<style>
.example{
color: red;
}
</style>
</head>
<body>
<div>
<p class="example">Параграф</p>
<p>Какой-то текст</p>
<p class="example">Важная информация</p>
<p>Новый параграф</p>
</div>
</body><head>
<style>
#current{
color: red;
}
</style>
</head>
<body>
<div>
<p>Параграф 1</p>
<p id="current">Параграф 2</p>
<p>Параграф 3</p>
<p>Параграф 4</p>
</div>
</body><head>
<style>
li{
color:blue;
}
ul li{
color:red;
}
</style>
</head>
<body>
<ul>
<li>List item 1</li>
<li>List item 1</li>
<li>List item 1
<ul>
<li>List item 2</li>
<li>List item 2</li>
<li>List item 2</li>
</ul>
</li>
</ul>
</body><head>
<style>
li{
color:green;
}
.list > li{
color:red;
}
</style>
</head>
<body>
<ul class="list">
<li>List item 1</li>
<li>List item 1</li>
<li>List item 1
<ul>
<li>List item 2</li>
<li>List item 2</li>
<li>List item 2</li>
</ul>
</li>
</ul>
</body><head>
<style>
h2 {
margin-top: 30px;
}
h1+h2 {
margin-top: 15px;
}
</style>
</head>
<body>
<div>
<h1>Главный заголовок статьи</h1>
<h2>Подзаголовок</h2>
</body><head>
<style>
p ~ ul {
background: #ff0000;
}
</style>
</head>
<body>
<div>A div element.</div>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<p>The first paragraph.</p>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<h2>Another list</h2>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</body><head>
<style>
a[target] {
background-color: yellow;
}
</style>
</head>
<body>
<a href="http://www.w3schools.com">w3schools.com</a>
<a href="http://www.epam.com" target="_blank">epam.com</a>
<a href="http://www.wikipedia.org" target="_top">wikipedia.org</a>
</body><head>
<style>
a[target=_blank] {
background-color: blue;
color:white;
}
</style>
</head>
<body>
<a href="http://www.w3schools.com">w3schools.com</a>
<a href="http://www.epam.com" target="_blank">epam.com</a>
<a href="http://www.wikipedia.org" target="_top">wikipedia.org</a>
</body><head>
<style>
a[href^='http://www.ep'] {
color: red;
}
</style>
</head>
<body>
<a href="http://www.w3schools.com">w3schools.com</a>
<a href="http://www.epam.com" target="_blank">epam.com</a>
<a href="http://www.wikipedia.org" target="_top">wikipedia.org</a>
</body><head>
<style>
a[href$='.org'] {
color: red;
}
</style>
</head>
<body>
<a href="http://www.w3schools.com">w3schools.com</a>
<a href="http://www.epam.com" target="_blank">epam.com</a>
<a href="http://www.wikipedia.org" target="_top">wikipedia.org</a>
</body><head>
<style>
a[data-lang="en"] {
color: red;
}
</style>
</head>
<body>
<a href="http://www.w3schools.com" data-lang="en" >w3schools.com</a>
<a href="http://www.epam.com">epam.com</a>
<a href="http://www.wikipedia.org" data-lang="en">wikipedia.org</a>
<a href="http://www.google.com">google.com</a>
<a href="http://www.ya.ru">yandex</a>
</body><head>
<style>
span:after{
content: "IM AFTER";
}
span:before{
content: "IM BEFORE";
}
</style>
</head>
<body>
<span>
Simple Text
</span>
</body>
!Свойство content:" " обязательно!
В javascript к псевдоэлементам обратиться нельзя
:first-letter применяется к первой букве элемента селектора
<head>
<style>
p:first-letter{
color:red;
}
</style>
</head>
<body>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
</body>
:first-line применяется к первой линии элемента селектора
<head>
<style>
p:first-line{
color:red;
}
</style>
</head>
<body>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
</body>
:hover активизируется, когда курсор мыши находится в пределах элемента, но щелчка по нему не происходит.
:focus применяется к элементу при получении им фокуса. Например, для текстового поля формы получение фокуса означает, что курсор установлен в поле, и с помощью клавиатуры можно вводить в него текст
<head>
<style>
li{
list-style-type:none;
display:inline-block;
border-left:1px solid red;
padding-left:5px;
}
li:first-child{
border:none;
}
</style>
</head>
<body>
<ul>
<li>Вкладка 1</li>
<li>Вкладка 2</li>
<li>Вкладка 3</li>
<li>Вкладка 4</li>
</ul>
</body>
:first-child применяется к первому дочернему элементу селектора, который расположен в дереве элементов документа.
:last-child применяется к последнему дочернему элементу селектора, который расположен в дереве элементов документа.
<head>
<style>
li{
list-style-type:none;
display:inline-block;
border-right:1px solid blue;
padding-right:5px;
}
li:last-child{
border:none;
}
</style>
</head>
<body>
<ul>
<li>Вкладка 1</li>
<li>Вкладка 2</li>
<li>Вкладка 3</li>
<li>Вкладка 4</li>
</ul>
</body>
:nth-child(n) можно выбрать любой дочерний элемент. Отсчет ведется с 1.
<head>
<style>
tr:nth-child(4){
background:red;
}
</style>
</head>
<body>
<table border="1">
<caption>Таблица размеров обуви</caption>
<tr>
<th>Россия</th>
<th>Великобритания</th>
<th>Европа</th>
<th>Длина ступни, см</th>
</tr>
<tr>
<td>34,5</td><td>3,5</td><td>36</td><td>23</td>
</tr>
<tr>
<td>35,5</td><td>4</td><td>36⅔</td><td>23–23,5</td>
</tr>
<tr>
<td>36</td><td>4,5</td><td>37⅓</td><td>23,5</td>
</tr>
<tr>
<td>36,5</td><td>5</td><td>38</td><td>24</td>
</tr>
<tr>
<td>37</td><td>5,5</td><td>38⅔</td><td>24,5</td>
</tr>
<tr>
<td>38</td><td>6</td><td>39⅓</td><td>25</td>
</tr>
</table>
</body>
:only-child(n) он позволяет вам выбрать элементы, которые являются единственными дочерними
<head>
<style>
div p:only-child{
color:red;
}
</style>
</head>
<body>
<div>
<p> Один параграф.</p>
</div>
<div>
<p> Два параграфа </p>
<p> Два параграфа </p>
</div>
</body>
:not(selector) псевдокласс отрицания помогает исключить тот элемент, который указывается в скобках
<head>
<style>
span:not(.descript) {
color: #666;
}
</style>
</head>
<body>
<span>Text</span>
<span>Text</span>
<span class="descript">Text</span>
<span>Text</span>
<span class="descript">Text</span>
</body>
<!-- HTML -->
<a href="#" class="link" id="generalInfo" style="color:red">Ckick me</a>
/* CSS */
*{
color:gray;
}
a{
color:blue;
}
.link{
color:green;
}
#generalInfo{
color: yellow;
}Определяет их приоритетность в таблице стилей. Чем специфичнее селектор, тем выше его приоритет.
Правила вычисления специфичности селекторов:
1. Самый высокий приоритет имеет атрибут style. Это правило перекрывает все селекторы описанные в стилях.
2. Второе место занимает присутствие #id в селекторе.
3. Далее идут все атрибуты (в том числе и атрибут class) в селекторе (.class).
4. Самый низкий приоритет у селекторов с именами элементов (просто название тега)
h1 {color: red} /* специфичность 0, 0, 0, 1 */
p em {color: purple} /* специфичность 0, 0, 0, 2 */
.grape {color: purple} /* специфичность 0, 0, 1, 0 */
*.grape {color: purple} /* специфичность 0, 0, 1, 0 */
p.bright em.dark {color: red} /* специфичность 0, 0, 2, 2 */
#id234 {color: red} /* специфичность 0, 1, 0, 0 */
h1#id234 em {color: red} /* специфичность 0, 1, 0, 2 */
<a style=“color:green;”> /* специфичность 1, 0, 0, 0 */
<div>
<p>
<span>?</span>
</p>
</div>p span{
color:blue;
}
html span{
color:red;
}
<p>
<span class="text">?</span>
</p>
/* CSS */
span.text{
color:red;
}
p > span{
color:blue;
}
p .text{
color:green;
}<p id="id_1">
<span id="id_2">?</span>
</p>
/* CSS */
#id_1 span{
color:red;
}
#id_2{
color:blue;
}Недостатки !important
- нарушает стандартные правила наследования таблиц стилей. - работа с такой стилевой таблицей (поиск ошибок, модернизация) будет более трудоемкой;
- динамически (с помощью JavaScript) нет возможности переопределить свойство (это можно обойти, если менять не свойство, а класс).
Старайтесь избегать применения правила !important.
имеет приоритет над правилами наследования
Идея семантического HTML и CSS заключается в разделении структуры и стилей. Помните, всегда храните стили в таблицы стилей.
- исключают возможность поменять внешний вид компонента без изменения кода самого компонента
- увеличивают размер итоговой страницы
- если нет доступа к HTML, придется использовать !important
cm - сантиметр
mm - миллиметр
pt - типографская величина =1/72дюйма
px - пиксель
% - процент от другого свойства, какого - зависит от того, размер чего ставим.
em - текущий размер шрифта. В большинстве браузеров шрифт по умолчанию имеет размер 16px
ex - высота символа x
rem - равен значению <html>
! Дробная часть отделяется ТОЧКОЙ
Во всех современных браузерах, исключая IE8-, поддерживаются новые единицы из черновика стандарта CSS Values and Units 3:
vw — 1% ширины окна
vh — 1% высоты окна
vmin — наименьшее из (vw, vh), в IE9 обозначается vm
vmax — наибольшее из (vw, vh)
<div style="font-size: 24px"> 24px
<div style="font-size: 24px"> 24px </div>
</div>Размеры в пикселях — абсолютные.
Они не зависят от того, в каком месте находится элемент:
Размеры в em— относительные.
Они определяются по текущему контексту:
<div style="font-size: 1.5em"> 1.5em
<div style="font-size: 1.5em"> 1.5em </div>
</div>В примере выше первая строчка при настройках браузера по умолчанию равна 16*1.5 = 24px.
А вторая в 1.5 раза больше текущего, уже увеличенного, размера шрифта, т.е. 24*1.5 = 36px.
В двух строчках будет 24px.
Итак, мы знаем, что в настройках браузера по умолчанию размер равен 16px. Это и есть наши 100%.
<div style="font-size: 200%"> будет 32px
<div style="font-size: 200%"> будет 64px </div>
</div>em всегда привязан к шрифту, а % могут зависить и от других свойств, такие как отступы, ширина/высота элемента
Бывают задачи, когда мы хотим сделать на странице большие кнопки «Шрифт больше» и «Шрифт меньше». При нажатии на них будет срабатывать JavaScript, который будет увеличивать или уменьшать шрифт.
<ul>
<li>Собака
<ul>
<li>бывает
<ul>
<li>кусачей
<ul>
<li>только
<ul>
<li>от жизни
<ul>
<li>собачей</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>/* CSS for em*/
li {
font-size: 0.8em;
}/* CSS for rem*/
li {
font-size: 0.8rem;
}font-style (стиль шрифта): italic; normal, oblique
font-weight (насыщенность шрифта): bold; normal; 100-900
font-size (Размер шрифта): px; pt, px, em, %
line-height (Высота строки): px; pt, px, em, %
font-family (Семейство шрифтов): Georgia, serif;}
Краткая запись: font: font-style font-variant font-weight font-size/line-height font-family
Краткая запись: { font: italic bold small-caps 16px/30px Georgia; }
СВОЙСТВА ТЕКСТА:
text-align (Горизонтальное выравнивание ): left, right, center, justify
text-decoration (Оформление): none;
underline - подчеркивает текст (по умолчанию для тегов <a>, <ins> и <u>);
overline - черта сверху текста;
line-through - зачеркивает текст (по умолчанию для тегов <del>, <s> и <strike>);
blink - мигание текста (отсутствует в IE, Chrome)
text-transform (Преобразование регистра ): none; (по умолчанию)
capitalize - преобразует первую букву каждого слова текста в верхний регистр;
uppercase - преобразует все символы текста в верхний регистр;
lowercase - в нижний регистр
word-spacing (Дополнительное расстояние между словами ): px;
letter-spacing (Дополнительное расстояние между буквами): px;
text-indent (Красная строка): px;
background-color: #fff;
background-image: url("image.jpg");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: right bottom; 50px 50px; 25% 25%;
Краткая запись:
background: #fff url("image.gif") no-repeat fixed right bottom;
-webkit-property
-moz-property
-ms-property
-o-property
property
/* CSS */
-webkit-box-sizing: value;
-moz-box-sizing: value;
box-sizing: value;Каждый браузер устанавливает свои значения стилей по умолчанию для различных HTML-элементов. С помощью CSS Reset мы можем нивелировать эту разницу для обеспечения кроссбраузерности стилей.
- Сохраняет полезные стили по умолчанию, в отличие от многих reset проектов
- Нормализует стили для широкого диапазона элементов
- Исправляет ошибки и общие несоответствия браузеров
- Повышает юзабильность
- Хорошо и подробно откомментирован
- Поддерживает мобильные устройства и HTML5
/* style.scss or style.less */
h1 {
color: #ссс;
} $boxColor: #fff; /* цвет */
$margin: 16px; /* отступ */
.content {
border: 1px solid $boxColor; /* наш бордер */
background-color: $boxColor; /* цвет */
}
.leftSide{
padding: $margin / 2;
margin: $margin / 2;
border-color: $boxColor;
}@boxColor: #fff; /* цвет */
@margin: 16px; /* отступ */
.content {
border: 1px solid @boxColor; /* наш бордер */
background-color: @boxColor; /* цвет */
}
.leftSide{
padding: $margin / 2;
margin: $margin / 2;
border-color: @boxColor;
}boxColor = #fff /* цвет */
margin = 16px /* отступ */
.content
border 1px solid @boxColor /* наш бордер */
background-color @boxColor /* цвет */
.leftSide
padding $margin / 2
margin $margin / 2
border-color @boxColor
section {
margin: 10px;
}
section nav {
height: 25px;
}
section nav a {
color: #0982C1;
}
section nav a:hover {
text-decoration: underline;
}Рассмотрим пример кода:
section {
margin: 10px;
nav {
height: 25px;
a { color: #0982C1;
&:hover {
text-decoration:underline;
}
}
}
}
}