dot CMS

How to Integrate React Components with dotCMS Using Vite

How to Integrate React Components with dotCMS Using Vite
Author image

Freddy Montes

Product Manager

Share this article on:

Important Note About This Approach

While dotCMS strongly recommends implementing a fully headless architecture for new projects (we provide examples for it), we understand that some organizations are in a transition phase from traditional templating to a modern headless approach. This guide presents a hybrid solution that can be valuable in specific scenarios:

  • Transitioning Projects: If you have an existing dotCMS implementation using Velocity templates and want to gradually introduce React components

  • Legacy System Integration: When you need to maintain compatibility with existing Velocity-based templates while modernizing specific components

  • Incremental Migration: For organizations taking a step-by-step approach to moving from traditional to headless architecture

For new projects or complete redesigns, we strongly encourage adopting a fully headless approach to leverage the full benefits of modern web development practices and dotCMS's robust Page API and JavaScript SDK which can be fully integrated with our Universal Visual Editor.

Overview

This hybrid approach allows you to:

  • Develop React components locally with modern tools

  • Automatically build and upload components to dotCMS

  • Integrate components into pages using dotCMS's Velocity templating

  • Leverage npm packages and modern JavaScript features

  • Benefit from Vite's build optimization features

Workflow

  1. You develop in the react-app folder

  2. Vite builds and outputs files to a dotCLI sync folder, ex.: dotcli/files/live/[site]/application/react/dist/

  3. dotCLI watches this folder and automatically pushes changes to dotCMS

Prerequisites

Before starting, ensure you have:

  • Node.js (v18 or higher) and npm installed

  • Access to a dotCMS instance

  • Good knowledge of React and dotCMS

  • dotCLI installed globally: npm install -g @dotcms/cli

  • A read-only API token from dotCMS (for security best practices)

Project Structure

The integration uses a two-folder structure:

project/
├── react-app/                    # Your React application
│   ├── src/                      # React source code
│   └── vite.config.js           # Build configuration
│
└── dotcli/                      # dotCLI synchronization directory
    └── files/
        └── application/
            └── react/           # React integration files
                ├── dist/        # Built files
                │   └── .vite/manifest.json  # Asset mapping
                └── react-widget.vtl  # Velocity template

Step-by-Step Guide

Step 1: Project Setup

  1. Create your project root directory:

mkdir my-dotcms-react-project
cd my-dotcms-react-project
  1. Create a new React project with Vite:

npm create vite@latest react-app -- --template react
cd react-app
npm install
  1. Create the dotCLI directory:

cd ..
mkdir dotcli
cd dotcli
dotcli login

Step 2: Configure Environment

  1. In the react-app directory, create a .env file:

# dotCMS instance URL
VITE_DOTCMS_URL=http://localhost:8080
# Read-only API token
VITE_DOTCMS_AUTH_TOKEN=your_token_here

  1. Configure Vite (vite.config.js):

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  // Base path for assets in production
  base: process.env.NODE_ENV === 'production' 
    ? '/application/react/dist' 
    : '/',
  build: {
    // Clean output directory before build
    emptyOutDir: true,
    // Generate manifest for asset tracking
    manifest: true,
    rollupOptions: {
      input: {
        // Entry point of your application
        main: 'src/main.jsx'
      },
      output: {
        // Output directory in dotCLI folder
        dir: '../dotcli/files/live/en-us/demo.dotcms.com/application/react/dist'
      }
    }
  }
})

Key configuration points

  • base: Sets the base URL for assets in production

  • emptyOutDir: Cleans the output directory before each build

  • manifest: Generates a manifest.json file for asset tracking

  • rollupOptions

    • input.main: Specifies the file of the entry point of your component

    • output.dir: Specifies where built files should be placed

Rollup

While Vite is a development tool offering a speedier, leaner experience for web projects. Rollup, is the module bundler taking small bits of code and compiling them into more complex code, optimizing it for browser compatibility.

In the Vite configuration you can pass rollupOptions, which allows you to configure even further your components builds, for example, you can have multiple components files, for more information check the rollup options page.

Step 3: Create Integration Template

Create react-widget.vtl in dotcli/files/application/react/:

## Fetch the Vite manifest file

#set($manifest = $json.fetch("$!{host.hostname}/application/react/dist/.vite/manifest.json"))

## Collect and deduplicate CSS files

#set($cssFiles = [])
#foreach($entry in $manifest.entrySet())
    #if($entry.value.isEntry)
        #if($entry.value.css)
            #foreach($css in $entry.value.css)
                #if(!$cssFiles.contains($css))
                    #set($void = $cssFiles.add($css))
                    <link rel="stylesheet" href="/application/react/dist/$css" />
                #end
            #end
        #end
    #end
#end


## Add entry point scripts
#foreach($entry in $manifest.entrySet())
    #if($entry.value.isEntry)
        <script type="module" src="/application/react/dist/$entry.value.file"></script>
    #end
#end


## Root element for React
<div id="root"></div>

Note: $!{host.hostname} ensures the correct domain is used in different environments.

Development Workflow

  1. Start the development server:

cd react-app

npm run dev
  1. In a separate terminal, watch for file changes:

cd dotcli

dotcli files push files/live/en-us/demo.dotcms.com/application/react/dist -ra -rf --watch

Note: You can watch all the dotCLI files for push but I really recommend you only watch the dist folder where Vite will output the react build files.

Options explained:

  • --watch: Automatically push changes

  • --ra: Remove old assets

  • --rf: Remove old files

We need to remove old assets and files on every build because Vite by default add hashes to the file names to handle cached files in the browser and we don’t end up dotCMS file system with multiple unused JavaScript and CSS files.

dotCLI File Management

Common commands for managing files:

# Check status
dotcli status

# Pull all files
dotcli pull

# Push specific directory
dotcli files push <path>

# List changes
dotcli files list

Best Practices

  1. Security

    • Always use read-only tokens for client-side applications

    • Keep environment variables secure

    • Never commit tokens to version control

  2. Performance

    • Enable code splitting for larger applications

    • Utilize dynamic imports for conditional loading

    • Implement proper caching strategies

  3. Development

    • Use TypeScript for better type safety

    • Implement proper error boundaries

    • Keep components focused and reusable

Multiple Components on One Page

When using multiple React components on the same page:

  1. Use unique root IDs for each component

  2. Create separate entry points for each component

  3. Update the Velocity template to handle multiple components

Example:

<div id="component1-root"></div>
<div id="component2-root"></div>

Advanced Options

  1. Code Splitting

// Dynamic import example
const MyComponent = React.lazy(() => import('./MyComponent'));
  1. TypeScript Integration

npm install -D typescript @types/react @types/react-dom


  1. CSS Modules

// Enable in vite.config.js
css: {
  modules: true
}

Troubleshooting

Build Issues

  • Missing Assets

    • Verify Vite config base path

    • Check dotCLI connection status

    • Verify file permissions

  • Build Errors

    • Clear dist directory

    • Verify dependencies

    • Check for syntax errors

Runtime Issues

  • Component Not Rendering

    • Check browser console

    • Verify manifest.json loading

    • Inspect network requests

dotCLI Issues

  • Push Failures

    • Verify authentication

    • Check file permissions

    • Ensure correct path structure

Additional Resources

Conclusion

This integration approach offers a modern development experience while maintaining dotCMS's templating capabilities. You get the best of both worlds: React's component-based development and dotCMS's content management features.