Kicking off decoupled Drupal & React projects with boilerplate
Yet another boilerplate?
In addition to the freedom of choice among multiple tools doing the same but differently, it’s not that easy to predict the cost of selecting the wrong tool (and you will be making mistakes, just accept it). For instance, how hard it will be to switch from yarn to npm after 1 year of development of a certain project if it will turn out that yarn is not your tool? I can easily name a hundred issues like this which may backfire in the long run. There are a few examples in our team where certain choices resulted in unreasonably complex development and support, so we see it as a serious concern.
Cracking through the learning curve of the decoupled world led us to the idea of creating a boilerplate to kick off every new decoupled project based on our experience for best practices from past projects. Also, we don’t want other developers to make the same mistakes as we did. That’s the beauty of open source, isn’t it? This initiative gave birth to the Drupal + React Boilerplate project.
The main idea behind the boilerplate
The idea of the project is dead simple: to collect all tools which proved themselves as reliable for development of production-ready decoupled applications from both Drupal and React worlds and make them play together.
The biggest challenge was to decide the amount of features we wanted to put into the boilerplate. Obviously, the more features a boilerplate has out of the box, the more opinionated they are and the less interesting it becomes for other teams. Therefore we decided to stick to the reasonable minimum set of opinionated tools and provide just enough solutions to kick off any decoupled project, but leave the door open for developers’ creativity. You’ll definitely find that there are some opinionated decisions in the boilerplate but they are there for a good reason.
What’s included on a high level
- One command installation from scratch to working and connected React + Drupal applications
- Docker-based infrastructure for literally everything (mostly powered by Docker4Drupal)
- Drupal backend configured for decoupling (powered by Contenta CMS)
- React frontend with server side rendering (SSR), code splitting and hot reloading (powered by Next.js)
- Boilerplate CLI for routine operations (powered by Makefile)
- 3 types of automated tests (end-to-end, API, unit) with examples (powered by Codeception)
- Code quality checks (powered by PHPCS and ESLint)
- Continuous Integration system with automated project installation / testing / code quality checks (powered by CircleCI)
- Ready for deployment (out of the box Platform.sh but not exclusive)
One command installation
Something we’re really proud of is how easy it is to install the boilerplate. It makes the barrier to entry so low! The only piece of software that has to be installed is Docker (with Docker Compose) and you’re all set.
Frankly saying, we’ve adopted this “one command installation” approach for all projects at SystemSeed and find it super helpful. Every time someone screws up their local installation, reinstalls the operating system or buys a new Macbook — installing a project to the state where it’s development ready is just one command and a cup of coffee away!
At SystemSeed we use Docker4Drupal for several years already and find it very valuable and flexible for our needs. Therefore standardizing decoupled infrastructure on top of it felt reasonable. We added just 2 more images to support automated testing inside Docker containers and the remaining images were configured to fall in place properly.
A nice extra feature here is the Docker composition file customizable per dev environment. The project installation process generates .docker/docker-compose.override.yml file which is under git ignore, allows developers to customize their development environment (i.e. enabling XDebug) without fear of committing the changes back to the repository.
Drupal powered by Contenta CMS
We’ve chosen Contenta CMS distribution as the standard for the boilerplate, because it was built by people who know how to handle decoupled stuff! Even though what the distribution is shipped with can easily be reproduced with pure Drupal, having it as a standard Drupal profile is still valuable. Otherwise we would have to keep our package.json up to date with rapidly growing decoupled Drupal ecosystem, which isn’t very fun.
Basically, Contenta CMS comes with set of pre-installed modules for exposing content in Drupal, therefore we believe it a good starting point, especially if you are not sure where to start the decoupled journey.
React powered by Next.js
I’m sure you know that React is an outstanding library for building UIs. But you don’t want to build your entire infrastructure with pure React from scratch. There are plenty of micro-frameworks or boilerplates which come with their own set of tools and features to quickly kick-off development (like hot reloading, code splitting, etc).
Originally we fell in love with Create React App so much that we decided to use it for a small production project. Eventually it turned out that it does not support server side rendering and code splitting which was a surprise. There were some hacky ways around it and eventually it all came out okay, but it forced us to pick micro-frameworks more thoroughly.
The micro-framework we’re really happy with is Next.js. It supports server side rendering, hot reloading, css and js code splitting and other nifty features you’d want as a developer. After building several large production-ready projects with it, we’re confident that it’s still a good choice going forward, therefore it made its way into the boilerplate as well.
The frontend part of the boilerplate also includes features like:
- HTTP Auth support (for publicly accessible dev environments)
- Compression for all serving assets
- Redux + Saga (we know it’s a bit opinionated, but seriously, we’re fond of them!)
- Example of data fetching from Drupal with errors handling
- And a few other small things
If you’re in the industry for 10+ years like me, you’ve likely heard about the good old Makefiles tool from Linux for automation of compilation projects built with C/C++. Recently it was discovered by web developers that Makefiles can actually also be used for the automation of other routine operations, even though Makefiles were not designed for it.
Personally I enjoy Makefiles for 2 reasons:
- It ships by default with most Linux and MacOS systems so no need to install anything extra (helpful for including this into open source projects)
- They’ve got freaking awesome namespace! Here’s a good example: if you add “install” or “code:check” target to the Makefile, the resulting commands will be make install and make code:check. Feels like you’re literally talking to the machine asking it to get something done. What can be easier to memorize?
So, we’ve decided to include a standard set of commands which are likely to be used by every developer, i.e. dev environment spin up / shut down, access drush or yarn CLI inside of containers, and so on. The full set of commands are available here.
Automated testing approach is always the most debatable and opinionated thing in our industry, so I’ll try to be very careful here. Everyone does testing for their clients their own way and that’s fine (the most important thing is that devs actually do it in the first place). We found our balance in this field by covering projects with unit and API tests for the backend and end-to-end (also known as “acceptance”) tests for the frontend. If you’re interested in more details about tests, you’re welcome to read the articles written by our very own Kate Marshalkina (this one and this one).
In most cases the Drupal backend is not what end users get to see, therefore end-to-end testing might be overkill. We built a Docker image which connects Codeception to a Drupal database (it’s already included in the boilerplate) and it makes the testing of methods and project state as easy as writing the usual Drupal code. Check out this example. Yes, we know that’s not what unit tests are supposed to be — database connection is not normal. However, this is our way of putting unit tests “on steroids” and we’re genuinely happy with their usability.
Another important type of testing from our point of view is API testing. As soon as something has changed from the default output of Drupal’s JSON:API or whatever you use to expose the content, it makes a lot of sense to write a test for it! Bear in mind that in the decoupled world API endpoints are the de-facto database for your frontend application. Who can argue with the fact that data source must be reliable?
Last, but not least, we have end-to-end (aka “acceptance”) testing. It emulates real user behavior in a real browser (in our case it’s Chrome). Over the past 7 years these type of tests have proven their worth for every client project we had. In the decoupled world they help us test frontend applications. What’s really cool in the boilerplate’s version of end-to-end tests is that you can dynamically pull data from the Drupal database using the usual Drupal API and run checks against this data on the React side! Here’s an example of the end-to-end test .
Remember, thanks to the boilerplate’s CLI, running tests is now a trivial operation.
Code quality checks
Continuous Integration (CI)
The existing CI configuration for the boilerplate ensures that the project is always ready-to-install, has the expected level of code quality and passes all tests. It’s recommended for people who’ll be using the boilerplate to keep the existing CI flow and just keep adding features and tests — it will not require any updates to CI. This is still an opinionated way to run the automation of routine operations, however we find it extremely handy!
At SystemSeed we’ve standardized the tool we use for CI across the projects by picking CircleCI. Developers can get really creative with its functions and flexibility.
Instead of the conclusion
We highly encourage you to give the boilerplate a shot! Any positive or negative feedback is highly welcome and will be much appreciated :-)
The main purpose of the project is to provide a super-quick start for decoupled applications development based on…
P.S. Special thanks to Chris Nater for his feedback and encouragement!