Skip to main content

Django ESM

Django ESM: NextGen JavaScript ESM module support for Django

NextGen JavaScript ESM module support for Django.

PyPi Version Test Coverage GitHub License

Sponsors

Sponsors

Highlights

  • 😌 easy transition
  • ⚡️ smart cache busting
  • 📦 no more bundling
  • ☕️ native ESM support
  • 📍 local vendoring with npm

Setup

Install the package:

pip install django-esm

First, add django_esm to your INSTALLED_APPS settings:

# settings.py
INSTALLED_APPS = [
    # …
    "django_esm",  # add django_esm before staticfiles
    "django.contrib.staticfiles",
]

Wrap your WSGI or ASGI application to serve the built output at /esm/ and pass every other request to the wrapped application:

import os

from django.core.asgi import get_asgi_application
from django.core.wsgi import get_wsgi_application

from django_esm import asgi, wsgi

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")

# runserver serves wsgi_app via WSGI_APPLICATION; ASGI servers serve asgi_app.
wsgi_app = wsgi.ESM(get_wsgi_application())
asgi_app = asgi.ESM(get_asgi_application())

Finally, add the import map to your base template:

<!-- base.html -->
<!DOCTYPE html>
{% load esm %}
<html lang="en">
<head>
  <script type="importmap">{% importmap %}</script>
  <title>Django ESM is awesome!</title>
</head>
</html>

That's it!

Development

Rebuild STATIC_DIR on every change:

python manage.py esm --watch

Run the development server in another terminal:

python manage.py runserver

Treeshaking

By default, every package entry point ends up in the import map. Pass --treeshake to drop entry points that are not reachable from your project's own entry points, keeping only the outputs actually imported:

python manage.py esm --watch --treeshake

Usage

You can now import JavaScript modules in your Django templates:

<!-- index.html -->
{% block content %}
  <script type="module">
    import "lit"
  </script>
{% endblock %}

Script tags

Use the esm tag to load a module from the import map as a script tag, with its resolved URL and integrity hash:

{% load esm %}
{% esm "htmx.org" %}
<script type="module" src="/esm/node_modules/htmx.org/dist/htmx.min-<hash>.js" integrity="sha256-… sha384-… sha512-…"></script>

The name must be a key of the import map, that is, a package name or a private module.

Form.media

To use your import map in Django forms, you can use the Form.media attribute:

# forms.py
from django import forms
from django_esm.forms import ESM


class MyForm(forms.Form):
    name = forms.CharField()

    class Media:
        js = [ESM("@sentry/browser")]

Now {{ form.media.js }} will render like this:

<script type="module" src="/esm/node_modules/@sentry/browser/build/bundle-<hash>.js" integrity="sha256-… sha384-… sha512-…"></script>

Private modules

You can also import private modules from your Django app:

<!-- index.html -->
{% block content %}
  <script type="module">
    import "#myapp/js/my-module.js"
  </script>
{% endblock %}

To import a private module, prefix the module name with #. You need to define your private modules in your package.json file:

{
  "imports": {
    "#myapp/script": "./myapp/static/js/script.js",
    // You may use trailing stars to import all files in a directory.
    "#myapp/*": "./myapp/static/js/*"
  }
}

How it works

Django ESM works via native JavaScript module support in modern browsers. It uses the import map to map module names to their location on the server.

Here is an example import map. Entries resolve under /esm/ and use content-hashed names:

{
  "imports": {
    "htmx.org": "/esm/node_modules/htmx.org/dist/htmx.min-<hash>.js"
  }
}

Metadata

Release files for django-esm 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-esm 0.11.0
File Size Uploaded
django_esm-0.11.0.tar.gz 9.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-esm 0.11.0
File Interpreter ABI Platform
django_esm-0.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.4 kB

Release files / django_esm-0.11.0.tar.gz

Download URL django_esm-0.11.0.tar.gz
Size 9.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e318700a35d59fdf990d6b433af0e633e7e963e49c12fc04d4908577fb540d09
BLAKE2b-256 checksum
How to use checksums
4050deb5ea4bc8c4f07c172a64b6e598f34436cd749b3935971038b81dc05aac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / django_esm-0.11.0-py3-none-any.whl

Download URL django_esm-0.11.0-py3-none-any.whl
Size 11.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7f2bab5da0135c36f7cc567fb7a372996ad2f94860ebeeb84c409c8b673e9b08
BLAKE2b-256 checksum
How to use checksums
d5d8410aa1b079f3efba09426f22de8183a8eff3852e54aaa633ec7b9aa8f6d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.12.0

2 release files

This release

0.11.0 This release

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page