About Jahia JavaScript Modules

May 25, 2024

Why Jahia isn’t just proposing a headless API

Although it is possible to use Jahia as a headless DXP (all of its APIs are available as GraphQL APIs), there are some clear advantages to having a modern templating system based on JavaScript. Pure headless projects, although very flexible, also come with higher integration costs, which not only occur at the initial development stage but also when any changes are needed to the solution.

Here is a table summarizing the advantages of Jahia’s approach:

Feature Jahia DXP Pure Headless CMS
High-level Architecture Modular: Everything is modules Microservices
Content & presentation coupling Decoupled: Even though presentation and content are on the same platform, they are decoupled, and the content can be accessed via a well-defined API. Decoupled: HTTP calls are used from the presentation layer to the content
Ease of Setup Generally easier to set up with less technical expertise. Requires more setup, especially on the front end.
Operational Complexity Simpler operations with everything under one system. More complex, involves managing multiple systems.
Cost Potentially lower overall due to reduced development needs, including lower maintenance costs Can be higher due to specialized staff and development costs. These costs will remain high in maintenance, especially for long-running projects
Authoring experience (In content-editing, preview) Tight integration, immediate preview of content as it will appear. Navigation is fully integrated with site and page concepts Separation of content and presentation, previews might need additional tools. Navigation is not defined and will have to be managed or reimplemented for each project
SEO Optimization Built-in features are typically included. May require custom development for optimization.
Security Standardized security measures are easier to manage. Potentially requires more complex security management across systems.

 

What makes React & JSX the best templating language in 2024?

On the front-end technologies side, many different frameworks (such as Angular, React, and Vue) are available for developers, but React remains the most popular and possibly the most productive one since the library of ready-to-use components (such as MUI) is very large. Using a popular framework also means it’s going to be easier to find developers with the corresponding skills.

React provides a very focused presentation layer (as opposed to Angular that is more complete but also causes more integration issues) that is now also available on the server side with React Server-Side Components (aka React SSR). React’s templating syntax - JSX - makes it easy to mix JavaScript and HTML to be able to build single-file components that embed everything that is needed to render a component.

 

The combination of React SSR and JSX makes it an excellent choice for a templating language for a modern DXP such as Jahia.

 

As Jahia integrates React SSR and JSX directly into the core of its templating and view system, all the existing functionality, such as on-page content editing, previewing, publishing, and caching, works transparently without the need for custom integrations or new frameworks.

Developers can be very productive and use modules to split larger projects into smaller parts that can be developed and tested independently. Maintenance is also easier as modules can be modified separately without having to redeploy all the solutions.

Jahia’s deployment system also shines at being completely dynamic, meaning that there is no need to restart the server to deploy changes to any modules, including Jahia JavaScript modules.

What about React server components ?

Introduced as an experimental feature, React Server Components aims to let developers build apps where components can be rendered on the server and sent to the client as minimal, interactive units of UI. Unlike SSR, which sends a static HTML snapshot of the component tree, Server Components enable dynamic server-side rendering capabilities, allowing parts of the React tree to be re-rendered in response to interactions without affecting the entire tree.

React Server components were evaluated as a possible solution for building server-side templates for Jahia, but they were not selected for the following reasons:

  • The technology is still young and immature
  • Actions were not yet implemented
  • Their asynchronous nature caused serious integration issues
  • Due to their async nature, it also introduces some complexity in component development and maintenance
  • Jahia’s fragment cache offsets the benefits of using React server components
  • Making it mandatory to use a rendering client-side Javascript was not something we wanted to require of our developers.
  • Developers should have the choice of what they want to use on the client side.
  • Server-side rendering components were a better fit for Jahia’s architecture.

Benefits of JavaScript modules compared to other technologies

​​In order to understand the benefits of JavaScript / JavaScript modules, we will compare them to other technologies, such as Jahia’s Java modules and NextJS for headless development.

