Миграция с drupal-composer/drupal-project на drupal/recommended-project

Освежаем старые проекты и приводим их в «современный» вид в соответствии с официальными Composer шаблонами проектов.

15.01.2020
15 комментариев
8 мин.

Начиная с Drupal 8.8.0 у нас появились официальные Composer шаблоны для управления Drupal.

Всего их было представлено два: drupal/recommended-project и drupal/legacy-project.

drupal/recommended-project — в данном шаблоне корень сайта вынесен на уровень ниже в папку web/ по умолчанию. Данный шаблон рекомендуется для всех новых проектов на Drupal 8.

Пример структуры проекта:

 project/
  ├─ web/
  │  ├─ core/
  │  ├─ libraries/
  │  ├─ modules/
  │  ├─ profiles/
  │  ├─ themes/
  │  └─ index.php
  ├─ vendor/
  └─ composer.json

drupal/legacy-project — аналогичный шаблон, но корень сайта находится в корне проекта, как это было и осталось в архивах.

Пример структуры проекта:

  project/
  ├─ core/
  ├─ libraries/
  ├─ modules/
  ├─ profiles/
  ├─ themes/
  ├─ vendor/
  ├─ index.php
  └─ composer.json

Если вы знакомы с drupal-composer/drupal-project, то становится ясно, что новый шаблон drupal/recommended-project является его аналогом. Их основная цель, управление Drupal через Composer, а также, вынесение корня сайта на уровень ниже.

У меня есть материал о двух вариантах установки Drupal. Я также везде где можно рекомендовал использовать drupal-composer/drupal-project для своих проектов. И вот, мы теперь имеем официальный шаблон.

drupal-composer/drupal-project никуда не девается, более того, он также обновлён на использование официальных пакетов (но распространится это только на новые проекты), но что если вы хотите перейти на официальный вариант? Тогда этот материал для вас. Это достаточно простая, пошаговая операция, где нужно лишь немного принять решений и всё будет работать дальше!

В чем отличие drupal/recommended-project от drupal-composer/drupal-project?

  • drupal/recommended-project является официальным темплейтом. Это подразумевает что он будет поддерживаться сообществом и проблемы, если такие будут возникать, будут исправляться намного быстрее.
  • drupal/recommended-project породил ряд других официальных Composer проектов, которые решают проблемы, которые раньше пытался решить drupal-composer/drupal-project своими силами и, возможно, костылями. Теперь всё подготавливается автоматически в экосистеме Drupal.
  • drupal/recommended-project практически не имеет никаких зависимостей по умолчанию. Он намного легковестнее, его структура и начальный проект не имееют «мусора» (если не считать приветственного пакета). Например, там нету ни Drush, ни Drupal Console, ни прочих подобных заметных зависимостей, и это хорошо! Вам ничего не навязывают и за вас ничего не решают.
  • drupal/recommended-project лучше подходит в качестве основны для создания своих собственных Composer шаблонов. Опять же, это связано с тем, что он «чище».
  • drupal/recommended-project нельзя использовать для проектов младше Drupal 8.8.0. Переходя на него, вы уже должны быть обновлены, либо сделать это в процессе.

В остальном, они не сильно отличаются и переходить сломя голову нет никакого смысла.

Я бы рекомендовал производить данную миграцию только если есть желание и возможности, в процессе обновления проекта до Drupal 8.8.0+ или же когда настанет момент обновляться на Drupal 9.

Миграция

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

Это значит, что миграция сводится к тому, что мы заменяем пакеты, которые ранее использовались и устанавливались drupal-composer/drupal-project на те, что используются drupal/recommended-project.

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

Некоторые зависимости появились в drupal-composer/drupal-project раньше, или наоборот позже, чем вы могли создать проект. Если их нету — просто пропускайте.

Подготовка проекта

Прежде всего, я бы рекомендовал вам обновиться до Drupal 8.8.0+, прежде чем продолжать идти по миграции.

Вы можете произвести всё это на лету в процессе миграции и сразу обновить проект, но в таком случае вам будет сложнее решать проблемы, которые могут возникнуть в ходе обновления, и изменения composer.json могут оказаться очень не кстати. Поэтому, надежнее всего, спокойно обновитесь до актуальной версии, убедитесь что проект полностью рабочий, задеплойте и приступайте к миграции. Так у вас будет точка возврата.

drupal/core

С релизом новых шаблонов проектов, появились новые официальные мета-пакеты. Один из них — drupal/core-recommended.

drupal/core-recommended — полный аналог drupal/core, с тем лишь отличием, что в нём версии для зависимостей ядра фиксированы. Это значит, что они будут обновляться только с новыми релизами Drupal. В drupal/core версии указаны минимальные, это значит, что как только у зависимостей выйдет новая версия, она будет обновлена сразу же, как только вы совершите очередное обновление.

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

Для миграции вам необходимо в composer.json файле, заменить свою текущую завиcимость, например "drupal/core": "^8.8.0", на новую "drupal/core-recommended": "^8.8".

drupal-composer/drupal-scaffold

drupal-composer/drupal-scaffold предназначен для загрузки скафолд файлов (index.php, robots.txt, .htaccess и т.д.). Для него также появилась замена в виде drupal/core-composer-scaffold.

Для миграции вам необходимо заменить в своём composer.json файле текущую зависимость, например "drupal-composer/drupal-scaffold": "^8.8.0", на новую "drupal/core-composer-scaffold": "^8.8",.

Затем, вам необходимо добавить новые настройки в extra.drupal-scaffold. Если они уже там имеются — это от старого пакета. Их необходимо временно куда-то скопировать, и вставить новые, от нового пакета.

По умолчанию в drupal/recommended-project они имеют вид:

        …
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            }
        },
        …

Затем перенесите все старые настройки в новый раздел. Только не забывайте, что у них разные настройки. Для того чтобы корректно перенести читайте документации для данных пакетов:

Пример моей новой настройки:

        …
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            },
            "file-mapping": {
                "[web-root]/sites/development.services.yml": false,
                "[web-root]/robots.txt": false
            }
        },
        …

webmozart/path-util

Данный пакет используется скриптом (scripts/composer/ScriptHandler.php), который поставляется с drupal-composer/drupal-project.

Он не потребуется — удаляем.

webflo/drupal-finder

Данный пакет используется скриптом (scripts/composer/ScriptHandler.php), который поставляется с drupal-composer/drupal-project.

Он не потребуется — удаляем.

vlucas/phpdotenv

vlucas/phpdotenv — предназначен для поддержки .env файлов.

Если на вашем проекте никак не используется .env файл на уровне веб-сервера и приложения, смело можно удалять зависимость. Если используется, оставляйте.

Если решили удалить, то не забудьте также удалить:

  • load.environment.php файл в корне проекта.
  • Загрузку данного файла в composer.json файле по пути autoload.files.
    …
    "autoload": {
        …
        "files": ["load.environment.php"]
    },
    …

drupal/console

Если не пользуетесь — удаляйте.

drush/drush

Если не пользуетесь — удаляйте.

Если решили удалить, не забудьте удалить папку drush в корне проекта.

Если drush оставили, но не используете его конфигурационные файлы и возможности (drush.yml, self.site.yml) и не указываете ему что прод, что стейдж, что дев — можно также удалить папку drush в корне. Если же вы обращаетесь через drush к продакшену, стейджу или другим инстансам проекта — оставьте.

wikimedia/composer-merge-plugin

wikimedia/composer-merge-plugin — позволяет импортировать содержимое composer.json файлов из других директорий внутри проекта и мерджить (виртуально) в один основной composer.json.

Данный пакет используется, в основном, только для кастомных модулей и тем. С релизом официальных шаблонов предлагается использовать штатное решение Composer, которое производительнее, не требует зависимостей и работает более «естественно».

Стоит ли удалять? Если у вас Composer версии 1.9.1+ (composer --version) — удаляйте, если меньше и нет возможности обновить — не трогайте.

Если у вас композер версии меньше 1.9.1 — обновите его при помощи composer self-update, в противном случае вы будете получать ошибку «Package cannot install to inside its source at…» при следовании советам ниже.

