» » 21 совет по эффективному использованию Composer

 

21 совет по эффективному использованию Composer

Автор: admin от 12-01-2018, 14:00, посмотрело: 22

21 совет по эффективному использованию Composer

Хотя большинство PHP-разработчиков умеют пользоваться Composer, не все делают это эффективно или лучшим возможным образом. Поэтому я решил собрать советы, которые важны для моей повседневной работы. Большинство из них опираются на принцип «От греха подальше»: если что-то можно сделать несколькими способами, то я выбираю наименее рискованный.

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



Совет № 2: различайте проект и библиотеку



Важно знать, что вы создаёте — проект или библиотеку. Каждый из вариантов требует своего набора методик.



Библиотека — это многократно используемый пакет, который нужно добавлять в качестве зависимости. Например, symfony/symfony, doctrine/orm или elasticsearch/elasticsearch.



Проект обычно представляет собой приложение, зависящее от нескольких библиотек. Обычно он не используется несколько раз (никакому другому проекту он не понадобится в качестве зависимости). Характерные примеры: сайт интернет-магазина, система поддержки пользователей и т. д.



Дальше в советах я буду переключаться между библиотекой и проектом.



Совет № 3: используйте для приложения конкретные версии зависимостей



Если вы создаёте приложение, то используйте для определения зависимости как можно более конкретный номер версии. Если нужно проанализировать YAML-файлы, то определяйте зависимость, например, так: "symfony/yaml": "4.0.2".



Даже если библиотека следует правилам семантического версионирования (Semantic Versioning), в минорных и патчевых версиях всё же могут возникать нарушения обратной совместимости. Допустим, если вы используете "symfony/symfony": "^3.1", то что-то устаревшее в 3.2 сломает ваши тесты. Или в PHP_CodeSniffer окажется исправленный баг, и в вашем приложении будут обнаружены новые ошибки форматирования, что снова может привести к сломанной сборке.



Обновляйте зависимости обдуманно, а не импульсивно. Подробнее об этом мы поговорим в одном из следующих советов.



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



Совет № 4: для зависимостей библиотек используйте диапазоны версий



Если вы делаете библиотеку, то определяйте самый возможный диапазон версий. Если создаёте библиотеку, использующую библиотеку symfony/yaml для YAML-разбора, то запрашивайте её так: "symfony/yaml": "^3.0 || ^4.0"



Тогда ваша библиотека сможет использовать symfony/yaml из любых версий Symfony с 3.x по 4.x. Это важно, поскольку данное ограничение распространяется и на приложение, которое обращается к вашей библиотеке.



Если есть две библиотеки с конфликтующими требованиями (одной, к примеру, нужна ~3.1.0, а другой ~3.2.0), то будет сбой при установке.



Совет № 5: в приложениях нужно коммитить composer.lock в Git



Если вы создаёте проект, то нужно коммитить composer.lock в Git. Тогда все — вы, ваши коллеги, ваш CI-сервер и рабочий сервер — будут использовать приложение с одинаковыми версиями зависимостей.



На первый взгляд этот совет кажется излишним. Вы уже выбрали конкретную версию, как в совете № 3. Но ещё существуют зависимости ваших зависимостей, которые не связаны этими ограничениями (например, symfony/console зависит от symfony/polyfill-mbstring). Так что без коммита composer.lock вы не получите такой же набор зависимостей.



Совет № 6: в библиотеках кладите composer.lock в .gitignore



Если вы создаёте библиотеку (назовём её acme/my-library), то не нужно коммитить файл composer.lock. Это никак не влияет на проекты, использующие вашу библиотеку.



Допустим, acme/my-library использует monolog/monolog в качестве зависимости. Если вы закоммитили composer.lock, то все, кто разрабатывает acme/my-library, будут использовать более старую версию Monolog. Но когда вы закончите работу над библиотекой и используете её в реальном проекте, может быть установлена более новая версия Monolog, которая окажется несовместимой с вашей библиотекой. Но раньше вы не заметили этого из-за composer.lock!



Лучше всего класть composer.lock в .gitignore, чтобы случайно не закоммитить.



Если хотите быть уверены в совместимости библиотеки с разными версиями её зависимостей, читайте следующий совет!



Совет № 7: запускайте сборки Travis CI с разными версиями зависимостей



Совет относится только к библиотекам (потому что для приложений вы используете конкретные версии).


Если вы собираете open-source библиотеку, то, вероятно, запускаете сборки с помощью Travis CI. По умолчанию Composer устанавливает последние возможные версии зависимостей, допускаемые ограничениями в composer.json. Это означает, что для ограничения зависимости ^3.0 || ^4.0 сборка всегда будет использовать последнюю версию релиза v4. И поскольку версия 3.0 никогда не тестировалась, библиотека может оказаться несовместимой с ней, что опечалит пользователей.



К счастью, в Composer есть переключатель --prefer-lowest для установки самых старших из возможных версий зависимостей (его нужно использовать вместе с --prefer-stable для предотвращения установок нестабильных версий).



Обновлённая конфигурация .travis.yml может выглядеть так:



language: php

php:
  - 7.1
  - 7.2

env:
  matrix:
    - PREFER_LOWEST="--prefer-lowest --prefer-stable"
    - PREFER_LOWEST=""

before_script:
  - composer update $PREFER_LOWEST

script:
  - composer ci


Можете посмотреть её в работе на примере моей библиотеки mhujer/fio-api-php и матричной сборки Travis CI.



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



Совет № 8: сортируйте пакеты в require и require-dev по имени



Хорошая привычка — держать пакеты в require и require-dev отсортированными по имени. Это поможет пресекать ненужные конфликты слияния при перебазировании ветки. Потому что если вы в двух ветках добавляете пакет в конце списка, то конфликты слияния будут возникать каждый раз.



Вручную это делать нудно, так что лучше сконфигурировать в composer.json:



{
...
    "config": {
        "sort-packages": true
    },
…
}


Когда вы в следующий раз затребуете (require) новый пакет, он будет добавлен в правильное место (не в конец).



Совет № 9: не пытайтесь объединять composer.lock при перебазировании или слиянии



Если вы добавили в composer.json новую зависимость (и composer.lock) и перед слиянием ветки в мастер была добавлена другая зависимость, вам нужно перебазировать ветку. И вы получите в composer.lock конфликт слияния.



Никогда не пытайтесь разрешить его вручную, потому что файл composer.lock содержит хеш зависимостей, определённых в composer.json. Так что, если даже вы разрешите конфликт, получится некорректный lock-файл.



Лучше создавать в корне проекта .gitattributes со следующей строкой, и тогда ваш Git не будет пытаться объединять composer.lock: /composer.lock -merge



Можете решить проблему с помощью кратковременных веток фич (feature branches), как предлагается в Trunk Based Development (это нужно делать в любом случае). Если у вас есть правильно объединённая краткосрочная ветка, риск конфликта слияния в composer.lock минимален. Даже можете создать ветку только для добавления зависимости и сразу объединить её.



Но что делать, если в composer.lock возник конфликт слияния при перебазировании? Разрешите его с помощью версии из мастера, так у вас будут изменения только в composer.json (недавно добавленный пакет). А потом запустите composer update --lock, который захочет обновить файл composer.lock изменениями из composer.json. Теперь можете стейджить обновлённый composer.lock и продолжать перебазирование.



Совет № 10: помните о разнице между require и require-dev



Важно помнить о разнице между блоками require и require-dev.



Пакеты, необходимые для запуска приложения или библиотеки, должны быть определены в require (например, Symfony, Doctrine, Twig, Guzzle…). Если создаёте библиотеку, то будьте осторожны с тем, что кладёте в require. Каждая зависимость в этой секции тоже является зависимостью приложения, использующего библиотеку.



Пакеты, необходимые для разработки приложения или библиотеки, должны быть определены в require-dev (например, PHPUnit, PHP_CodeSniffer, PHPStan).



Совет № 11: обновляйте зависимости безопасно



Полагаю, вы согласны с утверждением, что зависимости нужно регулярно обновлять. И я советую делать обновление зависимостей прозрачно и продуманно, а не по мере какой-то другой работы. Если вы что-то рефакторите и в то же время обновляете какие-то библиотеки, то не сможете сказать, чем сломано приложение, рефакторингом или обновлением.



Используйте команду composer outdated для просмотра, какие зависимости можно обновить. Можно ещё включать --direct (или -D) для вывода только зависимостей, заданных в composer.json. Ещё есть переключатель -m для вывода обновлений только минорных версий.



Для каждой устаревшей зависимости придерживайтесь плана:




  1. Создайте новую ветку.

  2. Обновите в composer.json версию зависимости на самую свежую.

  3. Запустите composer update phpunit/phpunit --with-dependencies (замените phpunit/phpunit названием обновляемой библиотеки).

  4. Проверьте CHANGELOG в репозитории библиотеки на GitHub, чтобы узнать, нет ли всё ломающих изменений. Если есть, обновите приложение.

  5. Локально протестируйте приложение. Если используете Symfony, то можете найти предупреждения о deprecated в панели отладки.

  6. Закоммитьте изменения (composer.json, composer.lock и всё, что нужно для работы новой версии).

  7. Дождитесь окончания CI-сборки.

  8. Объедините и разверните.



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



composer update symfony/symfony symfony/monolog-bundle --with-dependencies



Или можете использовать шаблон для обновления всех зависимостей из определённого пространства имён:



composer update symfony/* --with-dependencies



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



Можно лишь в одном облегчить себе работу: разом обновлять все зависимости require-dev (если они не требуют изменений в коде, иначе предлагаю использовать отдельные ветки для упрощения ревизии кода).



Совет № 12: можете определять в composer.json другие типы зависимостей



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



Например, какие версии PHP поддерживает приложение/библиотека:



"require": {
    "php": "7.1.* || 7.2.*",
},


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



"require": {
    "ext-mbstring": "*",
    "ext-pdo_mysql": "*",
},


Используйте * для версий расширений, потому что они могут быть несогласованными.



Совет № 13: проверяйте composer.json в ходе CI-сборки



composer.json и composer.lock должны быть всегда синхронизированы. Поэтому целесообразно автоматически проверять их синхронизированность. Просто добавьте этот механизм в свой скрипт сборки:



composer validate --no-check-all --strict



Совет № 14: используйте Composer-плагин в PHPStorm



Существует composer.json-плагин для PHPStorm. Он добавляет автокомплит и ряд проверок при ручном изменении composer.json.



Если вы используете другую IDE (или только редактор кода), можете настроить проверку его JSON-схемы.



Совет № 15: определяйте в composer.json рабочие версии PHP



Если вы, как и я, любите иногда локально запускать предварительные релизы версий PHP, то рискуете обновить зависимости до версий, не работающих в продакшене. Сейчас я использую PHP 7.2.0, т. е. могу устанавливать библиотеки, которые не будут работать на 7.1. А поскольку продакшен использует 7.1, установка завершится сбоем.



Но переживать не нужно, есть лёгкое решение. Просто определите рабочие версии PHP в разделе config файла composer.json:



"config": {
    "platform": {
        "php": "7.1"
    }
}


Пусть вас не смущает раздел require, который ведёт себя иначе. Ваше приложение может работать на 7.1 или 7.2, но в то же время 7.1 будет определена как платформенная версия, т. е. зависимости всегда будут обновляться до версии, совместимой с 7.1:



"require": {
    "php": "7.1.* || 7.2.*"
},
"config": {
    "platform": {
        "php": "7.1"
    }
},


Совет № 16: используйте приватные пакеты из Gitlab



Рекомендую выбирать vcs в качестве типа репозитория, и Composer должен определить правильный способ извлечения пакетов. Например, если вы добавляете форк с GitHub, он будет использовать свой API для скачивания zip-файла вместо клонирования всего репозитория.



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



Сначала определил репозиторий типа git:



"repositories": [
    {
        "type": "git",
        "url": "git@gitlab.mycompany.cz:package-namespace/package-name.git"
    }
]


А затем использовал пакет, как это обычно делается:



"require": {
    "package-namespace/package-name": "1.0.0"
}


Совет № 17: как временно использовать ветку из форка с исправлением бага



Если вы нашли баг в публичной библиотеке и исправили его в своём форке на GitHub, то вам нужно установить библиотеку из своего репозитория, а не из официального (пока исправление не будет объединено и не появится исправленный релиз).



Это легко можно сделать с помощью inline aliasing:



{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/you/monolog"
        }
    ],
    "require": {
        "symfony/monolog-bundle": "2.0",
        "monolog/monolog": "dev-bugfix as 1.0.x-dev"
    }
}


Можете локально протестировать своё исправление, прежде чем загружать его, используя path в качестве типа репозитория.



Совет № 18: установите prestissimo для ускорения установки пакетов



Composer-плагин hirak/prestissimo ускоряет установку зависимостей посредством параллельного скачивания.



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



composer global require hirak/prestissimo



Совет № 19: если не уверены, протестируйте свои версионные ограничения



Написание корректных версионных ограничений иногда становится непростой задачей после прочтения документации.



К счастью, есть Packagist Semver Checker, позволяющий проверять, какие версии соответствуют конкретным ограничениям. Вместо простого анализа версионных ограничений данные скачиваются из Packagist для отображения актуальных выпущенных версий.

См. результат для symfony/symfony:^3.1.



Совет № 20: используйте в продакшене авторитарную карту классов (class map)



Сгенерируйте в продакшене авторитарную карту классов. Это ускорит загрузку классов благодаря включению в карту всего необходимого и пропуску любых проверок файловой системы.



Можете делать это в рамках вашей рабочей сборки:



composer dump-autoload --classmap-authoritative



Совет № 21: для тестирования сконфигурируйте autoload-dev



Вам не нужно включать тестовые файлы в рабочую карту классов (из-за размера файла и потребления памяти). Это можно сделать с помощью конфигурирования autoload-dev (аналогично autoload):



"autoload": {
    "psr-4": {
        "Acme": "src/"
    }
},
"autoload-dev": {
    "psr-4": {
        "Acme": "tests/"
    }
},


Источник: Хабрахабр

Категория: Программирование

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

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *