Skip to main content

Django server side rendering, powered by Parcel bundler

Project description

PyPI version

Django Parcel SSR

Zero configuration performant JavaScript server side rendering for Django web framework, powered by Parcel bundler.


pip install django-parcel-ssr
npm install parcel-bundler esm

React is supported out of the box, but any JavaScript view library with server side rendering support can be used instead (see scripts option and examples). To use React install additional dependencies:

npm install react react-dom react-helmet styled-jsx

Default React setup comes with optional styled-jsx CSS-in-JS support for writing CSS which applies only to a single component. To use it, add the .babelrc file with the plugin to your project root:

    "plugins": [

Note for TypeScript users: Parcel 1.x doesn't support Babel plugins for TypeScript out the box. Check out the TypeScript example for a workaround.


    # ...

        'BACKEND': 'ssr.backends.javascript.Components',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            # 'extensions': ['js', 'jsx', 'ts', 'tsx'],
            # 'output_dirname': 'dist/',
            # 'json_encoder': 'django.core.serializers.json.DjangoJSONEncoder',
            # 'cache': True,
            # 'env': {
            #     'NODE_ENV': 'development' if DEBUG else 'production',
            #     'NODE_OPTIONS': '-r esm',
            #     'WORKER_TTL': 1000,
            # },
            # 'scripts': {
            #     'server': os.path.join(BASE_DIR, '.ssr', 'scripts', 'react', 'server.js'),
            #     'client': os.path.join(BASE_DIR, '.ssr', 'scripts', 'react', 'client.js'),
            # }
    # ...

    os.path.join(BASE_DIR, '.ssr', 'static'),
    # ...

Initialize server side rendering in

# ...
import ssr

We recommend adding .ssr/ directory to .gitignore, to avoid committing your builds.


JavaScript files in bundles directories of installed Django apps serve as Parcel entry points and they have to provide a root component as default export. Avoid putting non root components in bundles directories to prevent unnecessary bundling:

  • bundles/
    • template.js
  • components/
    • layout.js
    • navbar.js
    • ...

Create an example bundles/template.js file in an installed app directory:

import React from 'react'
import { Helmet } from 'react-helmet'

export default props => {
    const [count, setCount] = React.useState(props.count)
    return (

            <h1>Count: {count}</h1>
            <button onClick={() => setCount(count + 1)}>+</button>
            <button onClick={() => setCount(count - 1)}>-</button>

            <style jsx>{`
                h1 {
                    color: ${props.color};

Bundles are available to the templating engine for server side rendering, but context has to be JSON serializable (see restrictions below).

Create an example Django view in

from django.urls import path
from django.shortcuts import render

def react_view(request):
    return render(request, 'template.js', context={
        'title': 'Django SSR'
        'count': 0,
        'color': 'red'

urlpatterns = [
    # ...
    path('', react_view)

Run ./ runserver and navigate to http://localhost:8000.

Consult Parcel documentation to learn about supported assets, recipes, and more.


Template context has to be a JSON serializable value because the actual rendering is handled by JavaScript. Django objects have to be serialized; querysets can be rendered as dictionaries instead of model instances using QuerySet.values(). For advanced use cases such as handling model relations, serialize context data manually, e.g. using Django REST Framework's model serializer.


If NODE_ENV option is set to production (by default this happens when DEBUG = False), starting the Django app will not automatically bundle entry points. You'll need to invoke the management command manually, and collect staticfiles afterwards:

./ bundle
./ collectstatic -l



Default: ['js', 'jsx', 'ts', 'tsx']

List of valid file extensions for bundles.


Default: 'dist/'

Name of the Parcel bundles output directory. Trailing slash is required.


Default: 'django.core.serializers.json.DjangoJSONEncoder'

JSON encoder class used for serializing view context into props.


Default: True

Enables or disables Parcel bundler caching.


Default: 'development' if DEBUG else 'production'

Development mode activates bundle watchers with HMR (hot module replacement). Production mode performs a single build and outputs optimized bundles.


Default: '-r esm'

CLI options for Node workers.

Server side renderer uses esm loader to handle dynamic imports.


Default: 1000

Number of milliseconds Node workers will wait for Django to restart before exiting.


Default: '{BASE_DIR}/.ssr/scripts/react/server.js'

Absolute path to custom createRenderer function, used to create render function which has to return HTML document string. This file is transpiled and executed on the server.

import { createElement, renderToString } from 'some-view-library'

export default Component => ({ script, stylesheet }, props) => {
    const component = createElement(Component, props)
    const html = renderToString(component)
    const serializedProps = encodeURIComponent(JSON.stringify(props))
    return `
        <!DOCTYPE html>
            <!-- ... -->
            ${stylesheet && `<link src="${stylesheet}" rel="stylesheet">`}
            <div id="root" data-props="${serializedProps}">${
                process.env.NODE_ENV === 'production' ? html : ''
            <script src="${script}"></script>


Default: '{BASE_DIR}/.ssr/scripts/react/client.js'

Absolute path to custom hydrate function, used to update the root DOM node when the page loads. This file is transpiled and executed in the browser.

import { createElement, hydrate, render } from 'some-view-library'

export default Component => {
    const root = document.getElementById('root')
    const props = JSON.parse(decodeURIComponent(root.dataset.props))
    const component = createElement(Component, props)
    const mount = process.env.NODE_ENV === 'production' ? hydrate : render
    mount(component, root)


For advanced use cases such as using client side routing, state management libraries, or different JavaScript view libraries altogether, check out the examples:

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-parcel-ssr-0.7.0.tar.gz (11.5 kB view hashes)

Uploaded source

Built Distribution

django_parcel_ssr-0.7.0-py3-none-any.whl (15.4 kB view hashes)

Uploaded py3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page