Ранее вы могли иметь следующие настройки:

        …
        "merge-plugin": {
            "include": [
                "web/modules/custom/*/composer.json",
                "web/themes/custom/*/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "merge-extra": false
        },
        …

Теперь это делается иначе, при помощи раздела repositories composer.json файла.

Вы можете указать конкретный путь до папки с composer.json файлом.

    …
    "repositories": [
        …
        {
            "type": "path",
            "url": "web/modules/custom/example"
        }
    ],
    …

Либо вы можете указать все папки внутри определенной:

    …
    "repositories": [
        …
        {
            "type": "path",
            "url": "web/modules/custom/*"
        },
        {
            "type": "path",
            "url": "web/themes/custom/*"
        }
    ],
    …

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

После данного изменения не забудьте также удалить старые настройки из extra.merge-plugin.

Важный момент в том, что все composer.json файлы, найденные таким способом воспринимаются Composer как полноценные пакеты. Это значит, что автоматически данные файлы не подхватятся, эти пути трактуются как репозитории пакетов и обрабатываются только в процессе обновлений или запросов новых пакетов.

Во всех composer.json файлах что вы хотите так использовать, обязательно должен быть указан "name" и "type". Это было совершенно ненужно со старым плагином. Теперь обязательно. Придется дать название всем кастомным пакетам в модулях.

Пример такого файла из кастом модуля «example»:

{
    "name": "example/example",
    "type": "drupal-custom-module",
    "description": "The custom code for example.",
    "keywords": [
        "Drupal"
    ],
    "require": {
        "npm-asset/swiper": "^5.0.0"
    }
}

Например, если у вас несколько модулей, и, допустим, есть «example_node», то давайте название example/example_node.

Вы можете указывать какие угодно зависимости, как и раньше, но репозитории здесь уже не поддерживаются. Вы не сможете здесь объявить https://asset-packagist.org, но можете это сделать в основном, а зависимости уже указывать модулям.

После чего вам необходимо запросить пакет через Composer. Если отталкиваться от примера выше, то composer require example/example. И так для каждого «пакета».

Фактически вы создаете свои пакеты, которые хостятся локально. А репозиторием выступает файловая система.

В результате данных действий у вас появятся соответствующие зависимости в composer.json файле проекта, что-то вроде "example/example": "dev-master", где вместо dev-master, может быть название вашей ветки git проекта.

webflo/drupal-core-require-dev

webflo/drupal-core-require-dev аналог drupal/core. В нём прописаны зависимости Drupal, необходимые исключительно для разработки, но бесполезные на продакшене и живом проекте. Для него также появился официальный аналог — drupal/core-dev.

Для миграции вам необходимо в composer.json файле, заменить свою текущую зависимость, например "webflo/drupal-core-require-dev": "^8.8", на новую "drupal/core-dev": "^8.8".

behat/mink

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

behat/mink-goutte-driver

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

jcalderonzumba/gastonjs

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

jcalderonzumba/mink-phantomjs-driver

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

mikey179/vfsstream

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

phpunit/phpunit

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

symfony/css-selector

Не нужен — удаляйте, присутствует в drupal/core-dev. Старая зависимость drupal-composer/drupal-project.

scripts/composer/ScriptHandler.php

Больше не нужен, его задачи покрывает официальный drupal/core-composer-scaffold.

Удалите файл физически, а также в composer.json из autoload.classmap и упоминания в scripts.

Если больше в scripts/ ничего полезного не присутствует — удаляйте папку целиком.

extra.installer-paths

Обновите свой раздел extra.installer-paths composer.json файла, убедитесь что ваши значения сходятся с новыми официальными и все на местах:

        …
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/libraries/{$name}": ["type:drupal-library"],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/Commands/contrib/{$name}": ["type:drupal-drush"],
            "web/modules/custom/{$name}": ["type:drupal-custom-module"],
            "web/themes/custom/{$name}": ["type:drupal-custom-theme"]
        },
        …

Не удаляйте то что вы добавили туда сами, например там могут быть "type:bower-asset" и "type:npm-asset". Просто убедитесь что все пути присутствуют и добавьте отсутствующие. Например, у вас может отсутствовать drush/Commands/contrib/{$name} или web/modules/custom/{$name} — вот тогда скопируйте и добавьте данные строки, остальные — не трогайте без необходимости.

Завершение

После того как вы сделали все замены, удаления и прочее, необходимо запустить процесс обновления — composer update --with-dependencies -o.

Если всё сделали правильно, ваш проект будет обновлён. Протестируйте его работоспособность и пуште на прод. Всё готово!

Drupal
Composer

Комментарии

Gnom7   ср, 15/01/2020 - 19:35

Я перешёл на composer-project благодаря Вашей статье и видео, и очень этим доволен. Новые проекты буду начинать recommended-project. Благодарю за качественную и актуальную информацию!

Ivnish   пн, 27/01/2020 - 22:54

Еще хочу добавить, что раньше на старом scaffold нужно было добавлять index.php и другие файлы из web/ в репозиторий, т.к. скаффолд скачивал их только при обновлении ядра, а на проде composer update нормальные люди не запускают. С новым drupal/core-composer-scaffold эти файлы скачиваются при любой операции composer и можно теперь удалить их из репозитория. При запуске composer install на проде они скачаются 100%

