В эту пятницу на Хабре я прочитал вводную статью про Nuxt.js, но в комментариях резюмировали, что маловато будет. Так случилось, что мы в Voximplant используем эту штуку и она приносит большую пользу. Под катом я расскажу про «киллер фичу» этого микро-фреймворка и где он может пригодиться.


Что такое Nuxt.js? Кратко и для программеров


Это надстройка над Webpack. Все, что делает Nuxt — это конфигурирует Webpack таким образом, что тот ищет определенные файлы в определенных директориях, использует преконфигурированные библиотеки и собирает одностраничное приложение.

Зачем это нужно, если можно взять «голый» Vue.js, «голый» Webpack, написать несколько строчек конфигурации и на выходе тоже получить одностраничное приложение? По той простой причине, что на выходе мы не получим никакого приложения. Мы получим здоровый кусок JavaScript, который, если его каким-то образом добавить в веб страницу, создаст там интерфейс с помощью Vue. Откуда берется эта страница, как туда попадет JavaScript — это нам нужно будет делать самим. А еще нам нужно будет конфигурировать работу с картинками и css, добавлять и настраивать роутер, что-нибудь для управления состоянием и так далее. В общем, не на пару минут задача.

Nuxt делает за нас довольно много. Достаточно поместить в директорию «pages» файл «index.vue» с компонентом — и у нас готово одностраничное приложение. Которое можно запустить в отладочном режиме командой «nuxt» и открыть на «localhost». Почти то же самое может «голый» Vue с Webpack, но даже в таком минимальном примере Nuxt уже начинает помогать нам «под капотом»: из коробки включен Hot Reloading, для страниц настроены кодировки, заголовки и все прочее.

Полезные мелочи


Отладочное «Hello world» на Nuxt мало отличается от него же на «голом» Vue плюс Webpack. Польза увеличивается по мере того, как проект перестает быть hello world и обрастает страницами с кодом. Все, что делает Nuxt, можно самому реализовать в несколько строк, но несколько десятков раз по нескольку строк кода, плюс отладка — это не так мало времени, как кажется. Какую пользу приносит Nuxt:

1. Routing


В проекте уже настроен vue-router, все что нужно — это поместить .vue-файлы в корневую директорю проекта. Каждый файл будет доступен в дев сервере по url, соответствующему его имени, то есть «pages/foo.vue» будет отдаваться как «localhost:3000/foo». Для прода, как и положено с vue-router, все это превратится либо в хеши, либо нужно будет настроить сервер отдавать приложение с любого url.

Из коробки поддерживаются динамические пути: поддиректории и файлы, начинающиеся с подчеркивания, будут обслуживать страницы с любыми строками вместо подчеркнутых элементов, а значение этих строк будут переданы компонентам. Например, компонент «pages/objects/_id.vue» будет отображать и «localhost/objects/100» и «localhost/objects/bar». Что именно отображается, доступно внутри компонента через $route.params, это делает vue-router. А Nuxt добавляет еще метод validate, с помощью которого компонент может проверить валидность переданного ему пути.

2. Работа со статикой


Nuxt конфигурирует Webpack искать изображения и другую статику в корневой директории «assets» и во время сборки складывает в специальную директорию "_nuxt", откуда это все будет забирать веб-страница. Из кода статика доступна с помощью альяса "~assets", Nuxt конфигурирует Webpack, чтобы "~" указывало на корень проекта.

3. Работа с мета-информацией


Создаваемые Nuxt HTML-страницы полностью конфигурируемы разработчиком: с помощью nuxt.config.js можно задать название страницы, мета информацию, подключить дополнительные стили, шрифты и так далее. Удобно, что это все делается в одну строку кода:


4. ES2017 из коробки


Одна из фичей Vue — возможность использовать «single file components» с почти любыми языками для шаблона, стилей и кода. Обычно я использую PUG для рисования HTML, Stylus для модульных стилей (да, как старый питонист я люблю отступы) и TypeScript для кода. В проекте Nuxt это точно так же настраивается, но JavaScript «из коробки» транспайлится с помощью Babel из синтаксиса ES2017. Что очень удобно для большинства мелких задач.

И, наконец, киллер фича


