Package: django-parcel-ssr
Django Parcel SSRZero configuration performant JavaScript server side rendering forDjango web framework, powered byParcel bundler.Installpipinstalldjango-parcel-ssr
npminstallparcel-bundleresmReactis supported out of the box, but any JavaScript view library with server side rendering support can be used instead (seescriptsoption andexamples). To use React install additional dependencies:npminstallreactreact-domreact-helmetstyled-jsxDefault React setup comes with optionalstyled-jsxCSS-in-JS support for writing CSS which applies only to a single component. To use it, add the.babelrcfile with the plugin to your project root:{"plugins":["styled-jsx/babel"]}Note for TypeScript users: Parcel 1.x doesn't support Babel plugins for TypeScript out the box. Check out theTypeScript examplefor a workaround.UpdateINSTALLED_APPS,TEMPLATES, andSTATICFILES_DIRSentries insettings.py:INSTALLED_APPS=['ssr',# ...]TEMPLATES=[{'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'),# }}},# ...]STATICFILES_DIRS=(os.path.join(BASE_DIR,'.ssr','static'),# ...)Initialize server side rendering inwsgi.py:# ...importssrssr.setup()We recommend adding.ssr/directory to.gitignore, to avoid committing your builds.UsageJavaScript files inbundlesdirectories 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 inbundlesdirectoriesto prevent unnecessary bundling:bundles/template.jscomponents/layout.jsnavbar.js...Create an examplebundles/template.jsfile in an installed app directory:importReactfrom'react'import{Helmet}from'react-helmet'exportdefaultprops=>{const[count,setCount]=React.useState(props.count)return(<div><Helmet><title>{props.title}</title></Helmet><h1>Count:{count}</h1><buttononClick={()=>setCount(count+1)}>+</button><buttononClick={()=>setCount(count-1)}>-</button><stylejsx>{`h1 {color:${props.color};}`}</style></div>)}Bundles are available to the templating engine for server side rendering, butcontext has to be JSON serializable(see restrictions below).Create an example Django view inurls.py:fromdjango.urlsimportpathfromdjango.shortcutsimportrenderdefreact_view(request):returnrender(request,'template.js',context={'title':'Django SSR''count':0,'color':'red'})urlpatterns=[# ...path('',react_view)]Run./manage.py runserverand navigate tohttp://localhost:8000.ConsultParcel documentationto learn about supported assets, recipes, and more.RestrictionsTemplate context has to be a JSON serializable value because the actual rendering is handled by JavaScript. Django objects have to beserialized; querysets can be rendered as dictionaries instead of model instances usingQuerySet.values(). For advanced use cases such as handling model relations, serialize context data manually, e.g. using Django REST Framework'smodel serializer.DeploymentIfNODE_ENVoption is set toproduction(by default this happens whenDEBUG = False), starting the Django app will not automatically bundle entry points. You'll need to invoke the management command manually, and collect staticfiles afterwards:./manage.pybundle
./manage.pycollectstatic-lOptionsextensionsDefault:['js', 'jsx', 'ts', 'tsx']List of valid file extensions for bundles.output_dirnameDefault:'dist/'Name of the Parcel bundles output directory.Trailing slash is required.json_encoderDefault:'django.core.serializers.json.DjangoJSONEncoder'JSON encoder class used for serializing view context into props.cacheDefault:TrueEnables or disables Parcel bundler caching.env.NODE_ENVDefault:'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.env.NODE_OPTIONSDefault:'-r esm'CLI options for Node workers.Server side renderer usesesmloader to handle dynamic imports.env.WORKER_TTLDefault:1000Number of milliseconds Node workers will wait for Django to restart before exiting.scripts.serverDefault:'{BASE_DIR}/.ssr/scripts/react/server.js'Absolute path to customcreateRendererfunction, used to createrenderfunction which has to return HTML document string. This file is transpiled and executed on the server.import{createElement,renderToString}from'some-view-library'exportdefaultComponent=>({script,stylesheet},props)=>{constcomponent=createElement(Component,props)consthtml=renderToString(component)constserializedProps=encodeURIComponent(JSON.stringify(props))return`<!DOCTYPE html><head><!-- ... -->${stylesheet&&`<link src="${stylesheet}" rel="stylesheet">`}</head><body><div id="root" data-props="${serializedProps}">${process.env.NODE_ENV==='production'?html:''}</div><script src="${script}"></script></body>`}scripts.clientDefault:'{BASE_DIR}/.ssr/scripts/react/client.js'Absolute path to customhydratefunction, 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'exportdefaultComponent=>{constroot=document.getElementById('root')constprops=JSON.parse(decodeURIComponent(root.dataset.props))constcomponent=createElement(Component,props)constmount=process.env.NODE_ENV==='production'?hydrate:rendermount(component,root)}ExamplesFor advanced use cases such as using client side routing, state management libraries, or different JavaScript view libraries altogether, check out theexamples:TypeScriptReact with React RouterReact with ReduxCycle.jsCycle.js ReactVue.js