Обновление App

С некоторых пор я плотно переехал на Webpack, так что решил обновить и свою заготовку для создания сайтов App.

Точкой входа во frontend приложение служит _build/assets/js/index.js, там вот такой код:
import 'jquery'
import 'bootstrap'
import '../scss/index.scss'

console.log('App is loaded!');


В чём прикол, по сравнению с Gulp? Ну в том, что нам нужна только эта точка входа для работы, в которой импортируются и скрипты и стили. А дальше Webpack уже сам всё разбирает:
— берёт указанные скрипты, проходит по ним, находит зависимости и тащит с собой
— затем проходит по стилям, обрабатывает пути к файлам и тащит импорты
— копирует и минифицирует изображения
— скрипты, стили, шрифты и картинки раскладываются в соответствующие директории
— а конечные директории перед этим очищаются от старых файлов
— имена файлов называются с припиской их хэша из 8 символов, для грамотного кэширования
— за всё это отвечает единый конфиг и при добавлении новых библиотек в нём ничего менять не нужно, просто импортировать их в index.js

В итоге получается вот такая картина в assets:


Так как имена файлов меняются, генерируется еще и специальный манифест с их именами:
{
  "bootstrap.js": "/assets/components/app/js/bootstrap.7ee522b0.min.js",
  ...
  "fonts/fa-solid-900.woff": "/assets/components/app/fonts/fa-solid-900.0be94a07.woff",
  "fonts/fa-solid-900.woff2": "/assets/components/app/fonts/fa-solid-900.64b3e814.woff2",
  "jquery.js": "/assets/components/app/js/jquery.a93a223a.min.js",
  "main.css": "/assets/components/app/css/main.628a6812.min.css",
  "main.js": "/assets/components/app/js/main.41054e11.min.js",
  "popper.js.js": "/assets/components/app/js/popper.js.103f3354.min.js"
}

Дальше дело техники получить его в плагине на OnBeforeRegisterClientScripts и подключить скрипты со стилями на страницу:
$manifest = MODX_ASSETS_PATH . 'components/app/manifest.json';
if (file_exists($manifest)) {
    $files = json_decode(file_get_contents($manifest), true);
    foreach ($files as $file) {
        if (strpos($file, '.css')) {
            $modx->regClientCSS($file);
        } elseif (strpos($file, '.js')) {
            $modx->regClientScript($file);
        }
    }
}

Больше про версии ассетов думать не нужно. Просто вызывайте npm run build перед сборкой и установкой App. Понятное дело, есть и npm run watch для разработки.


Как видите, автоматически грузится и шрифт FontAwesome который обработан через импорт в scss и скопирован в директорию fonts.

Помимо автоматизации вы можете использовать и все прелести ECMAScript 6, конечно. Можно подключать хоть Vue, хоть React, хоть чёрта лысого.

Всем приятной разработки!
Василий Наумкин
21 мая 2019, 13:12
modx.pro
20
3 448
+29

Комментарии: 38

