As announced in 2017 a new feature was added to the v9 version of the TYPO3 core. A so called "subtree split", that leads to a very convenient situation:

Starting with TYPO3 v9.0, each system extension can be installed separately (not activated yet) via composer using “typo3/cms-{extension-name}” as in “typo3/cms-feedit”.

So first, lets understand what that means, then why we want it and finally how do we use it in our projects.

A small disclaimer first: This feature is only utilizable when setting up TYPO3 with composer. If you do not do so yet, read my article about TYPO3 and Composer and start today!

On a second note: be aware that this will be mandatory for TYPO3 v9. We will no longer be able to install the typo3/cms package with composer (as most people do at the moment) but have to use the subtree splitted packages instead. No need to worry though. There will be simple solutions and there will be advantages. Let's dive into it:

What is a subtree split?

Basically a subtree split means that parts of a git repository are split into their own repositories. This is a git feature and can be achieved as follow:

git subtree split --prefix path/to/subtree -b name-of-branch

With this command everything that sits in path/to/subtree/ will be included in a new branch called name-of-branch. The cool thing is that the entire commit history is preserved in the newly created branch and shows every commit that changed a file in the subtree of the repository. The commits only contain the changes to those files. Pretty neat. After this a new repository can be created out of the branch, it can be removed from the original repository and required as a dependency instead. This way it can be used in other projects as well.

Note that this does not make sense in many cases. But in the case of the TYPO3 system extensions it does.

In the main git repository of TYPO3 all system extensions are still there. You can have a look at git.typo3.org or at the mirror on GitHub. The system extensions were not removed from the original repository. Instead they are now additionally available as readonly repositories under the TYPO3-CMS namespace on GitHub. The updating process is automated so that each merge into the core ist immediately split and distributed to the subtree repositories as well. Also the subtree repositories are automatically taged as the core is.

But why is this a good thing?

Top

Why do we want it?

Every system extension being available as its own composer package enables us to only require the system extensions we really need on a per project base. There is no need to have e.g. the workspace system extension lying around on the production server if it is not installed. The more code we have sitting at publicly available places, the worse the security situation becomes. Projects and Deployments become slimmer as TYPO3 Updates are reduced to the shipped system extensions. As a bonus your IDE does not need to index core code that is not there at all.

Ideally we do not need to look at the PackageStates.php or the extensionmanager to see what system extensions are installed because not installed system extensions are just not there. This maybe makes the PackageStates.php even entirely obsolete one day.

For example the sysext folder for this TYPO3 page looks like this:

tree web/typo3/sysext -L 1
web/typo3/sysext
├── backend
├── belog
├── beuser
├── core
├── cshmanual
├── extbase
├── extensionmanager
├── filelist
├── filemetadata
├── fluid
├── fluid_styled_content
├── frontend
├── info
├── info_pagetsconfig
├── install
├── lang
├── linkvalidator
├── lowlevel
├── recordlist
├── reports
├── rsaauth
├── rte_ckeditor
├── saltedpasswords
├── scheduler
├── setup
├── sv
├── t3editor
├── tstemplate
└── viewpage

29 directories, 0 files

There are only 29 system extensions present. Installed via typo3/cms TYPO3 8 LTS comes with 49 system extensions. So I got rid of 20 extensions, that I do not need in this project.

Let's see what we have to do to make this happen.

Top

How do we use it?

As mentioned before we need to have a composer based setup. All the system extensions are composer packages now. So we can just require them, right?

Well ... yes, sort of.

The vendor name of each package is typo3 and every system extension is prefixed with cms-. This leads e.g. to the composer package typo3/cms-core (see on packagist) for the core system extension. The core system extension is always needed and therefore every other system extension has at least a dependency to typo3/cms-core. And so should every TER extension as well, by the way. So if we just require this package in a newly created composer project we end up with composer installing the dependencies defined in the core system extension. This includes the typo3/cms-composer-installers package. The composer installers then recognize the typo3-cms-framework type that every system extension has and put the core system extension under typo3/sysext/ in your specified web-dir.

But this is of course not a working TYPO3 project. Mandatory parts of the core are missing. We have two options:

  1. Require every system extension that we need one after another. Hint: Every system extension that is absolutely required to be there for TYPO3 to run at all has the partOfMinimalUsableSystem flag set to true in its composer.json.
  2. Use an external composer package that holds a suitable collection of system extensions to that we can add further extensions. This could be e.g. the package typo3/minimal (Packagist, GitHub). We have to be aware that if such a meta-package changes its list of extensions, we can be effected whether we agree or not. So it might be the better option to keep track of the required system extensions in our own composer.json or self-maintain a matching meta package.

