Skip to content

Bug: get_dev_server_url incorrectly includes settings.STATIC_URL prefix in development mode #161

@Umensch

Description

@Umensch

1. Description

When using django-vite in development mode (DJANGO_VITE_DEV_MODE = True), the URL generated by the {% vite_asset %} template tag for assets served by the Vite development server incorrectly includes the Django settings.STATIC_URL prefix.

This results in the browser attempting to fetch assets from an incorrect URL, leading to 404 errors. For example, instead of requesting http://localhost:5173/src/main.ts, the browser requests http://localhost:5173/static/src/main.ts.

2. Code Analysis

The issue appears to stem from the get_dev_server_url method within the DjangoViteAppClient class (located in django_vite/core/asset_loader.py). Specifically, this section:

# Inside django_vite/core/asset_loader.py -> DjangoViteAppClient.get_dev_server_url
def get_dev_server_url(
    self,
    path: str,
) -> str:
    # ... (docstring)
    static_url_base = urljoin(settings.STATIC_URL, self.static_url_prefix) # Incorrectly uses STATIC_URL
    if not static_url_base.endswith("/"):
        static_url_base += "/"

    # This line combines the vite server base with a path that already includes STATIC_URL
    return urljoin(
        f"{self.dev_server_protocol}://"
        f"{self.dev_server_host}:{self.dev_server_port}",
        urljoin(static_url_base, path), # The inner urljoin creates "/static/path/to/asset"
    )

This code explicitly constructs the asset path by joining settings.STATIC_URL with the provided path, even when dev_mode is True. The Vite development server, however, serves assets relative to its configured root directory and does not expect the Django STATIC_URL prefix.

3. Steps to Reproduce

  1. Configure Django Settings (settings.py):
    • Set DEBUG = True
    • Set DJANGO_VITE_DEV_MODE = True (or link it to DEBUG)
    • Set STATIC_URL = '/static/' (ensure trailing slash)
    • Configure DJANGO_VITE_ASSETS_PATH and DJANGO_VITE_MANIFEST_PATH appropriately (though manifest isn't used in dev mode).
  2. Configure Vite (vite.config.js or vite.config.ts):
    • Set root to your frontend directory (e.g., frontend/).
    • Set base: '/' for development mode. Example dynamic config:
      // vite.config.js
      import { defineConfig } from 'vite'
      export default defineConfig({
        // ... plugins
        root: 'frontend', // Or path relative to config file
        base: process.env.NODE_ENV === 'production' ? '/static/' : '/',
        // ... server, build configs
      })
    • Ensure you have an entry point (e.g., frontend/src/main.ts).
  3. Use Template Tag (your_template.html):
    • Load the tags: {% load django_vite %}
    • Include the asset: {% vite_asset 'src/main.ts' %} (path relative to Vite root)
  4. Run Servers:
    • Start the Vite development server: npm run dev (or yarn dev) in the frontend directory.
    • Start the Django development server: python manage.py runserver
  5. Observe:
    • Load the Django page in your browser.
    • Inspect the HTML source code for the <script> tag generated by vite_asset.
    • Check the browser's Network tab.

4. Expected Behavior

The {% vite_asset 'src/main.ts' %} tag should generate a <script> tag with the src attribute pointing directly to the Vite development server, without the STATIC_URL prefix.

Example Expected src: http://localhost:5173/src/main.ts

5. Actual Behavior

The {% vite_asset 'src/main.ts' %} tag generates a <script> tag with the src attribute that incorrectly includes the STATIC_URL prefix.

Example Actual src: http://localhost:5173/static/src/main.ts

This leads to a 404 error in the browser's console when trying to fetch the asset from the Vite dev server.

6. Environment

  • django-vite version: 3.1.0
  • Django version: 5.1.6
  • Python version: 3.11.3
  • Node.js version: v22.14.0
  • npm / yarn version: npm 11.2.0
  • Vite version: 6.2.5
  • Operating System: Windows 11

7. Suggested Fix (Optional)

Modify the get_dev_server_url method in django_vite/core/asset_loader.py to avoid using settings.STATIC_URL when constructing the URL:

# Inside DjangoViteAppClient.get_dev_server_url
from urllib.parse import urljoin

def get_dev_server_url(
    self,
    path: str,
) -> str:
    # Base URL of the Vite development server MUST end with / for urljoin
    vite_server_base_url = f"{self.dev_server_protocol}://{self.dev_server_host}:{self.dev_server_port}/"

    # Combine the Vite base URL directly with the asset path (relative to Vite root)
    # Use lstrip('/') on path to prevent potential double slashes if path starts with /
    final_url = urljoin(vite_server_base_url, path.lstrip('/'))

    return final_url

8. Related Issues Checked

I have reviewed issues #44 and #47.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions