Logo

Why you should package your Adobe Commerce modules

Vlad Sikailo

Vlad Sikailo

13/05/2025

3 minutes read

Technical
Why you should package your Adobe Commerce modules

Why you should package your Adobe Commerce modules

Introduction

The standard way to store Adobe Commerce modules is in the app/code/<vendor>/ directory. In this blog post, I will describe an alternative approach and why you should consider it.

Approach

At run_as_root, we store custom modules as Composer packages. For all our modules, we create a dedicated Composer package, store it in the src/ directory, and require it via Composer.

/images/blog/why-you-should-package-your-modules/src-modules.png

If you want to learn how to package your module, check the detailed instructions on the Adobe Developer Portal.

Why This Matters

The main reason for doing this is to manage dependencies between your modules with Composer.

Has it ever happened to you that you removed some module, but there was still a dependency on it in another module?

The known declaration in module.xml won't help you with this problem. That's because the sequence directive only controls the module loading order - it doesn't check whether a module has been removed or never existed 🤯.

As we've seen - this way of controlling dependencies between your project modules does not work. However, Composer is designed for dependency management - so why not let it do the job for you?

Best Practice

As we already understand, the only way to control dependencies of project's custom modules - is to use Composer. It turns out that you need to declare dependencies in both composer.json and module.xml files:

  1. in composer.json to prevent missing dependencies: so if anyone tries to remove a module that another depends on, Composer will trigger an error.
  2. in module.xml to ensure the correct configuration load order

This is how you do it in composer.json:

1{
2 "name": "vendor/module-name",
3 "description": "Description of your module",
4 "version": "1.0.0",
5 "require": {
6 "vendor/dependency-module": "^1.0"
7 },
8 "type": "magento2-module",
9 "autoload": {
10 "files": [
11 "registration.php"
12 ],
13 "psr-4": {
14 "Vendor\\ModuleName\\": ""
15 }
16 }
17}

This is how you do it in module.xml:

1<?xml version="1.0"?>
2<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
3 <module name="Vendor_ModuleName">
4 <sequence>
5 <module name="Vendor_DependencyModule"/>
6 </sequence>
7 </module>
8</config>

When all dependencies are specified, you can easily rely on Composer and let it control them.

Do not forget to follow Magento best practices during modules development:

  • Several modules should not be responsible for one feature.
  • One module should not be responsible for several features.
  • Module dependencies on other modules must be declared explicitly.
  • Removing or disabling a module does not result in disabling other modules.

And remember, a key principle of clean architecture is keeping modules loosely coupled.

How To

Conclusion

To summarize:

  • Consider packaging your project modules and requiring them via Composer.
  • Explicitly declare all dependencies in your modules' composer.json and module.xml files.
  • Follow Magento's best practices for module development.
  • Keep modules loosely coupled.

Ready to master modular code?

Book a session with Vlad, and get your questions answered.

Book your slot now

Related Articles

Technical
/images/blog/blog-crafting-code-that-lasts_thumbnail.webp
Rico Neitzel Avatar

Rico Neitzel

11.03.25

Crafting Code That Lasts
Technical
images/blog/automation-done-right/automation-poster-desktop.webp
Matthias Walter Avatar

Matthias Walter

18.12.24

Automation Done Right