Let’s do a quick presentation of each technology before comparing them.

Java Modules

Java modules in Jahia are traditional server-side components that run on all versions of Jahia's content management system (CMS). These modules are typically developed using Java and utilize the Maven build system for managing dependencies and packaging. The primary language used for templating is Java Server Pages (JSP). Java modules are integrated tightly with Jahia's core features, such as CMS navigation, cache, and authentication systems.

JavaScript (NPM) Modules

JavaScript modules in Jahia, available from version 8.2 onwards, allow developers to build functionalities using JavaScript and Node.js ecosystems. These modules are packaged using NPM and typically use JSX for templating. Although they operate within the Jahia environment, they do not require a separate runtime and are designed to work seamlessly with the CMS's navigation, cache, and authentication, just like Java modules.

NextJS (Headless) Applications

NextJS is a React-based framework that enables the development of server-side rendered and statically generated web pages. In Jahia, NextJS applications can be developed as a combination of modules and JavaScript packages but require a separate packaging and deployment runtime. Unlike Java and JavaScript modules, NextJS applications do not integrate directly with Jahia’s CMS navigation, cache, or authentication out of the box and often use GraphQL to access content. NextJS applications will usually use Jahia’s Headless GraphQL API to implement their functionality.

Comparison of Java Modules, JavaScript modules, and NextJS Applications in Jahia

The following table compares the three technologies.

  Java Modules JavaScript (NPM) Modules NextJS
Availability All Jahia versions 8.2+ only Depends on the Jahia module tech used (Java/JavaScript)
Requires separate runtime No No Yes
Requires GraphQL queries to access Content No No Yes
Works with CMS navigation Yes Yes No
Works with CMS cache Yes Yes No
Works with CMS authentication Yes Yes No
Packaging Maven / jar NPM / tgz NPM / tgz
Reusable components Tag libraries React components React components
Module descriptor pom.xml package.json Separate (Java/JavaScript) module
Content type definitions definitions.cnd definitions.cnd definitions in separate module(s)
Main language Java JavaScript JavaScript (NextJS), Java/JavaScript (Modules)
Templating / view language JSP JSX JSX
Templating Jahia Studio JSX NextJS Routing
Business logic (actions, filters, ..) Java Coming up: JavaScript NextJS Actions
Labels properties JSON JSON dictionaries
Hot deploy Hot deploy for views in the local environment “yarn watch” deploys the whole module as you update it. Also works with remote environments NextJS Fast Refresh technology but only works locally or remotely using Visual Studio Code Dev Containers
Recommended IDEs Intellij + Jahia Studio VS Code, Eclipse, or IntelliJ VS Code or IntelliJ

 

Jahia recommends using the Java or JavaScript module technologies for most projects, as they offer the best combination of ease of use, strong integration, and the fastest time to delivery. NextJS, although possible, should only be used in cases where there is a very strong case for it, for example, when integrating with an already existing NextJS codebase.

Comparing Jahia with traditional and headless CMS

Jahia has quite a unique proposition in terms of addressing projects, so it might help to compare it with traditional and headless CMS.

  Traditional CMS Headless CMS Jahia
Content API ? (depends) Yes Yes
Server-side rendered content Yes Yes (using NextJS, Astro, etc.) Yes
Client-side Yes Yes Yes
Shared framework between server side and client side No Yes Yes
Good developer experience ? (depends) Yes Yes
Developers can choose their head No Yes No
Server-side business logic ? (depends) No Yes
UI extension ? (depends) ? (depends) Yes
Content-based CMS ? (depends) No Yes
In context editing Yes ? (depends) No

 

Benefit from all the React tooling

