0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Создатель Yarn и Babel Себастиан Маккензи (Sebastian McKenzie) долго работал над универсальным инструментом для JavaScript-разработчиков. 26 февраля он представил<a>проект Rome</a>. "Все дороги ведут в Рим", - таков девиз создателей инструмента.</p>
1
<p>Создатель Yarn и Babel Себастиан Маккензи (Sebastian McKenzie) долго работал над универсальным инструментом для JavaScript-разработчиков. 26 февраля он представил<a>проект Rome</a>. "Все дороги ведут в Рим", - таков девиз создателей инструмента.</p>
2
<h2>Содержание</h2>
2
<h2>Содержание</h2>
3
<ul><li><a>Что такое Rome</a></li>
3
<ul><li><a>Что такое Rome</a></li>
4
<li><a>Как это выглядит на практике</a></li>
4
<li><a>Как это выглядит на практике</a></li>
5
<li><a>Почему Rome - перспективный и удобный инструмент?</a></li>
5
<li><a>Почему Rome - перспективный и удобный инструмент?</a></li>
6
<li><a>Как устроена сборка в Rome</a></li>
6
<li><a>Как устроена сборка в Rome</a></li>
7
<li><a>Что у Rome с качеством сборки</a></li>
7
<li><a>Что у Rome с качеством сборки</a></li>
8
<li><a>Перспективы Rome в больших проектах</a></li>
8
<li><a>Перспективы Rome в больших проектах</a></li>
9
<li><a>Сокращение размеров сборки в Rome</a></li>
9
<li><a>Сокращение размеров сборки в Rome</a></li>
10
<li><a>Дальнейшая оптимизация</a></li>
10
<li><a>Дальнейшая оптимизация</a></li>
11
<li><a>Разделение кода в Rome</a></li>
11
<li><a>Разделение кода в Rome</a></li>
12
<li><a>Использование Rome в CLI</a></li>
12
<li><a>Использование Rome в CLI</a></li>
13
</ul><h2>Что такое Rome</h2>
13
</ul><h2>Что такое Rome</h2>
14
<p>Rome - это универсальный набор инструментов для разработки на JavaScript. Он компилирует и собирает JavaScript-проекты, выполняет линтинг и тайп-чекинг, запускает тесты, а также форматирует код.</p>
14
<p>Rome - это универсальный набор инструментов для разработки на JavaScript. Он компилирует и собирает JavaScript-проекты, выполняет линтинг и тайп-чекинг, запускает тесты, а также форматирует код.</p>
15
<h2>Как это выглядит на практике</h2>
15
<h2>Как это выглядит на практике</h2>
16
<p>Создатели представили Rome несколько дней назад. Но в CLI уже есть полезная информация об использовании инструмента. Вот некоторые команды:</p>
16
<p>Создатели представили Rome несколько дней назад. Но в CLI уже есть полезная информация об использовании инструмента. Вот некоторые команды:</p>
17
<ul><li>rome bundle - собирает модули в проекте JavaScript;</li>
17
<ul><li>rome bundle - собирает модули в проекте JavaScript;</li>
18
<li>rome compile - компилирует единый файл;</li>
18
<li>rome compile - компилирует единый файл;</li>
19
<li>rome develop - запускает локальный сервер;</li>
19
<li>rome develop - запускает локальный сервер;</li>
20
<li>rome parse - парсит единый файл и выводит абстрактное синтаксическое дерево;</li>
20
<li>rome parse - парсит единый файл и выводит абстрактное синтаксическое дерево;</li>
21
<li>rome resolve - резолвит файл;</li>
21
<li>rome resolve - резолвит файл;</li>
22
<li>rome analyzeDependencies - анализирует и выводит зависимости.</li>
22
<li>rome analyzeDependencies - анализирует и выводит зависимости.</li>
23
</ul><p>Подробнее об использовании Rome в CLI пойдёт речь ниже.</p>
23
</ul><p>Подробнее об использовании Rome в CLI пойдёт речь ниже.</p>
24
<h2>Почему Rome - перспективный и удобный инструмент?</h2>
24
<h2>Почему Rome - перспективный и удобный инструмент?</h2>
25
<p>Rome можно назвать новым подходом к использованию инструментов для разработки на JavaScript. Он больше похож на универсальные решения, которые применяют в крупных компаниях, чем на опенсорсные инструменты, каждый из которых решает какую-то одну задачу. То есть при использовании Rome разработчик использует только его, а не пропускает код через несколько разных инструментов.</p>
25
<p>Rome можно назвать новым подходом к использованию инструментов для разработки на JavaScript. Он больше похож на универсальные решения, которые применяют в крупных компаниях, чем на опенсорсные инструменты, каждый из которых решает какую-то одну задачу. То есть при использовании Rome разработчик использует только его, а не пропускает код через несколько разных инструментов.</p>
26
<p>Это решает одну из проблем, с которыми сталкиваются разработчики при использовании популярных сборщиков типа Webpack или Rollup. Она заключается в том, что анализ и оптимизация программы становятся слишком "дорогими", так как каждый инструмент независимо от других парсит код и строит своё абстрактное синтаксическое дерево (AST).</p>
26
<p>Это решает одну из проблем, с которыми сталкиваются разработчики при использовании популярных сборщиков типа Webpack или Rollup. Она заключается в том, что анализ и оптимизация программы становятся слишком "дорогими", так как каждый инструмент независимо от других парсит код и строит своё абстрактное синтаксическое дерево (AST).</p>
27
<h2>Как устроена сборка в Rome</h2>
27
<h2>Как устроена сборка в Rome</h2>
28
<p>Архитектуру Rome можно назвать уникальной. Компиляция выполняется помодульно. Это позволяет обрабатывать каждый модуль в пуле рабочих потоков. Это хорошо работает на уровне обработки модулей, но создаёт проблемы на уровне сборки. Чтобы избежать необходимости повторного парсинга модулей, необходимо создавать единое пространство имён. То есть все модули в проекте находятся в одной области видимости.</p>
28
<p>Архитектуру Rome можно назвать уникальной. Компиляция выполняется помодульно. Это позволяет обрабатывать каждый модуль в пуле рабочих потоков. Это хорошо работает на уровне обработки модулей, но создаёт проблемы на уровне сборки. Чтобы избежать необходимости повторного парсинга модулей, необходимо создавать единое пространство имён. То есть все модули в проекте находятся в одной области видимости.</p>
29
<p>Чтобы сделать сборку возможной с учётом помодульной обработки, Rome добавляет префиксы всем переменным в области видимости. Эти префиксы генерируются из названия файлов. Например, переменная foo в модуле test.js превращается в test_js_foo.</p>
29
<p>Чтобы сделать сборку возможной с учётом помодульной обработки, Rome добавляет префиксы всем переменным в области видимости. Эти префиксы генерируются из названия файлов. Например, переменная foo в модуле test.js превращается в test_js_foo.</p>
30
<p>Этот подход применяется к импортируемым и экспортируемым идентификаторам на уровне модулей. Это значит, что при экспорте можно использовать только название файла и идентификатор экспортируемой сущности.</p>
30
<p>Этот подход применяется к импортируемым и экспортируемым идентификаторам на уровне модулей. Это значит, что при экспорте можно использовать только название файла и идентификатор экспортируемой сущности.</p>
31
<p>Например, если имя файла - test.js, экспорт - export const foo = 1;, на выходе получаем const ___R$test_js$foo = 1;. Ещё один пример с именем файла index.js. Импорт выглядит так:</p>
31
<p>Например, если имя файла - test.js, экспорт - export const foo = 1;, на выходе получаем const ___R$test_js$foo = 1;. Ещё один пример с именем файла index.js. Импорт выглядит так:</p>
32
<p>На выходе получаем: console.log(___R$test_js$foo);.</p>
32
<p>На выходе получаем: console.log(___R$test_js$foo);.</p>
33
<h2>Что у Rome с качеством сборки</h2>
33
<h2>Что у Rome с качеством сборки</h2>
34
<p>В современной веб-разработке инструменты определяют качество и размер приложения. Это значит, что разработчики должны обращать внимание на содержание сборок Rome. Автор оригинальной публикации всегда проверяет, будет ли инструмент объединять модули в единое замыкание как Rollup, или сохранит границы модулей с помощью замыканий и рантайм-загрузчиков как Webpack.</p>
34
<p>В современной веб-разработке инструменты определяют качество и размер приложения. Это значит, что разработчики должны обращать внимание на содержание сборок Rome. Автор оригинальной публикации всегда проверяет, будет ли инструмент объединять модули в единое замыкание как Rollup, или сохранит границы модулей с помощью замыканий и рантайм-загрузчиков как Webpack.</p>
35
<p>Rome создаёт сборки с единым замыканием. Это похоже на то, как работает Rollup. Примеры ниже.</p>
35
<p>Rome создаёт сборки с единым замыканием. Это похоже на то, как работает Rollup. Примеры ниже.</p>
36
<p>Модуль:</p>
36
<p>Модуль:</p>
37
<p>Сборка:</p>
37
<p>Сборка:</p>
38
<p>Пока Rome не предлагает инструментов для уменьшения размеров сборки. Однако дополнительное использование<a>плагина Terser</a>улучшает результат.</p>
38
<p>Пока Rome не предлагает инструментов для уменьшения размеров сборки. Однако дополнительное использование<a>плагина Terser</a>улучшает результат.</p>
39
<p>Примеры показывают, что сборки Rome можно серьёзно оптимизировать. В идеале сборщик должен знать режим работы и поддерживать замыкания и директиву strict mode при работе с модулями ES. Он также мог бы поднимать глобальные декларации на уровень модуля.</p>
39
<p>Примеры показывают, что сборки Rome можно серьёзно оптимизировать. В идеале сборщик должен знать режим работы и поддерживать замыкания и директиву strict mode при работе с модулями ES. Он также мог бы поднимать глобальные декларации на уровень модуля.</p>
40
<h2>Перспективы Rome в больших проектах</h2>
40
<h2>Перспективы Rome в больших проектах</h2>
41
<p>Посмотрим на более сложный пример с двумя модулями, в которых есть общие зависимости.</p>
41
<p>Посмотрим на более сложный пример с двумя модулями, в которых есть общие зависимости.</p>
42
<p>entry.tsx:</p>
42
<p>entry.tsx:</p>
43
<p>other.tsx:</p>
43
<p>other.tsx:</p>
44
<p>react.tsx:</p>
44
<p>react.tsx:</p>
45
<p>type VNode = { type: string; props: any; children: Array<VNode|string> }; function createElement( type: string, props: any, ...children: Array<VNode|string> ): VNode { return { type, props, children }; } export default { createElement };</p>
45
<p>type VNode = { type: string; props: any; children: Array<VNode|string> }; function createElement( type: string, props: any, ...children: Array<VNode|string> ): VNode { return { type, props, children }; } export default { createElement };</p>
46
<p>Сборка с помощью rome bundle entry.tsx out генерирует директорию с файлом index.js.</p>
46
<p>Сборка с помощью rome bundle entry.tsx out генерирует директорию с файлом index.js.</p>
47
<p>Пример немного сложнее предыдущего, но структура в нём сохраняется.</p>
47
<p>Пример немного сложнее предыдущего, но структура в нём сохраняется.</p>
48
<p>Без реализации модулей и "мёртвого кода" три исходных модуля превращаются в одно замыкание.</p>
48
<p>Без реализации модулей и "мёртвого кода" три исходных модуля превращаются в одно замыкание.</p>
49
<h2>Сокращение размеров сборки в Rome</h2>
49
<h2>Сокращение размеров сборки в Rome</h2>
50
<p>Как сказано выше, в данный момент в Rome нет инструментов для уменьшения размеров сборки. Можно пропускать полученный результат через Terser. Если сделать это с кодом из примера выше, на выходе получаем следующее (код отформатирован для удобства чтения):</p>
50
<p>Как сказано выше, в данный момент в Rome нет инструментов для уменьшения размеров сборки. Можно пропускать полученный результат через Terser. Если сделать это с кодом из примера выше, на выходе получаем следующее (код отформатирован для удобства чтения):</p>
51
<p>После минимизации результат выглядит довольно хорошо. Надо учитывать, что это очень простое приложение. Результаты работы с реальным приложением могут быть другими.</p>
51
<p>После минимизации результат выглядит довольно хорошо. Надо учитывать, что это очень простое приложение. Результаты работы с реальным приложением могут быть другими.</p>
52
<h2>Дальнейшая оптимизация</h2>
52
<h2>Дальнейшая оптимизация</h2>
53
<p>Автор оригинальной публикации работает над инструментом, который оптимизирует сборки JavaScript. В качестве эксперимента он пропустил созданную с помощью Rome сборку через этот инструмент до обработки с помощью Terser. В итоге получился близкий к идеальному результат: без "мёртвого кода" и функций-обёрток, а также с использованием преимуществ современного синтаксиса JavaScript.</p>
53
<p>Автор оригинальной публикации работает над инструментом, который оптимизирует сборки JavaScript. В качестве эксперимента он пропустил созданную с помощью Rome сборку через этот инструмент до обработки с помощью Terser. В итоге получился близкий к идеальному результат: без "мёртвого кода" и функций-обёрток, а также с использованием преимуществ современного синтаксиса JavaScript.</p>
54
<p>Этот пример кажется перспективным.</p>
54
<p>Этот пример кажется перспективным.</p>
55
<h2>Разделение кода в Rome</h2>
55
<h2>Разделение кода в Rome</h2>
56
<p>Похоже, Rome не поддерживает динамический импорт и разделение кода. Использование import() позволяет импортировать модуль, но он ведёт себя как при статическом импорте. Исходный оператор import() не меняется при сборке, что приводит к ошибке.</p>
56
<p>Похоже, Rome не поддерживает динамический импорт и разделение кода. Использование import() позволяет импортировать модуль, но он ведёт себя как при статическом импорте. Исходный оператор import() не меняется при сборке, что приводит к ошибке.</p>
57
<p>Пока неизвестно, как разделение и фрагментирование кода повлияет на качество сборки. Эффективность этих действий зависит от доступа к переменным, которые попадают в одну сборку из другой.</p>
57
<p>Пока неизвестно, как разделение и фрагментирование кода повлияет на качество сборки. Эффективность этих действий зависит от доступа к переменным, которые попадают в одну сборку из другой.</p>
58
<h2>Использование Rome в CLI</h2>
58
<h2>Использование Rome в CLI</h2>
59
<p>Ниже приводится вывод хелпа Rome в CLI.</p>
59
<p>Ниже приводится вывод хелпа Rome в CLI.</p>
60
<p>$ rome --help Usage: rome [command] [flags] Options --benchmark --benchmark-iterations <num> --collect-markers --cwd <input> --focus <input> --grep <input> --inverse-grep --log-path <input> --logs --log-workers --markers-path <input> --max-diagnostics <num> --no-profile-workers --no-show-all-diagnostics --profile --profile-path <input> --profile-sampling <num> --profile-timeout <num> --rage --rage-path <input> --resolver-mocks --resolver-scale <num> --silent --temporary-daemon --verbose --verbose-diagnostics --watch Code Quality Commands ci install dependencies, run lint and tests lint run lint against a set of files test run tests --no-coverage --show-all-coverage --update-snapshots Internal Commands evict evict a file from the memory cache logs rage Process Management Commands restart restart daemon start start daemon (if none running) status get the current daemon status stop stop a running daemon if one exists web Project Management Commands config publish TODO run TODO Source Code Commands analyzeDependencies analyze and dump the dependencies of a file --compact --focus-source <input> bundle build a standalone js bundle for a package compile compile a single file --bundle develop start a web server --port <num> parse parse a single file and dump its ast --no-compact --show-despite-diagnostics resolve resolve a file</p>
60
<p>$ rome --help Usage: rome [command] [flags] Options --benchmark --benchmark-iterations <num> --collect-markers --cwd <input> --focus <input> --grep <input> --inverse-grep --log-path <input> --logs --log-workers --markers-path <input> --max-diagnostics <num> --no-profile-workers --no-show-all-diagnostics --profile --profile-path <input> --profile-sampling <num> --profile-timeout <num> --rage --rage-path <input> --resolver-mocks --resolver-scale <num> --silent --temporary-daemon --verbose --verbose-diagnostics --watch Code Quality Commands ci install dependencies, run lint and tests lint run lint against a set of files test run tests --no-coverage --show-all-coverage --update-snapshots Internal Commands evict evict a file from the memory cache logs rage Process Management Commands restart restart daemon start start daemon (if none running) status get the current daemon status stop stop a running daemon if one exists web Project Management Commands config publish TODO run TODO Source Code Commands analyzeDependencies analyze and dump the dependencies of a file --compact --focus-source <input> bundle build a standalone js bundle for a package compile compile a single file --bundle develop start a web server --port <num> parse parse a single file and dump its ast --no-compact --show-despite-diagnostics resolve resolve a file</p>
61
<p><em>Адаптированный перевод статьи<a>Rome, a new JavaScript Toolchain</a>by Jason Miller. Мнение автора оригинальной публикации может не совпадать с мнением администрации Хекслета.</em></p>
61
<p><em>Адаптированный перевод статьи<a>Rome, a new JavaScript Toolchain</a>by Jason Miller. Мнение автора оригинальной публикации может не совпадать с мнением администрации Хекслета.</em></p>