Decoupled or Headless CMS fully or progressively decouples the frontend from the backend. In this approach, Drupal serves as a backend content vault, while one can choose a frontend technology that suits them best for a project. The Decoupled Menus initiative is a step towards exploring potential of Decoupled Drupal integration with various frameworks by making Drupal Menus as an API to be integrated with a modern JS framework such as React/Next.js. This idea has been officially launched as Drupal Core Strategic Initiative. You can find more information on this initiative here.
Source - Drupal.org
We, at QED42, have chosen NextJS - a Server Side Rendering and Static Generation framework of React as the frontend to pre-render the menu. Due to its features like prefetching, fast refresh, automatic routing, compilation and bundling, performance optimization, SEO, and much more.
Why do we Decouple our Menus?
Background: Every time a non-developer wants to change a menu item on the Drupal side, a developer has to get involved to implement it on the JS side. That developer must change and rebuild the code, and then deploy those changes to production. These steps may take days to complete depending on the availability of the developer, and the complexity of the deployment process.
Other reasons are as follows –
- Recognize improvements for Headless CMS, with the menu as a use case
- Not all Drupal modules need to be modules
- Especially while updating the version of Drupal, most of these do not require the database and other features of Drupal
- Some Drupal modules do not make complete utilization of Drupal and can be built in other languages
- Shorter bandwidth to rebuild all modules in a reasonable timeframe.
- NextJS came into view because its modules are much simpler and faster to write.
- We can create features that are missing and much needed to develop.
- We do not want to create functionality that already exists.
- Make Decoupled Drupal and menus attractive to non-Drupal FE developers.
Please Note: You can join the Decoupled-menu-Initiative slack channel here. The weekly meetings take place every Tuesday at 14:00 UTC and again at 4:00 UTC at the Slack channel itself.
In support of this initiative, we will present you with a NextJS menu component that recursively renders the menu data provided by the Drupal API and displays it in the form of a dropdown. This can be considered Part-1 of our “NextJS for Decoupled menus” series. In this blog we will share the setup, components, prefetching and rendering of the menu. In the next part, we will be integrating this with Drupal.
Deployed on: https://nextjs-decoupled-menus.vercel.app/
A glimpse of the Drupal menu API (data)
The menu APIs provided by Drupal have JSON data stored in a linear structure rather than a hierarchical structure. Therefore, a frontend developer has to construct a tree-like hierarchy from the data to render the menu in a drop-down format. That is what we have focused on currently and have explained in the next section. Given below are the APIs, with the Drupal-menu-hierarchy key for each sub-menu, revealing its hierarchy level.
What does our NextJS code do – Static Generation
Architectural Diagram of Current Application Structure
The following steps describe the functionality of our existing application –
Step 1: The_app.js is the root file of our application. The Component returned by it is wrapped in our custom Layout component, with page properties passed as children. This file also utilizes the Head Component of NextJS as the header of a page and includes the title and all the meta-tags that are one of the reasons for our 100% SEO.
Get better performance, accessibility, SEO and much more with NextJS
Step 2:Theindex.js file is the Home page of our application. It performs like a logical component because it fetches data from the provided Drupal API using fetch()in getStaticProps()and returns the JSON data as props to _app.js.
Step 3:The components folder, which lies outside the pages folder contains our presentational components - menuBar, Layout and Footer.
Step 4:The Layout component further passes the props-children to the menuBar, which was passed by the _app.js component. It also calls the Footer component in the end.
Step 5:The menuBar component makes use of the Drupal-API data passed as props to render it as a menu of our page. we have used the menuHelper utility to create a menu Tree and return it to the menuBar.
- Mapping through the menu data array, we have used the given menu-hierarchy of each menu object to add submenus to the mainRoot as children.
- We further iterate through each sub-menu to add further children until the leaf node (last menu item) is reached based on the given hierarchy.
- This creates our menu Tree in the mainRoot object using Loops.
- Then, we have rendered the main level of the menu Tree using the TreeView API of Material UI.
- Lastly, the inner root levels are rendered Recursively using the TreeItem API of Material UI in the user-defined method createTreeItem(). This method checks if the menu item is the last item in its particular hierarchy. If yes, then it simply displays the content/link, else it recurses further till the last menu-item is reached.
Step 6:The Footer component simply displays the Copyright content.
Step 7:The _document.js file enables the material UI icons to be available at the first render, avoiding unusual FOUC.
Conclusion & Future Work
The purpose of this blog was to showcase how one can use the Drupal Menu API with NextJS as the frontend for pre-rendering and how it improves SEO ranking. At the moment this application is only deployed to Vercel, and has not yet been converted into a package. Stay tuned for our upcoming blog that will revolve around integrating our NextJS package with Drupal. Interested to know more about the other Drupal Initiatives? Click here to read more.