The Decoupled Pages module provides a quick and simple way to define new Drupal routes which can be overtaken by a single page application, often written in Javascript using React, Vue.js, or Ember (to name a few common frameworks).
How to create a decoupled page
1. Defining a route
To define a new decoupled page, you define a new route in your module's routing file. The basic structure of your route definition remains unchanged. You can add route requirements, route defaults and route options pretty much as normal. The only caveat is that you must not define a _controller
or _form
route requirement.
Instead, you'll define a _decoupled_page_main
route requirement. The value of this key is the name of an asset library containing your single page application and its dependencies. It should take the form your_module/name
. You can define this asset library in a your_module.libraries.yml
file, but any module can provide an asset library.
Here is an example of a decoupled page route definition:
your_module_name.foo:
path: /some/path/of/your-choosing
defaults:
_decoupled_page_main: decoupled_pages/route_test
requirements:
_access: 'TRUE'
Once your route definition has been created, a new route will be available after you've rebuilt Drupal's cache (make sure to enable your module too 😉).
The decoupled_pages/route_test
asset library is pre-defined by this module. You can use it to test your route without first registering your own library. If your route works, you should be able to visit the path you defined. Check the browser console for a message saying that your route worked.
Warning: _access: 'TRUE'
will make your route accessible to everyone.
2. Adding your single page application
This module will place an empty <div>
into the main content region of your active theme. It will have the HTML ID decoupled-page-root
, like so:
<div id="decoupled-page-root"></div>
Your JavaScript can attach to that element.
Once you've defined an asset library of your own. Go ahead and point your route's _decoupled_page_main
to that library.
3. Customize for your needs
Paths routed in JavaScript
If your single page application defines its own routes, you'll want to make sure that your users can link directly to them. In order to do that, Drupal needs to know about those paths. You can add additional paths for Drupal to serve your application code by setting the _decoupled_page_paths
route option, like so:
options:
_decoupled_page_paths:
foo: /some/path/of/your-choosing/foo
bar: /some/path/of/your-choosing/bar
foobaz: /some/path/of/your-choosing/foo/baz
Adding additional CSS and JavaScript libraries
You may also need the ability to attach additional JavaScript or CSS to your decoupled pages that can't be included in your main asset library. You can tell Drupal about those assets by defining the _decoupled_page_assets
route option, like so:
options:
_decoupled_page_assets:
- your_module/some_extra_css
Passing configuration to your JavaScript application
In order to keep your JavaScript application from hardcoding certain assumptions (e.g. API URLs), you may want to pass configuration to your JavaScript via the root data element. Custom data attributes are an excellent way to pass information from the backend to your JavaScript application. To do that, you can specify a _decoupled_page_data
route default, like so:
defaults:
_decoupled_page_data:
api-base-path: /my/api/v1
Your data attribute names must be strings containing only the lower-case letters a-z and dashes and must not begin or end with a dash. You data attribute values must also be strings. You can access these data attributes from JavaScript, like so:
const root = document.getElementById('decoupled-page-root');
root.dataset.apiBasePath === '/my/api/v1'; // true
Notice that the dasherized key name that you defined in YAML is lower-camel-cased in JavaScript. This is a browser behavior, not a feature of this module.
Defining data attributes dynamically
If you need to be able to define data attributes described above dynamically, you may do so. There are three steps. First, create a class which implements Drupal\decoupled_pages\DataProviderInterface
(see the decoupled_pages_test
module for an example implementation). Second, define a service in your_module.services.php
tagged with decoupled_pages_data_provider
:
services:
your_module.your_custom_data_provider:
class: Drupal\your_module\YourCustomDataProvider
tags:
- { name: decoupled_pages_data_provider }
Finally, register your data provider on your decoupled route definition by its service ID:
defaults:
_decoupled_page_data_provider: your_module.your_custom_data_provider
The rules for data attribute names and values described above still apply.
Project information
- Minimally maintained
Maintainers monitor issues, but fast responses are not guaranteed. - Maintenance fixes only
Considered feature-complete by its maintainers. - Module categories: Decoupled
- 90 sites report using this module
- Created by gabesullice on , updated
- Stable releases for this project are covered by the security advisory policy.
Look for the shield icon below.
Releases
Drupal 10 support
Development version: 8.x-1.x-dev updated 18 Oct 2024 at 08:34 UTC