Для чего


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
¦   ¦   L-- clock
¦   ¦       L-- Clock.jsx
¦   L-- index.html
L-- 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, и, соответственно, не может нормально разрешать пути импортируемых модулей. На гитхабе идет обсуждение решения этой проблемы.

Комментарии (49)


  1. vlreshet
    12.12.2017 14:32

    Уже который раз есть желание изучить все эти бандлеры, и каждый раз втыкаюсь в одни и те же 2 проблемы:

    1. Во всех уроках/инструкциях/древних манускриптах есть строка типа «теперь просто ставим babel-plugin-transform-react-jsx postcss-modules autoprefixer something-fucking-js one-more-plugin againreactcssjsbullshit, и всё работает!». Но никто и нигде не говорит откуда брать эти списки модулей? Откуда вы их взяли? Что за postcss? Откуда новичку знать что нужно поставить а что нет? Где почитать об этих десятках модулей которые ставят для hello world на vuejs? Просто набор магии «напишите вот так и будет работать»

    2. Потом так же «легко и быстро» пишут по 10 конфигов для всего на свете. Такое ощущение что в мире js ничего не имеет конфигов по умолчанию, нельзя просто сделать install и запустить всё на стандартных настройках (как в том же composer на php, где можно воообще без конфигурирования поднять hello world за 3 команды). Или другая крайность — «сделайте вот так, и мы всё сами скомпилим, запихнём вам в html, и будет вам счастье». А где оно появится в моём html, почему, как это можно изменить — непонятно.

    И в этом плане Parcel не выглядит чем-то сильно удобнее. Всё те же конфиги (у каждого свои), магия расположения папок, и необходимость несколько дней курить документацию для того чтобы сделать всё осознанно а не тупо скопировать команды как обезьяна. В этом плане js уходит в какую-то тёмную степь, в том же java я за пару часов понял как поставить, запустить, и поправить проект с maven, имея околонулевый опыт в java.

    P.S. Ох и выхвачу сейчас минусов, всё же «элементарно и понятно»


    1. xxxTy3uKxxx Автор
      12.12.2017 14:43

      Давайте по порядку.


      Откуда вы их взяли?

      Из официальной документации и, самое главное, из документации Babel и PostCSS. Знаете как использовать — используйте. Не знаете — почитайте, попробуйте. Никто же не заставляет :)


      Такое ощущение что в мире js ничего не имеет конфигов по умолчанию, нельзя просто сделать install и запустить всё на стандартных настройках

      Можно, больше Вам скажу — на главной странице пример, который не требует ни одного конфига для Babel или PostCSS. Если они Вам не нужны — не пишите. Тут сыграло роль то, что статья носит чисто информативный характер, и если в нее вставить еще более простой пример, то Вы никак не увидите его главный плюс, заключающийся в отсутствии необходимости писать даже маленький сферический webpack.config.js


      И в этом плане Parcel не выглядит чем-то сильно удобнее. Всё те же конфиги (у каждого свои), магия расположения папок, и необходимость несколько дней курить документацию для того чтобы сделать всё осознанно а не тупо скопировать команды как обезьяна.

      Так в статье нет ни одного конфига для самого Parcel :)


      1. vlreshet
        12.12.2017 15:20
        +1

        Открываем parceljs.org. Первая страница:

        Видим:
        image


        1. xxxTy3uKxxx Автор
          12.12.2017 15:31

          Хотите LESS — импортируйте .less файл и он добавится в бандл. Хотите VueJS — импортируйте в бандл. Суть в том, что вы скармливаете в Parcel некую точку входа. Он начинает анализировать ее вглубь, строя дерево зависимостей. Поэтому, если в ваш импорт попадает тот или иной файл — он оказывается в итоговом бандле.
          Возможно, я слишком вскользь упомянул это в данном абзаце:


          У нас есть сущность — Asset. Ассет — это любой файл. Механика работы такова: реализуется интерфейс, который предоставляет логику для превращения файла в AST, разрешения всех зависимостей, применения нужных трансформаций и генерирования итогового кода.

          CSS не нужно тянуть через JS, Вы можете импортировать его через другой CSS файл, подключить в HTML или, опять же, в JS. Пример использовал так называемые CSS Modules для наглядной демонстрации того, что в вебпаке потребовало бы конфигурации.


          Свой сервер вы можете поднять, насколько я знаю, если хотите — я могу найти, как это сделать. Но опять же, я не предполагал, что к данному инструменту возниктнет так много базовых вопросов, ведь это обзорная статья, а не туториал.


          Подводя итог — попробуйте создать обычный HTML, подключить в нем SCSS в теге <style> и свой JS-файл в теге <script>, в котором докиньте Vue и запустите команду parcel index.html. И все, никаких CSSinJS и прочего.


          1. vlreshet
            12.12.2017 15:43
            +1

            Спасибо за развёрнутый ответ! Теперь всё стало чуточку понятнее и parcel кажется действительно более удобным чем тот же webpack)

            P.S. это не сарказм, реально спасибо.


            1. xxxTy3uKxxx Автор
              12.12.2017 15:47

              Не за что, рад что стало немного яснее :) Надо вынести в статью информацию о том, как происходит разрешение зависимостей.


              1. vlreshet
                13.12.2017 19:32

                Разобрался более подробно, затестил, забираю обратно свои слова:

                И в этом плане Parcel не выглядит чем-то сильно удобнее.

                Parcel — офигенская штука. Да, сейчас не всё работает, но судя по баг трекеру на гитхабе — прогресс идёт, надеюсь в будущем придёт и бОльшая популярность. Главное чтобы проект не забросили.

                P.S. а не работают пока-что однофайловые .vue компоненты, так и не нашёл способа их запустить.


                1. xxxTy3uKxxx Автор
                  13.12.2017 21:08

                  Есть плагин
                  Сейчас сам пишу плагин для Pug. Кода немного, раздумываю, стоит ли написать ради этого статью с объяснением работы.


            1. kahi4
              12.12.2017 17:28

              Ну базовая механика в нем ровно такая же как в вебпаке, удобство только для старта, но всегда есть yeoman. Почти уверен что для более-менее сложной конфигурации если он и позволит настроить так же гибко как вебпак, то будет выглядеть не менее монструозно. А вот скорость работы действительно радует, даже интересно насколько это правда (думаю, что на больших проектах не очень банально по той причине, что скорость компилирования бейбеля не зависит от сборщика, а кеш и в вебпак завезли).


              1. xxxTy3uKxxx Автор
                12.12.2017 17:53

                Согласен, но тут конечно вся прелесть в том, что инструмент из разряда «поставил, нажал, заработало». Примерно так же многий софт под macOS позиционируется :) Данный принцип здорово подходит, когда тебе не нужно искать шаблон для yeoman (или писать свой), а просто надо в полпинка запустить окружение и делать разные клевые штуки. Возможности вебпака больше, это бесспорный факт.


                1. kahi4
                  12.12.2017 18:27

                  Данный принцип здорово подходит, когда тебе не нужно искать шаблон для yeoman (или писать свой), а просто надо в полпинка запустить окружение и делать разные клевые штуки.

                  Да, тут не поспоришь. Хоть я и в состоянии написать сколь угодно громоздкий конфиг вебпака, всегда когда нужно быстро на коленках собрать и проверить mvp один и тот же геморрой с boilerplate, которые частично не работают/слишком переусложнены/устарели и прочее.


                  Глубоко не копал, но все же — вот у меня есть тесты на карме, которые в кармаконфиге инклудят конфиг вебпака. Можно это завести тут и как вообще в parcel дела с тестами обстоят?


                  1. xxxTy3uKxxx Автор
                    12.12.2017 18:39

                    В официальной документации на этот счет ничего нет, поэтому скорее всего по старинке, ручным запуском команды. Но можно копнуть в сторону запуска Parcel через его экземпляр, как показано в этом примере внизу


                    1. kahi4
                      12.12.2017 18:42

                      Да проблема не в том, как запустить тест через Parcel, а как к карме подцепить конфиг парселя, чтобы файлы корректно парсились, например, импорт svg.


                      1. xxxTy3uKxxx Автор
                        12.12.2017 20:23

                        Думаю можно попробовать через инстанс бандлера провернуть


                        const Bundler = require('parcel-bundler');
                        let bundler = new Bundler('src/App.js');

                        Надо проверить в бою


          1. ZoNT
            12.12.2017 18:16

            Я уже попробовал: по-умолчанию бандл собирается в папку dist. В итоговом html (который тоже лежит в папке dist) прописаны пути вида \dist\index.js. То есть нельзя просто собрать билд и выложить его из папки dist на сервер.
            Как это вообще можно настроить в parcel — непонятно: вроде есть ключ --public-url, но он работает некорректно.


            1. xxxTy3uKxxx Автор
              12.12.2017 20:23

              Здесь посмотрите :)


              1. ZoNT
                14.12.2017 09:43

                Как будто я не прочёл всю доку перед использованием…
                Пришлось форкнуть и внести изменения под свой проект.


                1. xxxTy3uKxxx Автор
                  14.12.2017 13:47

                  Я не знаю, зачем и что Вы форкали, потому что команда


                  parcel build src/content.pug -d build/ --public-url ./

                  генерирует такой вывод:


                  <html><head><link rel="stylesheet" href="4a0e5b1da5011b82b932acfe8650e4a8.css"></head><body><h1>Test extends</h1><script src="4a0e5b1da5011b82b932acfe8650e4a8.js"></script></body></html>


                  1. ZoNT
                    14.12.2017 17:03

                    А теперь с той же командой запустите девелоп-сервер, положите в папку dist любой json и попробуйте загрузить его XHR-ом.


                    1. ZoNT
                      14.12.2017 17:08

                      В общем вариант такой: либо нормально работает сборка и не работает dev, либо работает dev, но корень сервера определяется неправильно (не относительно папки dist)


    1. superconductor
      13.12.2017 18:54

      Так в 2017 для настройки всего этого специальный человек нужен — frontend build engineer.
      А фронтендер — пишет компоненты на реакте.
      Но ничего не верстает, для этого тоже отдельный человек.


  1. Tihon_V
    12.12.2017 17:14

    Т. е. Parcel позволяет использовать любые типы файлов в качестве assets и при этом не требует отдельной конфигурации для нового типа (только запуск в директории с исходниками и index.html)?

    На мой взгляд теряется смысл различных связках boilerplate + webpack…


    1. xxxTy3uKxxx Автор
      12.12.2017 17:30

      Для типов, которые он не знает надо писать интерфейс для преобразования. А те, что знает — да, из коробки все без конфигов. Это покрывает многие мелкие проекты и задачи на 100%, как мне кажется


  1. RubaXa
    12.12.2017 17:22

    Всё правильно vlreshet говорит, вечные конфиги, rc-шки, соглашения и другие тайные занания. Почему никто не задумывается о another-awesome-bundler init, который бы сам задетектил jsx, ts, less/sass/postcss и сконфигурил бы как надо? Хочешь продвинутой конфигурации, не вопрос another-awesome-bundler eject, create-xxxx-app ведь создали, тут-то что мешает?


    1. xxxTy3uKxxx Автор
      12.12.2017 17:35

      Я думаю дело в том, что комплексные и сложные проекты проще поддерживать, имея свой конфиг. Его можно вертеть и так, и эдак, кидать лоадеры и плагины из гитхаба (форки с доработками, например) и так далее по списку. Посмотрите репозитории angular-cli, react-create-app и их аналоги — все просят дать возможность расширять коробочные конфиги и так далее


  1. Vampireos
    12.12.2017 18:16

    vampireos@home:~/parcel-test$ parcel index.html
    parcel: команда не найдена


    эм… как так та?) Ведь всё установилось же
    vampireos@home:~$ yarn global add parcel-bundler
    yarn global v1.3.2
    [1/4] Resolving packages...
    [2/4] Fetching packages...
    info fsevents@1.1.3: The platform "linux" is incompatible with this module.
    info "fsevents@1.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
    [3/4] Linking dependencies...
    [4/4] Building fresh packages...
    success Installed "parcel-bundler@1.2.0" with binaries:
          - parcel
    Done in 12.12s.

    или ему очень нужна эта штука info fsevents@1.1.3: The platform «linux» is incompatible with this module.


    1. xxxTy3uKxxx Автор
      12.12.2017 18:17

      Судя по логу ярна — все в порядке. У Вас корректно выставлена переменная PATH?


    1. Tihon_V
      12.12.2017 18:45

      Нужен вывод yarn config list и export | grep " PATH=".


      1. Vampireos
        12.12.2017 19:13

        vampireos@home:~/parcel-test$  yarn config list
        yarn config v1.3.2
        info yarn config
        { 'version-tag-prefix': 'v',
          'version-git-tag': true,
          'version-git-sign': false,
          'version-git-message': 'v%s',
          'init-version': '1.0.0',
          'init-license': 'MIT',
          'save-prefix': '^',
          'ignore-scripts': false,
          'ignore-optional': false,
          registry: 'https://registry.yarnpkg.com',
          'strict-ssl': true,
          'user-agent': 'yarn/1.3.2 npm/? node/v6.11.4 linux x64',
          lastUpdateCheck: 1513089669001 }
        info npm config
        { prefix: '/home/vampireos/.npm-global' }
        Done in 0.05s.
        


        vampireos@home:~/parcel-test$ export | grep " PATH="
        declare -x PATH="/home/vampireos/.npm-global/bin:/home/vampireos/.npm-global/bin:/home/vampireos/.npm-global/bin:/home/vampireos/.npm-global/bin:/home/vampireos/.npm-global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:yarn global v1.3.2
        


        1. xxxTy3uKxxx Автор
          12.12.2017 20:25

          Ну собственно не видно у Вас в PATH пути до глобальных модулей, установленных через yarn


    1. vintage
      16.12.2017 19:01

      yarn add parcel-bundler
      yarn parcel index.html

      Ставить что-то глобально — дурной тон.


  1. pletinsky
    12.12.2017 18:36

    А через gulp его можно легко запустить?


    1. xxxTy3uKxxx Автор
      12.12.2017 18:50

      Внедрить в цепочку пайпов нельзя, но можно просто подклбчить как модуль и вызвать на нужный файл


  1. aamonster
    13.12.2017 09:43

    Простите, я с наивным вопросом: а почему инструменты для работы с JS тоже пишут на JS? Ведь это тянет за собой кучу проблем, которые приходится как-то решать ("использует worker process для многопоточной сборки" — весьма жирный намёк).
    Неужели только желание оставаться в рамках одного языка?


    Я понимаю ограничения в браузере — на юзерском компе что-то другое не вдруг выполнишь. Понимаю на сервере (хотя там другие скриптовые языки тоже используются). Но почему инструменты разработки делаются на том же языке?


    P.S. В принципе, эта картина характерна не только для JS, но для него особенно заметна.


    1. vlreshet
      13.12.2017 10:13

      Возможно потому что так банально проще. Пример — какой-то модуль возвращает набор своих методов/классов, и js, естественно, спокойно этим манипулирует. В случае использования другого языка возникнет проблема понимания и разбора js, для взаимодействия с ним. Лишний труд.


    1. justboris
      13.12.2017 10:54

      "использует worker process для многопоточной сборки" — весьма жирный намёк

      Намек не очень понятный. Что именно здесь не так?


      1. aamonster
        13.12.2017 12:33

        Никакого "не так" здесь нет. Напротив, очень правильное решение.
        Но многопоточность — не конёк JS (и это, в общем-то, нормально для его ниши и понятно в условиях ограничений, накладываемых браузером). В других языках она поудобнее, имеет больше возможностей, не имеет таких пенальти по быстродействию (обычно ценой меньшей безопасности — что приемлемо в данном случае).


        1. justboris
          13.12.2017 19:08

          В других языках она поудобнее, имеет больше возможностей

          Вот это очень спорное утверждение. Не вижу каких-то киллер-фишек, ради которых нужно тащить другой язык.


          Зато есть анти-пример. По историческим причинам, node-gyp, использующийся для сборки нативных модулей, зависит от python, что причиняет немало трудностей при запуске в контейнерах и других минималистичных окружениях.


          Гораздо удобнее работать, когда все написано на едином языке и ничего лишнего ставить не надо, кроме движка для этого языка.


          1. aamonster
            13.12.2017 21:36

            Текстовый редактор у вас написан на JS? Оконный менеджер? Операционная система?
            Ну, вы поняли: когда речь идёт не о части вашего кода, а об инструменте для работы с этим кодом — удобнее уже собранный бинарник, и язык, на котором написаны его исходники, неважен.


            1. justboris
              13.12.2017 21:38

              К системе сборки приходится чаще писать плагины и обертки, чем к оконному менеджеру.


              Поэтому исходники на знакомом языке и дружелюбное API на JS лишними не будут.


            1. ZoNT
              14.12.2017 09:48

              Текстовый редактор у меня написан на js: github.com/Microsoft/vscode


            1. Tsimur_S
              16.12.2017 12:44

              хочется просто набрать npm i и что бы все заработало а не возится с поиском бинарника. node-sass который использует бинарный libsass не всегда выкачивает готовый бинарник под платформу а начинает собираться на компе пользователя и тут начинается — скачай python, скачай visual studio и тд тп.


  1. denisromanenko
    13.12.2017 12:35

    Brunch.io гораздо проще и удобнее.


    1. xxxTy3uKxxx Автор
      13.12.2017 12:36

      Проще чем так же поставить пакет и запустить?


  1. jesprider
    15.12.2017 14:51

    В целом для простых проектов я думаю, что парсель — долгожданный продукт. Я правда ещё не пробовал, но если бы я захотел сейчас переходить на парсель с вебпака, то сразу возникает несколько вопросов:

    1. Работаю с vue компонентами, парсель пока не поддерживает. Впрочем должно быть скоро имплементировано (https://github.com/parcel-bundler/parcel/issues/5). Но вопрос больше глобальный, как работать с фреймворком «х», если он требует дополнительного парсинга? И если начать поддерживать все фреймворки, то останется ли он таким быстрым? Или же нужно будет опять-таки конфигурировать?

    2. Я не увидел из доументации, что там с хэшами для js и css файлов? Добавляет ли он их автоматически. Зачастую бывает необходимо выгрузить хэши в json, чтобы потом бэкенд мог из использовать.

    3. Можно ли использовать алиасы и дополнительные плюшки, как то `webpack.DefinePlugin`.

    4. Уверен, что для определённых юзкейсов размер сборки будет не оптимальным. Как дебажить и оптимизировать (a-la `webpack-bundle-analyzer`)?


    1. xxxTy3uKxxx Автор
      16.12.2017 13:10

      1) JS он отдает бабелу, а там через плагины можно обвязку сделать
      2) Автоматически создает хэши и кладет файл sha.json со всеми хэшами
      3) Можно использовать алиасы в бабеле, опять же
      4) Пока такого нет, но думаю сделают :)


      1. jesprider
        16.12.2017 15:50

        Спасибо за ответ. Но не слишком ли много они ставят на бабел? По большому счёту уже сейчас можно начинать отправлять es6 модули. Тогда некоторые вопросы всё ещё актуальны.

        На самом деле я не пытаюсь разразить жаркую дискуссию, и даже тот факт, что моя компания инвестирует в вебпак тут не при чём :) Просто мыслю вслух могу ли я в своём проекте перейти на парсель. Ответ: пока нет. Слишком много надо будет кастомного допиливать пока. Обязательно буду следить за развитием проекта.


        1. xxxTy3uKxxx Автор
          16.12.2017 16:24

          Я предполагаю, что решение сделать основную ставку на бабел (или постцсс) — это отличный способ избавится от своих собственных конфигов. По поводу вебпака — он его не заменит, только на простых проектах. Да и у него нет такой цели :)


          1. jesprider
            16.12.2017 18:27

            Согласен. Хотя такое чувство, что вебпак воспринял появление парселя близко к сердцу: twitter.com/TheLarkInn/status/941568697272958976.