Research phase
Initial situation: challenge to build 10+ similar sites
The first site had been implemented on the basis of an existing template and consequently the other sites should also be based on the same template.
It was only after completion of these websites that it became clear that this trend will continue, so we approached the client to discuss their future plans.
The client confirmed their plan to implement a further 15+ websites in a similar style over the 12 months to come. We would be responsible for implementing – and later maintaining – these websites.
Given this information we quickly agreed within our team that we would need to find a more efficient and scalable approach to the wider project than just duplicating the existing Joomla! instance and modifying content/configuration for each new site.
Deciding on the right approach
Option 1: A single multi-domain CMS installation
In the past we had implemented multiple domains/websites within a single Joomla! Installation several times, and in several different ways.
The wrong approach – for many reasons…
On the basis of this experience we were able to quickly agree within our team that – while this might technically be possible in this case – it would be the wrong approach for various reasons:
- Each of the sites for a different department, project or subsidiary: hence little overlap in terms of backend/frontend users, permissions, etc.
- Separate usage of many components: Acymailing, DOCman, … also desire to avoid installing all components on all sites
- Risk of increasing complexity through small exceptions and workarounds as the dimensions of the project grow
- Inability to implement significant structural differences without complexity
Option 2: separate CMS / centralised resources
Instead we decided upon a completely different solution, combining the flexibility and simplicity of multiple CMS instances with the many benefits of centralisation of resources, content and settings across these websites.
Planning the project
As part of an initial planning phase for the project we discussed and answered the following questions:
What are the goals/benefits of centralisation?
- By avoiding duplication of code across these sites we can ensure that the sites remain aligned and save considerable time when changes are necessary
- Any new feature, function or layout will immediately be available to use on all 20 websites
- The convenience of dual-track CSS development: maintaining a central CSS file and multiple site-specific overrides
- Other resources such as language strings and configuration settings can also be shared across the sites
- A slight improvement in page speed through loading resources from a separate domain
- The project would give us the chance to prove – to ourselves, to our client and to the world in general – that Joomla can be extended to meet this sort of requirement
Methods/requirements
JS/CSS/images
Given the availability of a central ‘shared’ domain we can also serve shared JS, CSS and image files from this same central directory.
PHP files
Providing the sites are hosted on one server, we can load shared PHP files from a central directory located outside of the individual Joomla installation directories.
Language strings
By implementing our own dedicated Joomla language plugin and installing this on all sites we can centralise language strings globally.
Shortcodes
We use ReReplacer to make shortcodes available to content editors. By moving all of our rules (shortcodes) to a single, central XML file we can install ReReplacer on all sites and configure it to load the rules from this file.
Risks/threats
One bug to rule them all
With just one faulty line of code in a centralised file it’s easy to crash 20 sites at once. And that’s just what happened, notably with a faulty error.php file that generated millions of PHP requests and got us into some trouble with the client.
The need for documentation
When implementing new styles or features we would need to think ahead (what might we use this for in the future?) and back (have we done something similar in the past?). To make this possible we would need to document our development far more carefully than before.
Notes and results
We also gave some initial thought to which elements it would/wouldn’t make sense to centralise, however rather than discuss that here in the next section I’ll focus on the end results of the project … i.e. what we did/didn’t centralise, and why.
Based on this research we were able to convince the client to make the time/budget available for this project, which would be divided into three phases:
- Implement the technical infrastructure for centralisation
- Retroactively bring the existing sites into line with this plan
- Plan processes for the introduction of new websites
Implementation phase
During the course of the project that followed, we centralised a variety of resources.
Centralising CSS/JS files
The mess we had to deal with
By the time we got started with actual centralisation, we had already implemented 6-7 separate websites in this style, each with its own custom CSS/JS.
Our first task would be an arduous one: to compare and harmonise this code, removing as much redundant code as possible, and (ideally) without breaking any of the individual sites.
As regards CSS, an ill-considered decision early in the project lead us to separate this code for each site out into modular blocks, each as a separate file.
Although when viewed as a whole, 75% of the CSS across the sites was the same, there were 10-15 individual files for each site, and these files had been worked on by different developers, each with their own approach and all working on tight deadlines. Consequently these files contained many small differences.
The situation with JS was similar, but fortunately there was far less code overall to contend with. Also, by the nature of JS it was much easier to deduct the purpose of each line of code.
Our approach
Over several days we compared and harmonised this code, ultimately separating the both CSS and JS each into a single ‘global’ file, which would be used by all sites, and a single ‘local’ file for each website, with code specific to that site.
Once this was dealt with, all that remained was to set up a single, central domain to serve these files. Here we opted to stick with the standard Joomla! Template directory structure:
CSS
data.domain.com/templates/name/css/custom.css
data.domain.com/templates/name/css/local/site1.css
data.domain.com/templates/name/css/local/site2.css...
JS
data.domain.com/templates/name/js/custom.js
data.domain.com/templates/name/js/local/site1.js
data.domain.com/templates/name/js/local/site2.js...
As an initial, temporary solution to load these centralised files we modified the main template index.php of each site manually to point at data.domain.com explicitly.
Everything worked, and it was with great joy that we deleted all remaining CSS/JS from within the individual Joomla instances … and still, everything worked. A good start.
Centralising PHP files
Template files
The template we were using had been developed by a third party on the basis of JoomShaper’s SP Page Builder.
We centralised most template files (e.g. index.php, error.php, offline.php, component.php) and also removed many of the unnecessary JS/CSS ‘clutter’ that is common with commercially developed templates.
Since not every site required custom CSS/JS, we set up the index.php to first check if these files were present (using PHP filepath) and only then to load them (by URL).
Extension layout overrides
The centralised sites used a couple of same extensions. We needed to modify the layouts of said extensions to better match the client’s wishes. Those overrides were also centralised to keep everything uniform.
SPPB Addons
We centralised most of the PHP layout overrides and also added several new addons of our own – centrally across all of the client’s sites.
Google CSE integration
We centralised the code that integrated an external search engine. Used for the search function across all sites. We have written a Blog post that explains this specific implementation.
Read about our implementation of Google CSE in a central way across all sites.
Our approach
Local file replaced by ‘shell’
$file_path = realpath( __FILE__ ); include $_SERVER['DOCUMENT_ROOT'] . '/_php/central.php';
Absolute filepath stored in central.php
$data_directory = 'data.domain.eu'; $data_path = str_replace( basename($_SERVER['DOCUMENT_ROOT']), $data_directory, $file_path ); include $data_path;
What else did we centralise?
- We created a single central XML file with ReReplacer rules with shortcodes
- We extended the core function JText via a dedicated plugin to allow centralisation of language strings
- We configured DOCman to serve PDF files from a central repository
- A central font-face icon file with corporate vector icons
- Custom backend CSS (e.g. bespoke layout for custom fields)
Experiences and lessons learned
Joomla is awesome
Joomla! proved it can be adapted well to an ‘enterprise CMS’ scenario, running 20+ sites in parallel, while remaining easy to manage/maintain. Our client’s staff are all big Joomla! fans.
Bugs/errors were centralised too
If you break something that’s centralised, it can break all 20 websites at once (error.php). If you break 20 websites at once your client looks at you like this ****
Development
This new centralised scenario quickly necessitated a dedicated deployment workflow/tool to mitigate increased risk of breaking many sites at once. Over the months that passed, we implemented our own tool for this.
If you want to read more about the tool we made to ease our developer needs, read about Building an elegant Joomla development workflow using Akeeba Unite.