Все описанное выше не тянет на использование еще одной технологии. По-хорошему, это вопрос собственного шаблона для vue-cli с теми настройками Webpack и структурой папок, которые вы предпочитаете. Но есть у Nuxt одна фишка, которая делает его использование более чем целесообразным. Встречайте: nuxt generate!

Эта команда делает Server Side Rendering «из коробки». После ее выполнения мы получим директорию «dist», в который будут лежать «index.html» и та самая директория "_nuxt" со сгенерированными изображениями, css, джаваскриптом — в общем, всем тем, что нужно для нашего сайта. И это все статика. То есть можно раздавать с CDN или выкладывать на GitHub Pages.

Server Side Rendering — непростая в конфигурировании штука. В отличие от мелких удобств, которые предлагает Nuxt, правильно настроить SSR – это вопрос отнюдь не одного часа. А Webpack простой только для простых проектов, SSR к таким не относится. Nuxt делает все за нас — правильные настройки, правильные плагины, разбиение кода на подгружаемые модули и много всего еще. HTML-страница со стилями и изображениями грузится с CDN очень быстро, после чего неторопливо забирает JavaScript и выполяет его. При выполнении кода происходит процесс «дегидрации»: Vue, построив в памяти дерево компонентов, изучает имеющийся DOM из HTML, видит, что тот соответствует имеющимся компонентам, ничего не меняет и приложение просто «оживает». Как раз за те одну-две секунды, которые нужны пользователю, чтобы захотеть куда-то кликнуть.

Где применим Nuxt


Мы используем его для быстрого прототипизирования интерфейсов: вообще, ничего лишнего, настроенный Hot Reloading, результаты можно за несколько секунд переложить в GitLab Pages (у нас локальный GitLab с CI, очень удобно) и кому-нибудь показать.

Nuxt очень хорош для страниц проектов на GitHub и GitLab — в отличие от Jekyll и других статических генераторов вы используете полноценный фреймворк Vue, у вас есть JavaScript, роутинг — можете хоть аналог Photoshop сделать и раздавать его с GitHub Pages или CloudFlare.

Сами авторы намекают, что Nuxt можно использовать для ускорения проектов, где чтение информации более часто, чем ее изменение. Возьмем, к примеру, главную Хабра. Ее можно генерировать Nuxt и отдавать мгновенно. А в фоне постоянно пересобирать статику, чтобы раз в несколько секунд обновлялись статьи, комментарии и прочая «динамическая» информация. Nuxt позволяет сконфиругировать генератор статики для динамических путей: вы отгружаете ему список элементов, а он создает столько отдельных html-файлов, сколько нужно. Да, статика для интерент-магазина с миллионом товаров будет генериться полчаса. Но ведь и товары добавляются туда не каждую минуту! Зато страницы будут отдаваться мгновенно. Любому количеству пользователей, если использовать CDN. Ситуация «сервер не справился с нагрузкой» просто перестанет быть. Ну, за исключением backend, конечно. Но там своя атмосфера.