Иван Бочкарев
21 мая 2019, 13:44
+2
Спасибо!
    Денис
    21 мая 2019, 14:49
    +2
    За модуль webpack-assets-manifest спасибо, прикручу к своему конфигу и теперь нормально свяжу с modx.
      Max Roganov
      21 мая 2019, 14:58
      +1
      Отличненько, попробуем вебпак =)
        Александр
        21 мая 2019, 19:32
        0
        А из админки MODX можно как-то вызывать «npm run build» кнопкой созданной? Через shell_exec или есть способы получше?
          Василий Наумкин
          22 мая 2019, 03:42
          0
          App придуман именно для того, чтобы в админку вообще не заходить.
            Александр
            22 мая 2019, 11:54
            0
            Это, конечно, здорово, но вопрос никак не отменяет :)
            Пример. Создал я в удобном для меня окружении сайт, всё без админки, по фен-шую! Но, пришёл после меня менеджер, которую эти webpack / gulp совсем ни о чём не говорят, ему надо только шрифт в нескольких местах изменить, да скриптов пару поправить. И для этого ему надо подключаться по ssh, чтобы в терминалы выполнить npm run build? Это неудобно)
              Василий Наумкин
              22 мая 2019, 13:10
              +5
              которую эти webpack / gulp совсем ни о чём не говорят, ему надо только шрифт в нескольких местах изменить, да скриптов пару поправить.
              Менеджер не должен этого делать, это не его работа. А если он берётся за работу, в которой ничего не понимает, то это уже его проблемы.

              Скрипт сборки по умолчанию и так запускает npm run build, но процесс это небыстрый и, как правило, build.php прибивается по таймауту, если запускать его из браузера. А вот при работе в консоли такой проблемы не будет.
                Александр
                22 мая 2019, 13:32
                0
                Каждый раз вызывать программиста, верстальщика, разработчика для того, чтобы изменить какую-нибудь мелочь — тоже дело довольно странное. Речь ведь не о функциональных возможностях, не о программировании, а о контенте, о том, как ог отображается. И, если надо убрать несколько строк CSS из тех файлов, что есть, то это вызывает слишком много лишних телодвижений, занимающих время, которое продуктивнее направить в другое русло.

                Ваш метод хорош, а желание совместить приятное с полезным, чтобы всем было удобно, остаётся.
                Самый логичный способ — добавить 1 кнопку для ребилда скриптов, стилей и т.д. Идеально же!
                  Василий Наумкин
                  22 мая 2019, 13:39
                  +1
                  Мой метод хорош для серьёзных проектов и разработчиков. И для серьёзных заказчиков, которые платят за техобслуживание сайта. А для проектов «на коленке» он, безусловно, совсем не хорош.

                  Прямо сейчас представил, как я сдал modstore.pro Витале с Лёней, а они там стили со скриптами в админке правят, чтобы меня не вызывать лишний раз. До слёз!
                    Александр
                    22 мая 2019, 22:51
                    0
                    Бесспорно, это так. Вы очень выборочный в заказчиках, это здорово, что у вас грамотные заказчики.

                    Рад, что развеселил вас! Не плачьте
                      mrmelkiy
                      31 мая 2019, 20:24
                      0
                      Александр, РУ сообщество MODX разъяснения то начинает если ты, как минимум, с PHPна 4? 4+?, если нет — «метод хорош для серьёзных проектов и разработчиков. И для серьёзных заказчиков, которые платят». Это не место для таких вопросов ) А если, не дой Бог, вы начали изучать, то точно не сюда за помощью ). Поэтому MODX сообщество самое малочисленное ).
                      А так Василий создал хорошую вещь и она только для программеров и не более.
                        Алексей Соин
                        03 июня 2019, 12:30
                        0
                        эт ты еще на всяких форумах и чатиках по линуксу не спрашивал начальные вопросы)))) вот там джентльмены знают толк в покрывании хренами)

                        честно говоря твой посыл в этом сообщении я понял только после 4-5 раза перечитывания :D
          Степан Прищепенко
          22 мая 2019, 09:49
          0
          Можно еще в один файлик все компоновать быстрее будет.
            Василий Наумкин
            22 мая 2019, 10:29
            0
            Если я одну библиотеку обновил, то именно она и загрузится у юзера заново, а остальные останутся в кэше.

            Лично меня не радует перекачивать какой-нибудь бандл на много мегабайт при каждой обновке. Именно поэтому всё разбито на файлы с хэшем в имени.
              Степан Прищепенко
              22 мая 2019, 11:50
              0
              На вкус и цвет конечно, мне больше нравиться вендоры отдельно компоновать (они достаточно редко обновляются, за исключением если это делается автоматом конечно со всякими тестами), а динамичные куски js держать в html. В итоге получаем 1-н css 1-н js 1-н спрайт, шрифты и отдельные файлы подгружаемых картинок контента.
                Александр
                22 мая 2019, 11:56
                0
                Доброго времени суток, Степан. Чем генерируете спрайты, используете иконочные шрифты?
                  Степан Прищепенко
                  22 мая 2019, 12:03
                  2
                  +1
                  Доброго, делаю через gulp, есть определенная структура и от местоположения файликов, скрипт сам решает что куда распихивать, просто напишу частично что используется:
                  • gulp-iconfont и gulp-iconfont-css
                  • gulp-rev
                  • gulp-uglify
                  • gulp-clean-css
                  • gulp.spritesmith и gulp-imagemin
                  • gulp-svgmin, gulp-svg-sprite, gulp-cheerio
                    Алексей Соин
                    23 мая 2019, 07:25
                    +3
                    Советую вместо gulp-uglify использовать gulp-uglify-es, так как gulp-uglify не поддерживает ES6 и при компиляции такого кода будут возникать ошибки
          Владислав
          27 мая 2019, 16:57
          0
          @Василий Наумкин Отличное решение, но одну противоречивость так и не удается победить:
          Файл main.XXX.min.css — каждый раз новый, что удобно для кеширования, но не удобно для «истории».
          Не успел опробовать, пожалуйста, подскажи:
          Реально ли писать имя файла в формате main.min.css?v=XXX, где XXX — contenthash
          filename: options.mode == 'production'
                       ? 'css/[name].[contenthash:8].min.css'
                       : 'css/[name].css',
            Василий Наумкин
            27 мая 2019, 17:07
            0
            Для истории нужно использовать Git.
              Владислав
              27 мая 2019, 17:12
              0
              Я про эту историю:
              archive.org/web/ и «Сохраненная копия» поисковиков

              Такая же проблема с использованием Minify — каждый раз новые файлы (css и js)
                Василий Наумкин
                27 мая 2019, 17:14
                0
                Меня проблемы этих сервисов как-то совсем не заботят.

                Если есть огромное желание — убери вообще [contenthash:8]. и добавляй версию при подключении файла в плагине.
            Артем
            12 июля 2019, 01:46
            0
            Спасибо за webpack, да и вообще отличную заготовку! Правда один момент неоднозначный получается: ресурсы генерируются со статическими id из массива, но что, если менеджер создал несколько новых ресурсов в админке? Получится так, что если мы вдруг надумаем добавить еще один ресурс в массив, то при следующей сборке ранее созданные ресурсы менеджером перезапишутся ввиду того, что наш пакет не знает о них. Такая же история получается при какой-нибудь выгрузке из 1C, например.
              Евгений
              17 сентября 2019, 14:20
              0
              Спасибо за отличную заготовку! Все супер. Правда есть пара вопросов, буду рад ответам:

              1) как поставить пакеты из modstore (подгружаю файл providers.php в resolvers и поставщик ставится без проблем), пробую указать такую конструкцию в setup.php, но пакет не ставится:
              'pdoTools' => [ 
                      'version' => '2.12.3-pl',
                      'service_url' => 'modstore.pro',
              ],
              Что делаю не так?
              2) почему то при установке в папке core/components создается папка 0, которая полностью дублирует папку assets/components/app, это так и должно быть?
                Артем
                18 сентября 2019, 02:43
                0
                1) неправильный service_url, правильный: modstore.pro/extras/
                2) есть такая проблема
                  Евгений
                  23 сентября 2019, 16:00
                  0
                  1) оказалось была ошибка в API-ключе, после исправления все заработало. modstore.pro/extras/ не обязательно указывать, modstore.pro досточно как оказалось.
                  2) эту папку можно удалять без каких-либо последствий?
                Евгений
                23 сентября 2019, 16:01
                0
                можно ли как-то при помощи webpack-а чистить папку cache при каждом редактировании элементов, в частности сниппетов?

                Я так понимаю, что нужно копать в файле webpack.config.js в блоке CleanWebpackPlugin, параметр cleanaftereverybuildpatters? Или ничего не получится и необходимо дополнительно ставить gulp?
                  Николай
                  23 сентября 2019, 20:43
                  0
                  Как вариант предложу вот такую штуку, сам пользуюсь. Правда там немного по-другому
                    Евгений
                    27 сентября 2019, 15:18
                    0
                    грузить страницу каждые 0.5 секунд выполнением скрипта, это сильно конечно :))
                      Николай
                      27 сентября 2019, 17:55
                      0
                      «Страница» это всего-лишь малюсенький скрипт на чистом PHP) Он запускает маленький процесс на сервере, который не напрягает ни процессор ни оперативку. А процессов этих в любой операционной системе тьма) Некоторые жрут сотни мегабайт оперативки каждую секунду, и грузят процессор. Gulp тоже запускает всякие процессы иначе как он узнает о том, что файлы изменились? У меня этот скрипт работает на локалке, и как-то я не чувствую тормозов в системе)) Он вообще для разработки, потом можно удалить ;) Кстати, та страница отдаётся за 20-30 мс.
                        Николай
                        27 сентября 2019, 17:58
                        0
                        В общем, проблем не было даже на хостинге. Вообще не понимаю удивления. За запросы к страницам что деньги берут или наказывают как-то?)
                          Евгений
                          20 декабря 2019, 16:11
                          1
                          0
                          решилось настройкой конфига:

                          new CleanWebpackPlugin({
                              verbose: false,
                              cleanStaleWebpackAssets: true,
                              cleanAfterEveryBuildPatterns: [base + '../../../core/cache/*'],
                              dangerouslyAllowCleanPatternsOutsideProject: true,
                              dry: false,
                          }),
                    Евгений
                    27 сентября 2019, 15:16
                    0
                    Народ, никто не сталкивался с проблемой, когда указываешь в типах содержимого для HTML расширение "/", чтобы все страницы заканчивались слэшем, получается циклическая переадресация?
                      Евгений
                      27 сентября 2019, 15:53
                      0
                      Разобрался сам, мб кому пригодится:
                      в папке /Extras/App/core/components/app/model/ в файле app.class.php нужно найти код (101 строка):
                      if ($uri != '/' && in_array(substr($uri, -1), ['/', '?'])) {
                           $this->modx->sendRedirect(rtrim($uri, '/?'), ['responseCode' => 'HTTP/1.1 301 Moved Permanently']);
                      }
                      на
                      if ($uri != '/' && in_array(substr($uri, -1), ['?'])) {
                           $this->modx->sendRedirect(rtrim($uri, '?'), ['responseCode' => 'HTTP/1.1 301 Moved Permanently']);
                      }
                      Сергей
                      09 апреля 2020, 18:03
                      0
                      Всем привет. Понимаю, что вероятность крайне мала, но вдруг кто-то может помочь: почему-то не добавляются на страницу ни стили, ни скрипты. Такое чувство, что событие OnBeforeRegisterClientScripts просто не срабатывает. Что я делаю не так? Как заставить стили и скрипты грузиться из манифеста?
                        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                        38