The biggest challenge to using Django with React IMO is getting the right blend of isomorphic rendering down. I don't want to go full SPA with Django as this defeats the purpose of Django IMO. Most parts of the site I want server-rendered, while in stateful parts I want React. So, let's say I have a site with 20 different React "apps" (i.e. stateful components) that I want to distribute amongst my various Django sections (Django "Apps" within the same project). And I want to do that with one webpackconfig. How do I tell my webpack where to put all those react bundles? The answer I've found is django-webpack-loader[1], however as you can see in the Issues section, one of the biggest limitations here is the inability to chunk React (and other issues).
Does anyone have a solution they like for this kind of isomporphic Django problem?
I've spent many years working on django including production setups for 3 different companies. My strong advice is to only use Django for API calls (DRF) and the built in admin UI. Do not use Django for ANY client facing static site rendering.
1. Deploy the React static pages and JS/CSS resources completely separately from Django. Cloudfront/S3 is my personal choice. You will need to tweak the CORS_ORIGIN_WHITELIST and CORS_ALLOW_HEADERS in the django settings but that's relatively easy.
2. Use Gatsy or something similar to help you with static site generation using react. Remember: React is in charge of HTML/JS/CSS of any type and Django should not get involved.
3. Use https://github.com/ctrlplusb/react-async-component or something similar to help break up your SPA so the browser doesn't have to load all of it at once and only loads smaller components on an as needed basis.
Don't mess with webpack and eject unless you have a very specialized need that cannot be addressed with everything out there.
Can you give me a solid usecase of why not to use djangos templating and use - as per your example - an SSG?
Seems like the usecases are edge cases. Why use Django just to make api calls when smaller and nimbler alternatives abound.
Its no wonder React devs command such a strong hourly fee. They'll mostly be fixing dung with more dung and hooks.
Pardon the rant. Im at a job where no one seems to be listening to my case against react when plain whole JS would do. The code will be verbose but there is no magic or illusion. Anyone from junior intern to senior dev can understand the codebase without much help. Its not that big either.
> Pardon the rant. Im at a job where no one seems to be listening to my case against react when plain whole JS would do.
I don't know your job, your coworkers or your context. You may be right… probably not, though. React is a powerhouse in terms of developer productivity.
I have 17 years of software engineering behind me, and while I dabbled in a lot of things, most of these years have been spent using Python (and Django). And the current typescript+react ecosystem is several orders of magnitude more productive than anything else I've ever used, be it in Python or any other language.
You say "overcomplication", but React is far, far simpler than Django's template system. You're basically throwing away a LOT of overly complex shit that is simply there to generate HTML in non-html. React generates HTML with actual HTML -- well, okay, JSX/TSX is not technically HTML, but it maps perfectly where it needs to, and still gives you that added layer of typing for extra safety. React can't generate invalid HTML, and if your app compiles, you won't ever have a client-side syntax error.
I can't stress how bad a tool Django templates are for the job of generating HTML.
Oh and JS without React? I mean, sure, if you're literally just adding a couple of dynamic elements on a mostly static site. If you're actually going to have JS-driven UI elements in a dynamic interface, just use React. Not saying you have to, but it's probably the correct choice.
There's a lot of purists out there who will cry foul at 50kb more of some gzipped code, but do you want to spend your time tweaking and manually testing imperative UI behaviour for all your little widgets and how they interact with each other, or do you want to be productive?
Feel free to email me more context on your situation and I can give you a more specific assessement … but my €.02 here is, spend some time learning react & typescript, and playing with the more useful bits of it (NextJS+Typescript). It's not time that will be wasted either way. Give it a week and re-assess.
Not the OP but this approach is great if you're starting a new project that is intended to grow.
Django has lots of stuff besides the template system, in particular the admin, authentication, and ORM which allow rapid iteration and getting your product into production.
After some growth though, you may find yourself constrained by the framework: a mixture of difficulty implementing functionalities, performance problems, and organizational/deployment problems (i.e. several teams wanting to deploy simultaneously).
Around that time you'll probably start looking at taking your (obviously well-designed) monolith apart and peeling off the business domains out into separate services. Maybe rewrite some parts Go or Rust? Anyway if you use the template system, you'll have a much harder time doing this than if you're only slinging JSON around.
Another advantage is that you get right from the start is having the ability to modify purely display parts of the UI without having to touch the back-end, it doesn't sound like much but is incredibly useful when prototyping/testing new ideas.
For an SSG though, for me that's the wrong use case. For that I would use Zola which is incredibly fast and uses a template system that's basically a Rust port of Jinja, so a Django developer is right at home.
> my case against react when plain whole JS would do.
IME (not a senior dev) it's easier to turn the entire front-end over to React. I don't want to rebuild the wheel and write custom CSS every time I need a new component. I want to be able to plug in common components, with unsurprising and predictable props. If I'm already using React for dialog boxes, it may well as handle my click handlers as well. Then it can also grab data.
I agree with the spirit of avoiding more dependencies though and for this reason I try to avoid Redux. I find React absolutely invaluable for styling and reusable components however.
> I don't want to rebuild the wheel and write custom CSS every time I need a new component.
You are telling me it is worth migrating to a new architecture/build with all the overhead just so we can have less time writing custom css? Surely you jest. Devs should not define their jobs as cookie cutters. We use common stuff as a base to start work on the customized business facing solution yo.
I've seen some custom PHP production codebases with plain css and jquery doing its thing with 1x10^6 plus weekly traffic. It was a pleasure to read and figure out. I could throw an intern at it and he would figure it out. Verbose as hell too.
> I've seen some custom PHP production codebases with plain css and jquery doing its thing with 1x10^6 plus weekly traffic.
I've worked on plenty of those. I've handled more traffic with uglier shit, too. This isn't a performance thing, nor is it a premature optimization thing. It's about developer productivity.
Refactors are faster. Components are easier to break down. Bugs are easier to catch at compile time. Some classes of bugs are entirely avoided. A LOT of UI logic makes a ton more sense when written declaratively (as React forces you to), than imperatively. And none of that is even getting into the realm of how much easier it is to find devs who will work on a ReactJS codebase (and even more so, will be happy to do so).
My field Python experience surpasses my Typescript/React experience easily 50x. And yet, I'll be much faster at picking up a new client's React/TS codebase than their equivalent Python one. The productivity gains are real.
Absolutely. He’s talking about custom CSS which has already been written for the organization. You don’t want to have someone waste time duplicating the style. They may be against a deadline or have higher priority tasks.
Plus, you may have gotten lucky with that app, but that’s very often not the case.
That's a nice idea for new projects but how would you handle a company with large existing Django sites that want to bring in one or two react-based SPAs?
We did this with Vue.js, not sure if it applies to React (I haven't used React).
The way we did it was to start with a few parts of the page that really benefited from having Vue.js, using a simple `script src=`. So no components or anything fancy. For this we just put the JS stuff using Django's template system.
Once we had proved that this improved the site, we went all in and started to use the "proper" way, building the JS and deploying to a CDN.
In parallel to this we set up Django Rest Framework and set up alternate routes to fetch the view data as JSON.
In retrospect I would probably skip the hybrid system and just start building view components, but it was done this way so we could more easily revert if it didn't work out.
I’m currently building an SPA with the above approach and it most definitely isn’t “not using Django”. There’s plenty of Django if you use DRF. You’re also still exposed to templating if you use Django Admin like they suggest and I’m also doing.
I’m doing this and so far it’s great. I’m not using Gatsby or hosting the React app separately though... serving from the Django server is good enough for my use case.
I've done as you describe, separate Django views have different client components and those components import subcomponents which are shared as needed, throughout the site. I just have the webpack build each "root" client component individually, and you can separate subcomponents into libraries.
You can even have multiple react apps rendered into their own containers that do not share state as long as you separated them cleanly.
When you say "tell webpack where to put the files" what do you mean exactly? I recommend just making one bundle per "app" (can be configured as different entry points in your webpack config), and then using the outputs as standard Django static files. I found django-webpack-loader to be a little to magical for my taste and solving a problem that didn't really exist for me (the need for refreshless hot reloading).
> Django with React IMO is getting the right blend of isomorphic rendering down. I don't want to go full SPA with Django as this defeats the purpose of Django IMO.
"I don't want to go full SPA with Django as this defeats the purpose of Django IMO" -> What is this "purpose" ? Django is here to help me model my database, handle few permissions and bring few API up online, I see no problem with having a PWA in front of it. Are you trying to get all of your website server rendered ? In which case you could do that without having to worry about integrating it with Django... TBH after 5 years of react and 8 of Django, i'm just not mixxing them up except for the front-end calling a query on the back-end (which both can be served at the same domain using nginx) ;
I've worked with Django for 12 years and I don't know why you would want to use their awful templating language.
It's untyped, messy, buggy, inconsistent, ugly and altogether a pain in the arse to use. Yeah sure it's "simple", but working with React and Typescript is a million times healthier for any sort of workload.
And if you really want to do an SSR'd app and don't want to go the SPA route, there's better alternatives to Django IMO (Flask for one).
Totally agree with your assessment of Django in terms of its templating and SSR abilities. It's horrible and should be avoided at all costs.
However, the Django admin system is extremely powerful and saves you a HUGE amount of dev time. Every single saas product needs an admin interface from an operations point of view. I haven't seen anything out there that is better than Django Admin.
Yes I agree with you. My favourite stack right now is Django with DRF+Admin for backend, Typescript+NextJS (React) for frontend. I front the backend with Caddy, have django live on both admin.example.com and api.example.com with a couple of rewrites, and put cloudflare access in front of admin.example.com.
Currently I still use allauth for social authentication, though I'm not a fan of how little flexibility I get with it especially in such a setup (it makes a lot of assumptions about a template setup).
The other weakness in this stack is the lack of API typings. I haven't bothered messing with OpenAPI yet; I probably should but I understand that it's not a silver bullet in terms of typings either, so I just end up writing my own types for the API and it does become a very repetitive maintenance burden…
You should check out FastAPI. I’ve been a Django dev for years but now that all projects have pretty much moved to client side js + drf backend anyway I’ve been using FastAPI for new projects. The way it takes advantage of Python typing is a thing of beauty!
Yup I've used FastAPI and love it. I'm not entirely sold on it when it comes to dealing with the ORM though, and the lack of a Django-quality admin is kind of a bummer.
I don't think django tempating is as bad as you've described but one reason is that a project is long-standing and dev resources are already familiar with it.
A product manager may establish customer demand for an experience on the site that a react SPA would facilitate very well.
The org may want to dip its toe in react without throwing out or re-writing vast, stable aspects of the site that may also need ongoing changes.
Honestly I don't really know how to summarize it. Django templates have a ton of gotchas. They have the dumbest safeguards, too, such as preventing you from using variables beginning with underscores.
Jinja templates at least let you use normal python syntax in the tags. You can easily do something like {{ items.filter("books")[:5] }} — in Django, you would have to write a special accessor or template tag to call filter("books") as it doesn't let you specify arguments to function calls, and you'd use the awful |slice:":5" to slice it.
But more than anything else, Django templates are not just untyped, they are untypeable. You can't really validate them. Best you can do is try to compile them in a CI job see if anything fails. Not to mention that the way you're outputting HTML essentially arbitrarily anywhere in the page means there is no way for the editor / tools / even yourself to know if some piece of code is syntactically or semantically valid in context. Got a list_item.html with a naked "<li>{{ item }}" inside? Why the fuck not! Could even be raw css or js outside a tag in your template, could be valid in some includes, invalid in some others. Everything goes. You can't even know whether a template is in use, as it's completely arbitrary code that calls these template inclusions, via string filenames (which therefore can be included however you want).
It's impossible to create these problems with react/typescript. And react heavily encourages code reuse: creating reusable components that are as small as possible. Django templates encourage copy-pasting.
Yes. I have large portions of a server-rendered, django web application that uses react largely as you've described.
I wanted to bring a single react app into the django project using a root dom element from a django template using the same template inheritance as the rest of the site. (common navbar)
Benefits of this approach on Django side were adherence to Django structure and session-based auth for the react app's API calls.
My goal was to minimize customization while retaining the "spirit" of both Django and react.
I decided the react app should flow from an unejected Create React App (CRA) project. This provides the developer experience of CRA's development environment hot-reload and production build bundling.
It also makes it more likely the react app can be migrated to new versions of CRA.
The webpack config changes needed to pull this off are not extensive but do leverage Create React App Configuration Override (CRACO). [1] CRACO is the best-supported config layer for CRA today, supporting CRA 4.*.
Key aspects of my implementation are:
- Use of package.json poststart to move files generated by CRA's run script and update paths made by CRA-generated files to work inside django.
- Use of the package.json postbuild script to move and rename files to nestle assets into their proper place in a django static path.
- Customization of HtmlWebpackPlugin to modify CRA's:
- Out-of-box behavior of webpack bodyTags and headTags.
- webpackConfig.output to use a project-excluded directory that facilitates hot reload during dev
While my implementation doesn't currently support N react apps bundles at this time I could see it being done provided they share a single package file.
Being relatively new to modern web front end toolchains I ended up rewriting much of the of the user documentation for CRACO as part of my learning process for this mash of Django and React. [2]
I have not released my solution but I have stubbed out the problem and solution description [3].
If someone is very much in need of this project, please write me. I have wanted to release it but have just not had time yet, and I need to update it to CRA 4.
All this said and done, having accomplished my initial goals, I am less certain now that it is worth trying to integrate a CRA-app into Django, at least if the goal is to retain shared sub templates from the rest of the Django app.
Instead, I suspect the better method would be to expect to have to maintain a react-compatible implementation of say a navbar or other "common" portion of the UI on the server-rendered pages and leverage only django's session auth on the SPA.
Ultimately, this integration experience made me take a hard look at my investment in Django. I know and enjoy python and the Django framework. But at least for new projects, I can't help but feel they faces an existential threat from modern web (react) paired with a node backend.
Does anyone have a solution they like for this kind of isomporphic Django problem?
1. https://github.com/owais/django-webpack-loader