Для чего
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, и, соответственно, не может нормально разрешать пути импортируемых модулей. На гитхабе идет обсуждение решения этой проблемы.
Автор: xxxTy3uKxxx