In the end both options do exactly the same thing by requiering a set of needed system extensions.

Top

TYPO3 v9

If we required the latest version of typo3/minimal (I'll go with this option for now) than we are on version 9 of TYPO3 and directories should look like this (vendor excluded):

tree . -L 4 -I vendor
.
├── composer.json
├── composer.lock
└── public
    ├── index.php
    └── typo3
        ├── index.php
        ├── install.php
        └── sysext
            ├── backend
            ├── core
            ├── documentation
            ├── extbase
            ├── extensionmanager
            ├── filelist
            ├── fluid
            ├── frontend
            ├── install
            ├── lang
            ├── recordlist
            └── saltedpasswords

15 directories, 5 files

Now, this looks good and should be functional. Yay. Simple. Easy. Love it.

However, what if we want to use this sweetness with TYPO3 8 LTS?

Top

TYPO3 8 LTS

Let's require typo3/minimal ^8.7 for that. And look at the results:

tree . -L 3 -I vendor
.
├── composer.json
├── composer.lock
└── typo3
    └── sysext
        ├── backend
        ├── core
        ├── cshmanual
        ├── extbase
        ├── extensionmanager
        ├── filelist
        ├── fluid
        ├── frontend
        ├── install
        ├── lang
        ├── recordlist
        ├── saltedpasswords
        └── sv

15 directories, 2 files

We see three differences here:

  1. We have a different list of Extensions
  2. This version has no web-dir
  3. There are no entry scripts (e.g. index.php or typo3/index.php)

So what do we made of it?

  1. We ignore that the list of extensions slightly differs. It is only installed what is specified in the composer.json of typo3/minimal and we could just make our own package with a different list.
  2. The web-dir was created by the composer-installers for the v9 version because TYPO3 9 uses v2.0 of the composer installers (with 2.0 the composer installers also deny the installation of the typo3/cms package). You can have a look at the development of the composer installers over at GitHub. Anyway, if we would have specified a web-dir in our root composer.json (what we should have) this would have been used in both cases.
  3. No entry points. That's a real bummer. It is hard to get a TYPO3 system running without those ;). But as so often our beloved Hero Helmut Hummel comes for the rescue. He developed the missing piece to make the subtree splitted packages usable with TYPO3 8 LTS (and therefore with the cms-compoer-installer v1.x). His package helhum/typo3-composer-setup can be found as usual on GitHub and Packagist. And it already requires typo3/minimal. So for our little example here, we only need to require helhum/typo3-composer-setup and enjoy the result:
tree . -L 3 -I vendor
.
├── composer.json
├── composer.lock
├── index.php
└── typo3
    ├── index.php
    ├── install.php
    └── sysext
        ├── backend
        ├── core
        ├── cshmanual
        ├── extbase
        ├── extensionmanager
        ├── filelist
        ├── fluid
        ├── frontend
        ├── install
        ├── lang
        ├── recordlist
        ├── saltedpasswords
        └── sv

15 directories, 5 files

We see that Helmuts package took care of creating the entry scripts. Now this also is a functional TYPO3 system. So, go on Twitter and drop Helmut a little "Thank You".

Top

Important Notes

  • Bleeding Edge. The earliest tag that is available in the subtree splitted packages is 8.7.7. But if you are running a TYPO3 8LTS Website on 8.7.6 or lower you should update anyway.
  • Convenience with 8.7.10. Helmuts helhum/typo3-composer-setup is part of the cores dependencies in the 8 LTS branch (see the patch) since the 8.7.10 release. We do not need to require it in our root composer.json any longer.
  • No symlinks. All system extensions will be put directly into <web-dir>/typo3/sysext/. There is no longer a symlink to the vendor folder (because there is no longer only one package like typo3/cms)! Keep this in mind when switching to the subtree packages. See also this discussion for reference.
  • Mandatory with v9. With TYPO3 9.0 and later the package typo3/cms can is no longer installable by composer. So we have to use the subtree packages. Good thing that we also want to use them.
  • Keep Control. It might be better to manage your requirements in the root composer.json file of your project instead of relying on a third party meta package that might change without you noticing.

Thanks for reading. Hope your projects soon start to embrace the new power of slimness and also I hope that this article was of some use to you. If it was, consider supporting this blog on patreon. Would be much appreciated.

Top