The advantage of using React JSX as a server-side rendering technology is that all the usual tooling associated with it can be used, such as:

  • React: The core library for building user interfaces in JavaScript.
  • React Rehydration: SSR involves sending HTML with initial data to the client. React rehydration then takes over on the client side, attaching event handlers and making the HTML interactive again.
  • Webpack: A module bundler used to bundle JavaScript, CSS, and other assets for the browser. It's often configured with server-side rendering in mind to support both client and server builds.
  • CSS Modules / CSS-in-JS: Techniques for styling React components. CSS Modules allow scoped CSS locally to components, while CSS-in-JS libraries like styled-components or Emotion offer CSS styling directly within JavaScript.
  • ESLint / Prettier: Tools for enforcing code style and catching errors in JavaScript code. They help maintain consistency and improve code quality across the project.
  • Cypress: Cypress is an end-to-end testing framework for web applications. While it's commonly associated with testing single-page applications (SPAs), it can also be used for testing SSR applications. Cypress allows you to write and execute tests that interact with your application in a real browser environment, including both client-side and server-side rendering scenarios.
  • Webpack Loaders and Plugins: Additional tools integrated with Webpack for handling specific tasks like image optimization, CSS preprocessing (e.g., Sass or Less), and code splitting.
  • TypeScript: TypeScript is a superset of JavaScript that adds static typing to the language. It's commonly used in React SSR projects to improve code maintainability, catch errors at compile time, and enhance developer productivity. TypeScript provides features like type checking, interfaces, and enums, which can be particularly beneficial in larger codebases.
  • GraalVM Chrome Debugger: GraalVM is a universal virtual machine that supports multiple programming languages, including JavaScript. The GraalVM Chrome Debugger is a debugger tool that allows you to debug JavaScript code running on GraalVM-based runtimes, such as Node.js. It provides features like breakpoints, stepping through code, inspecting variables, and profiling performance. While not specific to React SSR, it can be useful for debugging server-side JavaScript code in SSR applications running on GraalVM-based environments.
  • JSDoc: JSDoc comments provide automatic documentation generation, enhance type inference, improve IDE integration, and enhance code readability and maintainability in React SSR projects.

Interoperability with Java components & services for existing users

Thanks to GraalVM, it is entirely possible for JavaScript code to access Java libraries and services directly without needing to go through layers such as HTTP requests. Java objects may be exposed by the server to make them available to JavaScript/JSX code, as is the case with the useServerContext that exposes the following structure :

/**
 * A context object that gives access to the underlying Jahia Java objects that are part of the current rendering context
 */
export interface ServerContext {
    /**
     * Jahia's rendering context, it provides access to all kinds of context information, such as the current request, response, user, mode, mainResource and more
     */
    renderContext : RenderContext;
    /**
     * The current resource being rendered, which is a combination of the current node and its template/view information
     */
    currentResource : Resource;
    /**
     * The current JCR node being rendered
     */
    currentNode : JCRNodeWrapper;
    /**
     * The main JCR node being rendered, which is the root node of the current page
     */
    mainNode : JCRNodeWrapper;
    /**
     * The OSGi bundle key of the current module being rendered
     */
    bundleKey : string;
}

    

All the types in the interface are actually Java classes exposed through the useServerContext() hook to be accessible in React components. This makes it possible to access all the power of Jahia’s API while still remaining inside the JavaScript/React development environment. There are other Java objects and functions available through the server object.

Be careful when calling Java code

It is important to note that only the documented objects are considered supported. All other objects that might be accessible, for example using Java.type() to access other Jahia classes is not supported and these may be deprecated, removed, or modified at any time, so it is recommended to avoid using them. If there are objects that you believe Jahia should expose, please open a ticket with Jahia support team to inform us of your requirements.

Also, it is generally recommended to minimize the number of calls to Java code and to build as much as possible in JavaScript.

Java Interoperability Q&A

In this section, we will answer some common questions that users might have about JavaScript modules.

Can I add JSP in JavaScript module ?

No this will not work. While the system will detect the JSP files, they will require OSGi imports in the MANIFEST.MF file that are generated by the Jahia Maven Plugin that is not used when building JavaScript modules. Anyway this would never be recommended as the JavaScript modules are designed to fully replace all the needs for JSP, including replacing the functionality of tag libraries with custom React components.

Can I add JSX views to my Java modules?

This is technically possible although not easy, but it is not recommended at all. It is much better to create a separate module that will for example access some functionality provided by a Java module.

Can I mix JavaScript modules and Java on the same website?

Yes, mixing JavaScript and Java modules is fully supported on the same website and is a very common deployment scenario for users who are upgrading from previous versions. It is also possible to use elements registered by one type of module in the other type, for example, using content definitions or Java services. For new projects, it is, however, recommended to choose between JavaScript modules and Java modules and ideally use one type of module to simplify project maintenance.

On the same page?

Yes it is possible to use JavaScript and Java modules on the same page, this is a supported scenario. The same recommendation as in the case of website applies, avoid mixing the two types if possible, to make maintenance of the modules easier.

Comparing React server-side and client-side components

React offers two main approaches to rendering: client-side rendering (CSR) and server-side rendering (SSR). Each method has its own advantages and considerations.

Client-Side Rendering (CSR)

In CSR, the entire React application is loaded in the browser. This means that the initial page load is faster because only minimal HTML is sent from the server. Once the initial HTML is loaded, the JavaScript bundle containing the React components is fetched and executed, allowing the application to render and function dynamically. CSR is ideal for applications where interactivity and real-time updates are essential, such as single-page applications (SPAs).

Server-Side Rendering (SSR)

In SSR, the React components are rendered on the server into HTML before being sent to the client's browser. This means that the user receives a fully rendered page directly from the server, which can improve performance, especially in scenarios where search engine optimization (SEO) or initial page load speed is crucial. SSR can also enhance perceived performance by providing meaningful content to users more quickly.

Hooks and Components Not Compatible with SSR

While most React features work seamlessly in both CSR and SSR, there are some hooks and components that are not compatible with server-side rendering. This is because SSR requires rendering on the server, where certain browser-specific APIs and lifecycle methods are unavailable. Some examples of hooks and components that may not work properly or cause issues in SSR include:

  • Window and Document Hooks: Hooks like useEffect or useState that rely on browser-specific objects such as window or document may not work as expected in SSR because these objects are not available on the server.
  • Lifecycle Methods: Class-based lifecycle methods like componentDidMount or componentDidUpdate do not exist in functional components and are not supported in SSR.
  • Third-party Libraries: Some third-party libraries may rely on browser APIs and may not be compatible with SSR out of the box. Developers need to ensure that any libraries they use are SSR-compatible or provide SSR-specific implementations.

Reusing React components between CSR and SSR

Building React components that can be used both in client-side rendering (CSR) and server-side rendering (SSR) involves considering the differences between these rendering environments and writing components that are compatible with both.

Here's a guide on how to build such components:

  • Avoid Browser-Specific Code: Write components that do not rely on browser-specific objects or APIs, such as window, document, or localStorage. Instead, use feature detection or provide alternative implementations where necessary.
  • Stateless components: as much as possible prefer stateless to stateful components when developing components that must work in both environments, as they are simpler and will therefore be easier to get to work everywhere.
  • Conditional Rendering: Use conditional rendering to handle cases where certain features or behaviors are not available in SSR. You can conditionally render components, features, or data based on the environment using techniques like ternary operators or logical && operators.
  • Test in Both Environments: Test your components thoroughly in both CSR and SSR environments to ensure they behave as expected and handle edge cases gracefully. Tools like Jest and Enzyme can help with testing React components.

Benefits of building components that work in both CSR and SSR include:

  • Reusability: components that can be reused in both environments will prove useful over time to simplify development and maintenance.
  • Skills: The difference between CSR and SSR is small, so developers skilled in one environment will be capable of working on both.
  • Packaging: It is possible to build libraries that work in both environments, managing the lifecycle of these libraries separately from the components that use them, easing development, testing, and deployment.