Ivnish   пн, 27/01/2020 - 22:59

Так же файлы .gitignore не обновятся, если они уже существуют

Sergiy   пт, 31/01/2020 - 22:21

Всем привет! Столкнулся с проблемой нехватки памяти при загрузке дополнительных модулей после установки recommended-project. Drupal-project такой проблемы раньше не было (работа на Openserver). У меня recommended-project ставится, все работает, но когда хочу установить что-то из дополнительного, ругается: "Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/local/bin/composer/src/Composer/DependencyResolver/Solver.php on line 223". По этому поводу есть тема на drupal.org (https://www.drupal.org/forum/general/general-discussion/2019-12-07/drupal-880-and-composer-memory-allocation#comment-13443099). В предпоследнем посте рекомендовали сменить в файле composer.json "drupal/core-recommended" на "drupal/core". После смены у меня все как надо поставилось и заработало. Надеюсь кому-то пригодится.

Pavel   вс, 09/02/2020 - 09:56

Для работы composer требуется не менее 2gb выделенной памяти для php и проблем не будет.

Sergiy   чт, 13/02/2020 - 15:05

Да, спасибо, уже понял. Тут все дело в памяти php (composer запускается по умолчанию из надстройки linux в Windows 10 и там именно память задана 128M). На ноутбуке стоит в настройках в php.ini файле memory_limit -1 и все работает. А вот на основном пока не могу поменять эту настройку. Точнее захожу меняю, сохраняю. Но после проверки опять 128M. Буду разбираться.

Sergiy   чт, 13/02/2020 - 15:12

Появился вопрос связанный с git. Раньше в drupal-composer/drupal-project файлы конфигурации были вынесены в отдельную папку и они нормально попадали в git. Сейчас в drupal/recommended-project эти файлы находятся по адресу web/sites/default/files/config_.../sync и не пойму как именно мне настроить .gitignore так, чтобы вместе с файлами конфигурации я не тянул в git все остальное из папки files. Подскажите пожалуйста если кто сталкивался.

Niklan   чт, 13/02/2020 - 18:07

Лучше всего вернуть их в корень проекта где они не будут доступны из вне ни при каких обстоятельствах.

Для этого в settings.php файле необходимо добавить настройку $settings['config_sync_directory'] = '../config/sync'; и всё будет как раньше.

Просто drupal-project эту настройку добавляли скриптом, а тут никаких махинаций нет.

Sergiy   чт, 13/02/2020 - 18:22

Спасибо большое! И главное настройку эту видел но просто "пропустил мимо глаз". Да, все работает!

Stepan   ср, 04/03/2020 - 14:56

Я так понял что это не полноценная миграция, а скорее обновление drupal-composer/drupal-project. Имя самого пакета не изменилось.

"name": "drupal-composer/drupal-project"

И мне пришлось добавить больше файлов в исключение, потому что во время установки на сервере он жалуется на доступ. "file-mapping": { "[web-root]/robots.txt": false, "[web-root]/sites/development.services.yml": false, "[web-root]/sites/default/default.services.yml": false, "[web-root]/sites/default/default.settings.php": false, "[web-root]/sites/example.settings.local.php": false, "[web-root]/sites/example.sites.php": false, "[web-root]/.htaccess": false }

Niklan   пт, 06/03/2020 - 07:43

Это полноценная статья по миграции.

Имя самого пакета не изменилось.

Так оно у всех своё. Темплейты оставляют своё по умолчанию, а затем каждый меняет под проект, либо оставляют как есть. Оно ни на что фактически не влияет в случае закрытого проекта. Это и не нужно менять при миграции, если устраивает текущее, то пусть и остаётся.

И мне пришлось добавить больше файлов в исключение, потому что во время установки на сервере он жалуется на доступ.

Так это проблемы с правами, которые нужно решать, а не вырубать обновление файлов.

Миграция полностью корректная и полная (я сам по ней с десяток сайтов перевёл, включая те, что создавались на старом проекте времен Drupal 8.3). Всё что вы описываете — это локальные проблемы, никак не связанная ни с миграцией, ни с одним из шаблонов.

Alex   пт, 06/03/2020 - 14:04

Мне со старого проекта drupal/drupal (v 8.5.6) на новый drupal/recommended-project удалось перейти только развернув рядом чистый recommended с указанием фиксированных старых версий ядра и модулей. Ручками из старого проекта перенес папку files, libraries и themes со своей темой. Импортнул старую базу. И далее composer update с исправлениями замечаний по версиям некоторых модулей. Потом поступательно поднимал версию ядра и модулей со всеми drush cr и drush update, пока не обновил полностью до последней версии. Всё это под docker4drupal. Ну и конечно не без примечания к релизам, чтобы не пропустить обновление media, layout_builder и особенно pathauto до перехода на 8.8.0.

tigos2   пт, 27/03/2020 - 16:17

В Docker4Drupal Composer 1.9.0 - как обновить? После всех изменений, описанных выше, куча пакетов Downgrading?

  • Downgrading composer/installers (v1.8.0 => v1.7.0): Downloading (100%)
  • Downgrading typo3/phar-stream-wrapper (v3.1.4 => v3.1.3): Downloading (100%)
  • Downgrading symfony/polyfill-ctype (v1.15.0 => v1.12.0): Downloading (100%)
  • Downgrading twig/twig (v1.42.5 => v1.42.3): Downloading (100%)
  • Downgrading symfony/yaml (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/polyfill-mbstring (v1.15.0 => v1.12.0): Downloading (100%)
  • Downgrading symfony/translation (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/validator (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/serializer (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/routing (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/polyfill-php70 (v1.15.0 => v1.12.0): Downloading (100%)
  • Downgrading symfony/http-foundation (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/psr-http-message-bridge (v1.2.0 => v1.1.2): Downloading (100%)
  • Downgrading symfony/process (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/polyfill-util (v1.15.0 => v1.12.0): Downloading (100%)
  • Downgrading symfony/polyfill-php56 (v1.15.0 => v1.12.0): Downloading (100%)
  • Downgrading symfony/polyfill-iconv (v1.15.0 => v1.12.0): Downloading (100%)
  • Downgrading psr/log (1.1.3 => 1.1.0): Downloading (100%)
  • Downgrading symfony/debug (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/event-dispatcher (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/http-kernel (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/dependency-injection (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/console (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading symfony/class-loader (v3.4.38 => v3.4.35): Downloading (100%)
  • Downgrading stack/builder (v1.0.6 => v1.0.5): Downloading (100%)
  • Downgrading pear/pear_exception (v1.0.1 => v1.0.0): Downloading (100%)
  • Downgrading pear/console_getopt (v1.4.3 => v1.4.2): Downloading (100%)
  • Downgrading pear/pear-core-minimal (v1.10.10 => v1.10.9): Downloading (100%)
  • Downgrading masterminds/html5 (2.7.0 => 2.3.0): Downloading (100%)
  • Downgrading guzzlehttp/guzzle (6.5.2 => 6.3.3): Downloading (100%)
  • Downgrading doctrine/lexer (1.2.0 => 1.0.2): Downloading (100%)
  • Downgrading egulias/email-validator (2.1.17 => 2.1.11): Downloading (100%)
  • Downgrading doctrine/inflector (1.3.1 => v1.2.0): Downloading (100%)
  • Downgrading doctrine/annotations (v1.8.0 => v1.4.0): Downloading (100%)
  • Downgrading doctrine/collections (1.6.4 => v1.4.0): Downloading (100%)
  • Downgrading doctrine/cache (1.10.0 => v1.6.2): Downloading (100%)
  • Downgrading doctrine/common (2.12.0 => v2.7.3): Downloading (100%)
  • Downgrading composer/semver (1.5.1 => 1.5.0): Downloading (100%)
  • Downgrading asm89/stack-cors (1.3.0 => 1.2.0): Downloading (100%)

Теперь на некоторых страницах сайта выскакивает: Fatal error: require(): Failed opening required '/var/www/html/vendor/composer/../doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php' (include_path='/var/www/html/vendor/pear/archive_tar:/var/www/html/vendor/pear/console_getopt:/var/www/html/vendor/pear/pear-core-minimal/src:/var/www/html/vendor/pear/pear_exception:.:/usr/local/lib/php') in /var/www/html/vendor/symfony/class-loader/ApcClassLoader.php on line 112

tigos2   сб, 28/03/2020 - 03:49

Никита, огромное спасибо за статью и за то что делишься с народом своим опытом!

Предыдущая ошибка "Fatal error" исчезла :-) После того как перезапустил докер, скорей всего какие-нибудь кэши.

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