
Для чего
Parcel — маленький и быстрый бандлер, позиционируется как решение для маленьких проектов. С момента первого релиза (7 дней назад) уже собрал 8725 звездочек на гитхабе. Согласно официальной документации имеет следующие плюсы:
Быстрая сборка
Parcel использует worker process для многопоточной сборки, а так же имеет свой файловый кэш для быстрой пересборки при последующих изменениях.
Собирает все ваши ассеты
Из коробки имеется поддержка ES6, TypeScript, CoffeeScript, HTML, SCSS, Stylus, raw-файлов. Плагины не требуются.
Автоматические преобразования
Весь код автоматически проходит через Babel, PostCSS, PostHTML — подхватываются при необходимости из node_modules.
️ Разделение кода без лишней конфигурации
Используя динамический import(), Parcel разделяет бандл для возможности быстрой начальной загрузки точки входа в приложение
Горячая перезагрузка
Типичный хот-релоад без конфигурации — сохраняете изменения и они автоматически применяются в браузере.
Дружелюбный вывод ошибок
При ошибке подсвечивается кусок кода, в котором она произошла.
Так же на главной странице приводится бенчмарк:
| Bundler | Time |
|---|---|
| browserify | 22.98s |
| webpack | 20.71s |
| parcel | 9.98s |
| parcel — with cache | 2.64s |
Механика работы
Подход Parcel схож с оным у Webpack (тут сложно придумать что-то новое).
У нас есть сущность — Asset. Ассет — это любой файл. Механика работы такова: реализуется интерфейс, который предоставляет логику для превращения файла в AST, разрешения всех зависимостей, применения нужных трансформаций и генерирования итогового кода. Если вас не устраивает работа какого-то ассета из коробки или вы хотите добавить свой — нет ничего сложного.
Дальше в дело вступает Packager. Упаковщик склеивает ассеты в итоговый бандл. Это происходит после обработки и успешного построения дерева. Упаковщики регистрируются на основе типа файлов. Хотите написать свой упаковщик? Вам сюда.
Так же мы можем писать свои плагины, которые Parcel будет подхватывать из package.json. Для этого у названия пакета плагина должен быть префикс parcel-plugin-. Но это уже совсем частный случай, который скорее всего уже ведет к тому, что надо переключаться на webpack или другой удобный инструмент.
На практике
Ставим пакет, инициализируем приложение через любой пакетный менеджер:
$ yarn global add parcel-bundler $ mkdir parcel-test && cd parcel-test $ yarn init -y
Для примера напишем hello world на Preact. Создадим следующую структуру:
parcel-test ├── package.json ├── src │ ├── app.jsx │ ├── components │ │ └── clock │ │ └── Clock.jsx │ └── index.html └── yarn.lock 3 directories, 5 files
А так же установим необходимые пакеты:
$ yarn add preact babel-plugin-transform-react-jsx postcss-modules autoprefixer
Для того, чтобы сконфигурировать Babel создадим .babelrc со следующим содержанием:
{ "plugins": [ ["transform-react-jsx", { "pragma":"h" }] ] }
Для PostCSS:
{ "modules": true, "plugins": { "autoprefixer": {} } }
Для autoprefixer:
> 1% last 2 versions
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Parcel demo</title> </head> <body> <script src="./App.jsx"></script> </body> </html>
App.jsx
import { h, render } from 'preact'; import { Clock } from './components/clock/Clock'; render(( <div> <h1>It works!</h1> <Clock /> </div> ), document.body);
Clock.jsx
import { h, Component } from 'preact'; import styles from './Clock.css'; export class Clock extends Component { constructor() { super(); this.state = { time: Date.now() }; } componentDidMount() { this.timer = setInterval(() => this.setState({ time: Date.now() }), 1000); } componentWillUnmount() { cleanInterval(this.timer); } render(props, state) { let time = new Date(state.time).toLocaleTimeString(); return <span className={styles.clock}>{ time }</span> } }
Clock.css
.clock { color: green; }

И это все. Как можно заметить, мы не потратили ни минуты на написание конфигурационных файлов, за исключением .babelrc и .postcssrc
Подводя некий итог
Перед нами эдакий "Webpack на минималках", предоставляющий возможность быстрого развертывания рабочего окружения для небольшого проекта. Стек технологий по сути ограничен лишь стандартным набором ассетов, но в любой момент его можно расширить и своими собственными. С учетом полной поддержки Babel мы легко можем использовать практически любой другой фреймворк или библиотеку (разве что с Angular будут сложности, ведь писать с его помощью на ES6 и без родного инструментария — задача на любителя), а поддержка PostCSS из коробки является еще одним приятным дополнением.
Из неудобств я пока что могу отметить только одно — при работе с TypeScript бандлер не учитывает пользовательские пути и базовый каталог (секции baseUrl и paths), указанные в файле tsconfig, и, соответственно, не может нормально разрешать пути импортируемых модулей. На гитхабе идет обсуждение решения этой проблемы.