Картинка для привлечения внимания взята с сайта vitaminius.ru

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


  1. oENDark
    04.09.2017 13:07
    +3

    К великому сожалению, ваша статья ничем не отличается от общедоступного руководства по nuxt / vue ssr.

    Повторюсь. Интересны примеры кода для решения конкретных задач. Тесты при нагрузке, проблемы и их решения.

    Складывается ощущение, что все кто так или иначе связан с vue не хочется или не может делится информацией.


    1. eyeofhell Автор
      04.09.2017 13:22

      Мы про прототипы. Как статика ведет себя под нагрузкой на CDN — это, наверное, к cloudflare вопрос? Или к CDNVideo?


  1. keslo
    04.09.2017 13:59

    Так понял, что Nuxt.js изначально направлен на работу с vue.js.
    Вы активно используете vue.js? И используете ли у себя Angular и React с кучей навесного?


    1. eyeofhell Автор
      04.09.2017 16:26

      Внутри у нас React для прода и Vue.js активно изучаем как его потенциальную замену


  1. dagen
    04.09.2017 16:26

    Из статьи появилось ощущение, что под SSR автор имеет ввиду генерацию статических страниц? Есть ли поддержка собственно универсальных/изоморфных приложений?


    1. eyeofhell Автор
      04.09.2017 16:27

      Изоморфная — это же статическая, которая на клиенте с помощью дегидрации оживает? Или нет?


      1. justboris
        04.09.2017 16:39

        Есть два варианта:


        • нарендерить кучу html страниц при сборке, задеплоить их куда-то
        • поднять сервер, который рендерит страницу на сервере под запрос конкретного пользователя

        Вы какой из них используете?


        1. eyeofhell Автор
          04.09.2017 16:42

          Nuxtjs может и то, и то: generate, middleware, nuxtjs.org/api/nuxt
          Мы используем кучу HTML страниц, так как это решает вопрос «быстро показать прототип»


  1. jesprider
    04.09.2017 18:08
    +6

    Решил я попробовать этот Накст, тем более сам Эван Ю его очень советует. Установив его и начав разбираться, я понял, что мне нужно изучить ещё один уровень абстракции. Да в нём даже исходный вебпак конфиг зарыт в зависимостях. И тут я подумал — а куда мы вообще двигаемся? Теперь не зная и не понимая самого языка можно написать приложение, но стоит копнуть чуть глубже и что? В итоге начинаешь изучать как написан инструмент (а ещё хуже «бороться с ним»), вместо того, чтобы решать реальные задачи.

    Я когда-то давно ставил под вопрос использование самих фреймворков. Теперь же, когда они достигли хорошей производительности и удобных интерфейсов, этот вопрос отпал. Но использовать двойную абстракцию с тонной зависимостей — спасибо, не надо. Дальше видимо надо будет рисовать в фотошопе, а тебе раз и приложение готовое. Но где-то я уже это видел…

    rm -rf nuxtjs-test


    1. eyeofhell Автор
      04.09.2017 18:09
      +1

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


    1. oENDark
      05.09.2017 09:46

      Полностью согласен!
      Когда попытался разобраться с тем как всё устроено, чтобы иметь возможность влиять на все звенья в проекте, который будет на этом построен, то понял, что нужно настолько долго разбираться в этом всём ради неизвестно чего, что плюнул на него.


      1. jesprider
        05.09.2017 10:00
        +1

        В скором времени я планирую пересечься с Эваном Ю на конференции и задать ему этот вопрос. Понятно, что можно и написать, но раз уж выпадает возможность пообщаться лично, то почему бы и нет.


    1. tr4rex
      05.09.2017 11:21

      это вы еще spring для java не видели. на любом проекте что-то сломается, что потом ищешь полдня


  1. ilovetwins
    05.09.2017 12:20
    +2

    Очень жаль что из-за подобный комментов в обоих статьях такой замечательный фреймворк проходит мимо хабрасообщества.

    1. Новая абстракция
    Его главная фича это серверный рендеринг, с каких пор люди ожидают что это не будет отдельным слоем абстракции? Если есть хоть один способ рендерить интерактивный js на сервере без новой абстракции, покажите мне его, я забуду про все эти потуги защищать vue и nuxt.

    2. Webpack
    Установив vue-webpack из vue-cli мы тоже получим готовый webpack конфиг, который не то чтобы самый простой, но в нем уже сделано почти все что может понадобиться. И мне тоже было старшно его использовать не разобравшись что там происходит. Что я сделал? Открыл конфиг и изучил его. Меня все устроило, только добавил плагин для svg. Чем это отличается от Nuxt? Установил, в этот раз зашел не в конфиг, а в node_modules, изучил там практически такой же конфиг и остался доволен. В проекте можно легко сделать extend и добавить все нужные параметры, я так же добавил плагин для svg и вырезал все лишнее из moment.js

    3. Борьба с инструментом
    Это будет всегда, какой бы вы фреймворк не взяли, всегда будут задачи которые не удобно на нем выполнять, тогда мы будем вспоминать фреймворк Х и думать что там это было проще.

    4. Тонна зависимостей и фотошоп.
    У меня создалось впечатление что вы решили, что Nuxt за вас приложение будет создавать, но он практически ничем не отличается от чистого Vue кроме фич для рендеринга, которые созданы по гайдам самого же Vue. Единственное что сразу бросается в глаза это автоматический роутинг по структуре папок и файлов и более продуманные middlewares, неужели это предвестиники фотошопа для сайтов?
    Вопрос с зависимостями меня ставит в тупик, это же фреймворк для серверного рендеринга, он выполняется на сервере, настраивает роутинг и т.д. Мы же не удивляемся почему так много зависимостей у Express или любого другого nodejs серверного фреймворка, почему же так боимся зависимостей Nuxt? Уверяю вас, ничего из этого не попадет в ваш браузерный билд, он будет почти таким же крошечным как у самого Vue.

    Повторюсь, главная фича это серверный рендеринг. Это не очередной новый фреймворк вокруг которого начнется необоснованный хайп и появится куча статей на медиуме с заголовками типа «Как я перешел с React на Nuxt». Это всего лишь минималистичная надстройка, которая решает конкретную проблему, не добавляя при этом не обоснованной магии.


    1. jesprider
      05.09.2017 17:19

      Подобные комментарии позволяют задуматься немного глубже об обсуждаемых инструментах. Ради этого мы и читаем/пишем комментарии, не так ли? А комментарий мой относится больше не к самому фреймворку. Он больше филосовский.
      Теперь по пунктам.

      1. Я бы не назвал серверный рендеринг — новым уровнем абстракции. Это достаточно непростая задача, которая даст разработчику много новых скилов.

      2. Можно и так. Не вижу тут особых проблем. Но скрывать конфиг в зависимостях — для меня это всё же странно.

      3. Согласен. А теперь представьте у вас новый баг. Где проблема — во Вью, в Наксте или быть может в Лодэше?

      4. А вот тут не согласен. Оставим фотошоп в стороне и поговорим про зависимости. Если зависимости не увеличивают сорс код, это вовсе не означает, что их не нужно контролировать. Все помнят историю про left-pad?
      Вопрос: только у меня ощущение, что с ростом зависимостей я становлюсь более уязвим и теряю контроль над проектом? Понятно, что многих зависимостей не избежать, но в целом я считаю, что нужно держаться курса по их уменьшению.

      Для каждой отдельной задачи нужно выбирать наиболее подходящий инструмент. Накст — это однозначно отличное решение для определённого типа задач.
      Вопрос, на который я пытаюсь для себя ответить — хорошо ли это для общего образования/становления новых разработчиков? С одной стороны — конечно. Это вдохновляет и подталкивает на новые открытия. А с другой стороны не вырастит ли это более, хм, скажем «ленивых» разработчиков, и таким образом не ухудшит ли это общий уровень среди разработчиков в целом? Разумеется никто не заставляет использовать фреймворк, без изучения основ программирования, но именно так и происходит во многих случаях, которые я вижу в последнее время.


      1. ilovetwins
        05.09.2017 17:58

        Спасибо за ваш ответ, все по существу.
        Единственное что можно добавить про зависимости, то что это необходимое зло. Мне их было тяжело принять в целом в Node.js. Но как ни крути точно такая же картина например в java и php со своими менеджерами пакетов и кучей зависимостей.

        А насчет фреймворков всегда будут «ленивые» люди которые их просто используют как есть и ищут ответы на stackoverflow, и всегда будут люди которые будут копаться в исходниках и доках чтобы понять что за инструмент он использует. И это нормально и первый, и второй может быть хорошим специалистом по задачам которые он решает. Разный уровень подкованности, разные задачи, разная оплата труда. Каждый сам выбирает свой путь. Толковый opensource фреймворк как ни крути, не окажется хуже велосипеда, который поддерживает только один человек, а не целое комьюнити.


  1. Kasheftin
    05.09.2017 15:07
    +1

    В статье вроде написано про серверный рендеринг, но подано это как-то странно, будто бы главным смыслом SSR является подготовка статики для выкладывания ее на CDN через nuxt generate.

    На самом деле, SSR в nuxt — это попытка наконец-таки делать индексируемые динамические сайты (single page applications) + попытка ускорить первоначальную загрузку этих самых сайтов. Грубо говоря, вместо того, чтобы грузить заглушку, которая после инициализации подтянет данные через ajax, эти данные будут подтянуты nuxt-ом на сервере через node, отрендерены и отданы сразу же в шаблоне.

    Насколько попытка удачная — покажет время, обещают скоро выкатить 1.0, пока что все это изрядно глючит, а раз так, едва ли можно положиться на nuxt в продакшене, где эти оптимизации имеют смысл.


    1. eyeofhell Автор
      05.09.2017 15:40

      Да, именно про это я и рассказывал, но старался сделать текст более читаемым. Если еще и про backend начать, и про кеширование, и про быструю отдачу — то статью поймут только те, кто это все уже и так знает :)