Prefer to watch rather than read? Check out the video from my Composer presentation at Magento Imagine 2017.
Composer is a powerful tool for developers to harness the full potential of Magento 2. It puzzles me that Composer gets a bad rap and some developers are reluctant to embrace it. Why all the fuss about Magento 2 and Composer? Commerce is a competitive business - the only constant is change. End user expectations are rising all the time and successful merchants need to be innovative and move fast.
Let’s be honest - Magento updates (and all the extension updates and compatibility checking that goes with it) can be a giant pain. Take the two most important Key Performance Indicators:
- Speed of updates (number of days between release of a Magento dot release and merchant running the latest release in production)
- Cost of updating
It’s clear we need to drive both KPI’s down for Magento to remain competitive. Updating Magento can be a costly bottleneck to merchants, and it’s currently harder than on other platforms.
Because Composer can help us speed up and reduce the cost of updating Magento. Seriously - Composer can save you a lot of time and hassle dealing with future Magento core and extension upgrades. By embracing Composer, we can make automated Magento updates a ‘thing’.
Working towards the goal of automatically applied updates for Magento will yield benefits every step of the way. And before you dismiss this as being too far out there consider this:
- We can do this for our OS
- We can do this for our browsers
- And even in the php world, Wordpress has been doing it for more than 3 years
The good news is we have the technology to make this happen for Magento.
In this blog post I’ll run through some tricks for getting Composer to work for you, and show you that you don’t have to set everything up at once to benefit from Composer. Most importantly, I want to directly address some of the most common objections people have to adopting Composer.
Magento 2 Composer Refresher
Before we begin, let’s start with a quick refresher on Composer for those newer to the topic.
Composer is the de-facto dependency manager for php. It crunches loads of detailed data on available packages and their corresponding requirements for other dependencies to provide the optimal set of packages to install. Essentially it does the stuff computers are good at, but we as humans not so much.
Essentially, Composer helps co-ordinate everything, and can let you know when a new Magento version might not be compatible with your installed extensions. We tell Composer to install new packages. It will run in the background all the required checks to see if this combination of versions is compatible.
I like this musical analogy from digital agency Creare:
“Composer is exactly like…. a composer. In this case Magento 2 is a musical and the packages installed are the members of the orchestra. Once installed in your project, Composer can be used to manage packages based on its dependency system. You can’t have a live musical without the orchestra and you can’t have Magento 2 without its packages. In both cases the composer is responsible for assembling components to allow the rest to work”
Composer Removes The Headache of Magento Updates and Saves You Time (Yes, Really)
With each release of Magento 2, managing all those updates can be a big job - even for a seasoned developer. Add in all your own extensions plus the different extension run by different clients, and you have a headache on your hands making sure that everything works together.
Without Composer, with each newly released Magento 2 version you essentially have two options:
1. Go ahead with the Magento update and see if anything breaks It might update just fine, but it might not. With the number of version releases Magento puts out, at some point something is very, very likely to break. It’s almost inevitable. And you’re a strange developer if you like spending time in damage control mode having awkward ‘I messed up’ conversations with your clients!
2. Manually check for compatibility each time This essentially means going through each extension individually to make sure it’s compatible with the new Magento version. This takes a long time to do as you might have to contact every single vendor to confirm compatibility - not to mention repeating the process for every Magento site you manage that has a different set of extensions. In other words, it's pretty painful.
Wouldn’t it be nice to live in a world where developers (and the merchants footing the bill!) don’t dread updating Magento? If you are using Composer upgrading and checking for compatibility can all be done with a couple of commands. And if there are any conflicts you need to address before the upgrade you get a detailed report letting you know what is holding back the upgrade.
Composer can give you a quick snapshot of whether a given extension is not yet compatible with the new version of Magento you're trying to upgrade to. This could prevent crashing a store (as a worst-case outcome).
Moving Away From app/code
Before we can use all of the benefits of Composer in Magento 2, we need to shift away from using modules under app/code, it’s a remnant of old times. To me having code under app/code creates instant technical debt. Sure, it works. So why is it bad?
In a Magento 1 world, we came to the conclusion that editing the core is a bad idea. Did editing the core work? Yes! It did, so why was is it a bad idea? The moment you edited the core, you basically created a ‘to do’ for either yourself (or more likely someone else) to address taking this shortcut when it came time to update. You created instant technical debt.
Remember the famous Ben Marks Magento 1 t-shirt? I’ll start a print run for a Magento 2 version if we get enough orders...
I consider placing extensions under app/code in the same category. It instantly creates technical debt when it comes to upgrading because the dependency information of this module is ignored. By the time you upgrade, you probably don’t even know anymore what was written, let alone what is compatible with what, so at the time of the update you will need to spend extra time and effort on this.
Killing Magento 2 Composer Objections
Objection 1: 'But It’s Slow…’ - Tricks To Speed Up Composer
A common complaint is that Composer is slow. I hear you, it can take some time for Composer to run. Especially on the first run as it needs to download and process package information for every single version of software that we ask it to process. My bet is that Composer is still faster and more accurate than the alternatives - not to mention less risky.
But there are a few things we can do make Composer faster.
Some clever folks in the community have done some experimenting and found a few ways to increase the speed. Here are my top picks:
- Use parallel downloads By default, Composer downloads package information sequentially. However as anyone involved in front-end optimisations can attest to - parallel downloading helps.
Pure gold!— Bartek Igielski (@Igloczek) February 20, 2017
"composer install" time on clean M2 decreased from 138.13s to 18.2s :O#realmagentohttps://t.co/UJjb67kdy3
- Create a local mirror with Satis Bring the packages closer to you by hosting a mirror of the repositories locally - this can be on your laptop, or on your local network for the whole team.
Objection 2: ‘But It’s Complicated…’
Magento Marketplace and the Web Setup Wizard (its installer) use Composer under the hood. Basically, you get all the benefits of using Composer without needing to care about some of the more technical details. The Web Setup Wizard not only allows you to install Magento, but also to install extensions and upgrade both Magento itself and individual extensions without needing to touch the command line.
Tips For Making Your Code Composer-Ready
Let’s look at getting some Composer basics in place.
Tip 1: Creating a Package
Creating a package might sound like a big thing. But it really isn’t. It’s as easy as 1, 2, 3.
Let’s assume this is your extension folder:
Step 1 is to add a composer.json file:
Here is the example content for this composer.json file describing this package:
- Step 2 is to create a zip file of the folder:
- That’s it - the zip file you have just created is your first package:
Note: If you’re using Git, you can create a package with these commands instead:
git add composer.json git commit git tag v2.0.0
Tip 2: Create a Repository
We’ve just created our first package. For Composer to be able to use it, we need a repository to provide this package from. Composer allows for lots of flexibility but I’ll show you two easy options.
Option 1 - The Local artifact approach: Remember the zip file we created for our package earlier? Well - just place them all into a folder:
Tell Composer that we have packages in this folder. You can now run your Composer install commands for these packages:
Option 2 - Using Git: Composer’s very flexible so you can also use Git:
git push git push --tags
Just remember to push your changes (don’t forget the tags!). Then tell Composer to use this git repository and you’re all set:
Tip 3: Use the “Integrator” Option To Install Magento 2
Magento offers a lot of options around installation to cater to a wide audience. My advice is to use what they’ve dubbed the ‘integrator approach’:
But - never clone from GitHub directly (unless you’re planning on contributing a PR).
Tip 4: Define Dependencies
Most code that we write these days will need other packages to operate - in other words, our code depends on something else. To formalise these relationships with Composer we use the require section of our composer.json file. It’s the heart and soul of what makes Composer work.
First we have to decide what other package to depend on. In the Magento context we could depend on the any of these, however my advice is to keep your dependencies as small as possible. In practical terms this means to require the magento/module-backend that you interact with but not the major Magento project packages. The benefit here is that not all Magento releases would make changes to all the modules, so less maintenance work for you:
Depend on Module versions, not headline marketing numbers. In other words, depend on the underlying module number rather than the big release number (the logic for this is that not all modules change with every version of Magento - hence again less maintenance work for you):
Let’s look at a few examples of how we can define our dependencies:
- Only work with this one specific version of module-backend:
- Work with any version - this is a very wide constraint and therefore does not provide much value:
- Give me any of these versions - 100.1.0, 100.1.1, 100.1.2, etc:
- Make the last number a wildcard which can only go up. Give me any of these versions - 100.1.2, 100.1.3, 100.1.4 ... etc:
- Allow any release from 100.1.2 until 101.0.0. Give me any of these version 100.1.2, 100.1.3, … , 100.20.120 (this is semantic versioning at work):
In examples 1-5 above, logic operators are allowed too:
>>= 100.1.2 && < 100.1.5 100.1.2 || 100.2.0
Ranges work too:
101.1.1 - 101.1.5
My current recommendations are:
- Themes 100.1.2
- Complex extensions ~100.1.2
- Simple extensions ^100.1.2 (Simple extension and any extension which is only using @api annotated methods / Interfaces to interact with Magento core code)
Tip 5: Applying a Bug Fix
Imagine you come across an issue in Magento 2. Luckily a fix is available and has already been merged into the development branch, so you can be sure it’ll be the official solution soon.
However you need the fix now. Placing the modified file into its own extension and adding a di.xml preference for the fixed file is very quickly done with Composer:
Set a reminder:
Next we add our composer.json file. Here I have picked a very specific version of the catalog-rule package that this fix applies to.
Now imagine a new Magento release comes out. When you run the Composer update, you’ll get the reminder we set (if this module has been updated) to alert us that this fix is installed.
You then check to either extend the need for the fix, or once the fix lands in a release for Magento (likely 2.2) you can simply remove the package and update and move on.
It might seem like more work, but once you get the hang of it a lot can be created with a code generator and takes a similar amount of time to other patching approaches. But the time saver comes when you are updating Magento, allowing you to move forward faster with fewer hiccups as you do not need to remember all the fixes that we applied but that not might be front of mind anymore.
Magento 2 Composer Phasing and Priorities
To encourage the widespread adoption of Composer in the Magento community, I’d like to think of the road forward with goals in two phases:
- Magento 2 is installed and updated via Composer
- All 3rd party extensions are installed and updated via Composer
These two goals will already get us substantially closer to the goal of minimising effort on upgrades.
- All code including project specific themes and extension are managed and updated via Composer
It's not about doing everything at once. We're all busy. Converting project specific-code involves extra work. There are further considerations around tooling and workflow. But if as a community we put our brains together to make upgrades easier, I'm convinced we can improve on the status quo for Magento merchants.
Alan Kent brought this Composer plugin to my attention, which might be an option to have our cake and eat it too (ie code under app/code while reaping the benefits of dependency management with Composer). But it first requires some solid evaluation - see for example this Github issue.
It will take the Magento community as a whole to embrace Composer and reap its benefits on Magento 2. We all have a role to play. Starting with Magento Inc, by steering people in the right direction during installation, always making it easier for people to start using Composer and keeping to semantic versioning with each and every new release.
Technology Partners need to be on board as well. All released extensions should be distributed as Composer ready packages, supported by timely updates in case of new Magento versions.
Solution Partners are most commonly responsible for choosing and implementing a development workflow and deployment process for a given site. They're an important gatekeeper group that I am hoping to help convince of the merits of using Composer more.
My advice to merchants - an online store is not a one-time project. Understanding the importance of a partner that can set you up with a Composer-based deployment process will yield awesome benefits in the medium term (i.e. on the first, second, and subsequent upgrades of Magento).
Easier upgrades are 100% needed to help Magento merchants remain competitive in this ever changing commerce landscape. What do you think?