Skip to content

Instantly share code, notes, and snippets.

@amalshaji
Forked from lucianoratamero/README.md
Created May 14, 2022 05:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amalshaji/dd0344eda39f0caa4cc0450826ef9611 to your computer and use it in GitHub Desktop.
Save amalshaji/dd0344eda39f0caa4cc0450826ef9611 to your computer and use it in GitHub Desktop.
Using Vite with Django, the simple way

Using Vite with Django, the simple way

This gist has most of the things I've used to develop the frontend using vite inside a monolithic django app.

Here's a boilerplate that uses this approach: https://github.com/labcodes/django-react-boilerplate

A couple of things to note:

  • it runs in SPA mode by default. If you want SSR, you may want to look into django_vite;
  • static files unrelated to your app, like images or fonts, should be served by django, instead of imported directly inside your frontend app;
  • you'll need to enable manifest in your vite configs for production;
  • I've only tested this with a React app, but I'll share my notes when testing with a Svelte app later.
    • I've already tested with svelte, and the changes are really small! For the most part, you'll only need to remove react-specific stuff (like react-refresh), use a svelte + vite app as base, and change base.html to import main.js instead of jsx. And I've created a sample template for it too!

Besides that, just read the comments carefully and everything should work out. Whenever I'm free, I'll make a video about this and add the URL here :]

I've published a video on how to do it, step-by-step: https://www.youtube.com/watch?v=FCyYIVfDkhY

{% load render_vite_bundle %}
<!DOCTYPE html>
<html lang="en">
<!--
For this base.html to work in dev and in production,
you'll need to set a couple of keys inside your settings.py.
Another file in this gist shows which ones you'll really need.
-->
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
{% if debug %}
<script type="module" src="http://localhost:3000/@vite/client"></script>
<!-- If you're using vite with React, this next script will be needed for HMR -->
<script type="module">
import RefreshRuntime from 'http://localhost:3000/@react-refresh'
if (RefreshRuntime) {
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => { }
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
}
</script>
{% endif %}
</head>
<body>
<div id="root"></div>
{% if debug %}
<!-- This url will be different for each type of app. Point it to your main js file. -->
<script type="module" src="http://localhost:3000/main.jsx"></script>
{% else %}
{% render_vite_bundle %}
{% endif %}
</body>
</html>
# This template tag is needed for production
# Add it to one of your django apps (/appdir/templatetags/render_vite_bundle.py, for example)
import os
import json
from django import template
from django.conf import settings
from django.utils.safestring import mark_safe
register = template.Library()
@register.simple_tag
def render_vite_bundle():
"""
Template tag to render a vite bundle.
Supposed to only be used in production.
For development, see other files.
"""
try:
fd = open(f"{settings.VITE_APP_DIR}/dist/manifest.json", "r")
manifest = json.load(fd)
except:
raise Exception(
f"Vite manifest file not found or invalid. Maybe your {settings.VITE_APP_DIR}/dist/manifest.json file is empty?"
)
imports_files = "".join(
[
f'<script type="module" src="/static/{manifest[file]["file"]}"></script>'
for file in manifest["index.html"]["imports"]
]
)
return mark_safe(
f"""<script type="module" src="/static/{manifest['index.html']['file']}"></script>
<link rel="stylesheet" type="text/css" href="/static/{manifest['index.html']['css'][0]}" />
{imports_files}"""
)
# These are the settings you should have for everything to work properly.
# Add these to your main settings.py file, or modify it accordingly.
# Needed for production. Avoid using '*'.
ALLOWED_HOSTS = ['your-production-domain.com']
# Needed for 'debug' to be available inside templates.
# https://docs.djangoproject.com/en/3.2/ref/templates/api/#django-template-context-processors-debug
INTERNAL_IPS = ['127.0.0.1']
# Vite App Dir: point it to the folder your vite app is in.
VITE_APP_DIR = BASE_DIR / "src"
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
# You may change these, but it's important that the dist folder is includedself.
# If it's not, collectstatic won't copy your bundle to production.
STATIC_URL = "/static/"
STATICFILES_DIRS = [
VITE_APP_DIR / "dist",
]
STATIC_ROOT = BASE_DIR / "staticfiles"
import { defineConfig } from "vite";
import reactRefresh from "@vitejs/plugin-react-refresh";
// https://vitejs.dev/config/
export default defineConfig({
build: { manifest: true },
base: process.env.mode === "production" ? "/static/" : "/",
root: "./src",
plugins: [reactRefresh()],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment