Drupal decoupled backend with JS frontend
Best practices, basic steps, lists of tools and tips to help you integrate a Drupal 8.x+ backend with a JavaScript frontend.
Note: Some examples below refer only to React development and are not JS agnostic.
Table of Contents
JS
Popular JS frontend frameworks
Compare JS frameworks
Online services to use when comparing frameworks (trends, popularity, usage, downloads, benchmarks etc).
- Questionnaires
- Trends
- Popularity
- https://www.githubcompare.com/vercel/next.js+facebook/react+angular/angular.js+vuejs/vue
- https://star-history.com/#facebook/react&vuejs/vue&angular/angular&vercel/next.js&Timeline
- https://www.hntrends.com/2020/dec-year-unlike-any-other-tech-tools-didnt-change-much.html?compare=AngularJS&compare=Ember&compare=React&compare=Vue
- https://frontpagemetrics.com/r/reactjs#compare=vuejs+angular2+sveltejs+nextjs
- Usage
- Analysis & dependencies
- Benchmarks
- Browser Support
Things to consider when selecting a frontend framework (in no particular order)
- Performance
- Stability
- Development experience
- Documentation and support
- Vendors behind
- Complexity and learning curve
- CRUD requirements
- Serving multiple platforms and consumers
- Existing in-house knowledge
Tools for JS development
Note: Before using these tools try to use the built-in, bundled tools you get from each framework.
- VSCode
- nvm, npm (no need to use
yarn
overnpm
in 2022) - Typescript
- Storybook
- Babel
- PostCSS
- husky
- JSX
- JSON, JSON API
- Bundlers: Webpack, esbuild
- Code linting etc: EditorConfig, ESLint, Prettier, JSLint
- Code generators: Hygen, nx, ReexJs CLI, generact
- Testing: Jest, Cypress, testing-library, nightwatchjs, playwright
- Data fetch: axios, react-query, SWR, node-fetch
- Data parser: qs, html-react-parser
- Routing: React Router
- Quality: danger
- Logging: pino
- Documentation: jsdoc
- Performance: next-boost, react-lazy-load-image-component, node-cache, webpack-bundle-analyzer
- Security: (npm built-in:
npm-audit, npm-outdated, npm-doctor
npm-check, snyk, npm-check-updates - State management: redux, zustand, recoil, jotai
- Translations, i18n: lingui, polyglot
- Mocks, faker: sinon, faker, JSON Server fake API
JS terminology
In order to start with JS you sould be familiar with the basic terms below. Note that some of them may refer to a specific JS framework.
- CORS
- Cache
- Code splitting
- Components
- Composition
- DOM
- Data fetch
- HMR (Hot Module Reload)
- HOC (Higher Order Components)
- Hook events
- Injection
- Invalidation
- Isomorphic
- PWA
- Props
- Routing
- SEO
- SSR, SSG, ISR, DSG, CSR
- SWA
- SideEffect
- State
- Web Vitals (LCP, FID, CLS)
- a11y
- es6/es7 etc
- hydration
- i18n
- library
- module
- node daemon
- package
- virtual DOM
Learn JS frameworks basics
JS app structure
- Move files around until it feels right
- Group by file type
- Avoid too much nesting
- Keep with the trends (e.g. use common names like "
src, public, pages, __tests__, docs
" etc
ToDo: Add some example structure here..
Styling a JS app
- Prefer "CSS in files" approach except if there are specific requirements.
- For inline styles you can use utility CSS libraries like tailwindcss and Windi CSS.
- For UI building isolation and sandboxing use Storybook, React Styleguidist, React Cosmos, React Preview etc.
Drupal
About Drupal decoupled solutions
- https://dri.es/headless-cms-rest-vs-jsonapi-vs-graphql
- https://dri.es/how-to-decouple-drupal-in-2019
- https://dri.es/drupal-looking-to-adopt-react
- https://dri.es/advancing-drupal-web-services
- https://www.drupal.org/industries/decoupled
- https://www.lullabot.com/articles/should-you-decouple
- https://www.softescu.com/en/blog/fully-decoupled-or-progressively-decoupled
- https://medium.com/analytics-vidhya/decoupled-drupal-as-a-solution-bd0ec25f39cf
- https://opensenselabs.com/blog/articles/different-options-decoupling-drupal
- https://www.lullabot.com/articles/decoupled-hard-problems-routing
Drupal slack channels
- #decoupled
- #headless
- #graphql
- #contenta
- #react
- #nextjs
- #gatsby
- #druxt (NuxtJS)
- #vue
- #custom-elements
Drupal modules
Note: Modules in emphasis are the most used across the Drupal universe.
JSON API (core)
jsonapi.org, JSON API: Drupal core module documentation
- Basic
- decoupled_kit
- decoupled_menus
- drupal_jsonapi_params
- entity_view_mode_normalize
- fieldable_path
- jsonapi_aliases
- jsonapi_comment
- jsonapi_embed
- jsonapi_extras
- jsonapi_menu_items
- jsonapi_views
- jsonrpc
- pager_serializer
- rest_absolute_urls
- rest_menu_detail
- rest_menu_items
- rest_normalizer
- https://github.com/pmelab/contextual_aliases
- Data
- config_pages
- Subrequests, nesting
- jsonapi_include
- rest_entity_recursive
- rest_export_nested
- subrequests
- Routing
- decoupled_router
- entity_router
- Collections
- jsonapi_cross_bundles
- decoupled_pages
- jsonapi_resources
- page_manager
- jsonapi_user_resources
- Search
- jsonapi_search_api
- Preview
- dpl
- jsonapi_node_preview
- jsonapi_node_preview_tab
- Performance
- jsonapi_earlyrendering_workaround
- jsonapi_boost
- warmer
- Images
- jsonapi_image_styles
- consumer_image_styles
- image_derivatives_selection
- image_derivatives_base64_representation
- Rate limits
- rate_limiter
- rate_limits
- API Documentation
- schemata
- openapi_ui_swagger
- openapi
- openapi_ui
- openapi_jsonapi
- openapi_rest
- openapi_ui_redoc
- swagger_ui_formatter
- jsonapi_schema
- social_json_api
- Authentication
- api_proxy
- simple_oauth
- consumers
- cors_ui
- rest_api_authentication
- key_auth
- api_key_manager
- access_filter
- jsonapi_access
- rest_password
- Administration
- restui
- jsonapi_explorer
- jsonapi_node_preview_tab
- restuiextention
- api_proxy
- Forms
- webform_rest
- webform_jsonschema
- rjsf
- Logging
- http_client_log
- request_logger
- rest_log
- restfullogger
GraphQL
(Advice: Do not prefer GraphQL over JSON API except if there are special requirements)
- graphql
- graphql_entity_by_object
- graphql_entity_definitions
- graphql_extras
- graphql_formatters
- graphql_menu
- graphql_metatag
- graphql_node_preview
- graphql_redirect
- graphql_redirect_entity
- graphql_search_api
- graphql_views
- graphql_webform
- preview_graphql
Other
- pdb
- relaxed
- jdrupal
- js_component
Drupal Distributions
- https://www.contentacms.org
- https://www.drupal.org/project/tide
- https://github.com/systemseed/falcon
- https://github.com/codingsasi/acephalous
- https://www.drupal.org/project/ezcontent (using REST, not a decoupled example)
Drupal starter-kits with JS frameworks
- https://next-drupal.org (Next)
- https://druxtjs.org (Nuxt)
- https://stack.lupus.digital (Nuxt)
npm packages for Drupal
- d8-jsonapi-querystring
- d8-subrequests
- drupal-jsonapi-extractor
- drupal-jsonapi-params
- drupal-sdk
- jsonapi-parse
- react-drupal-json-api
Drupal common issues with decoupled
- Displaying embedded entities on CKEditor (eg Media) inside JS components
- Multilingual
- Subrequets and relationships in data
- Customizing of responses like filtering, quering and altering
- Routing and path aliases
- Non entities data (e.g. metatags, redirects, path aliases, image styles)
- Workflows (Content Moderation) and revisions
- Node preview
- Authentication
- Invalidate partial cache
- Forms
Implementation matrix
An example matrix for common requirements of a decoupled Drupal backend with JS frontend.
The table show which part of the app should take care of each functionality.
For example, we could get the site logo from Drupal but we could also use a static image on the JS side as a logo.
Notice that, in some cases, there may be a combination of the two parts or a 3rd party solution (eg an external CDN for image assets).
Requirement | Drupal backend | JS frontend |
---|---|---|
access and permissions | ||
authentication | ||
basic site settings (eg logo, site name, site slogan etc) | ||
breadcrumbs | ||
caching | ||
collections (views VS JSON API entity queries) | ||
CORS | ||
CRUD requirements | ||
embedded HTML on CKEditor | ||
file attachments | ||
forms | ||
image styles | ||
menus | ||
metatags | ||
mocking data | ||
modifying JSON response | ||
multilingual | ||
multisite | ||
partial cache invalidation | ||
path aliases | ||
preview | ||
redirects | ||
relationships and field references | ||
revisions | ||
routing | ||
search_api | ||
sub-requests | ||
third party scripts (eg gtag) | ||
UI translations | ||
workflows (content moderation) | ||
xml sitemap |
Framework: React
- https://reactjs.org
- https://github.com/enaqx/awesome-react
- https://github.com/brillout/awesome-react-components
Learn React
- Thinking in React - reactjs.org
- Complete guide React + Drupal - drupalize.me
- React in patterns
- 30 Days of React - GitHub
- Functional Components
- React Components: https://reactjs.org/docs/react-component.html, https://github.com/brillout/awesome-react-components
- React Hooks: https://reactjs.org/docs/hooks-intro.html, https://usehooks.com
- React Props: https://akd3257.medium.com/what-are-props-in-react-2f822330e3a7
Drupal + React
- Guide: https://reactfordrupal.com
- Starter: https://github.com/systemseed/drupal_reactjs_boilerplate
- Example: https://github.com/DrupalizeMe/react-and-drupal-examples
Articles for React
Framework: NextJS
Why choose NextJS
- Better SEO. Supports SSR, SSG, ISR.
- Built in solutions for common requirements (routing, head/metatags, images, links, font optimization, data fetching, injected scripts, i18n, AMP)
- Built in tools (Typescript, Sass, ESLint, Webpack, env variables, preview mode, polyfills)
- Better Development Experience (DX) (zero config, built in tools, fast refresh)
- Based on React (can use all the React goodies)
Learn NextJS
Drupal + NextJS
NextJS popular tools
- https://swr.vercel.app (React Hooks for Data Fetching)
- https://next-auth.js.org (Authentication for Next.js)
- https://github.com/atilafassina/next-g11n (Translate and localize your Next.js app smoothly)
- https://github.com/next-boost/next-boost (Adds a cache layer to your SSR applications)
Articles for NextJS
- https://www.smashingmagazine.com/2021/11/maintain-large-nextjs-application
- https://stackabuse.com/guide-to-getting-started-with-nextjs-create-a-nextjs-app
Framework: Nuxt.js
Why choose Nuxt.js
- Better SEO. Suppports SSR and SSG.
- Built in solutions for common requirements (routing, head/metatags, images, links, font optimization, data fetching, injected scripts, i18n, AMP)
- Built in tools (Typescript, Sass, ESLint, Webpack, env variables, preview mode, polyfills)
- Better Development Experience (DX) (zero config, built in tools, fast refresh)
- Based on Vue (can use all the Vue goodies)
Drupal + Nuxt.js = Druxt
Druxt = DRUpal + nuXT
- druxtjs.org
- Fully Decoupled Drupal, with Nuxt.js in the frontend.
- Drupal JSON:API Client with Vuex caching.
- Modular Vue.js component library system.
- Slot and Wrapper theming system.
- API and File proxy.
Druxt Quick-start templates
Final tips
- Make it really "decoupled" (except if other requirements)
- Keep it simple. Use the basic tools and extend when needed.
- Less JS packages and less Drupal modules is prefferable.
- Work only with NodeJS LTS versions.
- Think in Components
- Create enough Components
- Modify the state directly
- Add keys on the lists (inside JS Components)
- Declare types, validate functions
- Always test your Components and app
- Dockerize your JS app
- For security updates of npm packages prefer to update the main JS library used (eg Next, React etc) and not the several npm packages independently.
- Drupal: Prefer Drupal modules from core (e.g. JSON API instead of GraphQL)
- Drupal: Do not override the default Drupal field machine names on JSON
- Drupal: prefer quering the
search_api
to get search results on the JS App when using 3rd party search engines like SOLR. - Start with the official starter kits (e.g create-react-app)
CONTRIBUTING
LICENSE
MIT - Copyright (c) 2022 EWORX S.A.