protibimbok / django-vite-plugin

This plugin configures Vite for use with Django backend.
112 stars 14 forks source link

We stand with Palestine against the ongoing genocide and brutal occupation.

Buy Me A Coffee

Django Vite Plugin

PyPI version

npm version npm downloads Licence

Introduction

Vite is a modern frontend build tool that provides an extremely fast development environment and bundles your code for production.

This plugin configures Vite for use with Django backend.

Installation

# Install django app
pip install django_vite_plugin

# Install vite plugin
npm install django-vite-plugin

Feature Highlights

1. Simple And elegant

2. Static file lookup

3. Auto Reload

4. JS Import helpers

5. Js import autocompletions

6. Test for production

Usage

Django

In your project's settings.py file, add django_vite_plugin in installed apps list

# Some settings
INSTALLED_APPS = [
    # Some apps
    'django_vite_plugin',
    # Other apps
]

Now use the following code in your template files to load the assets

{% vite '<app_name>/<path>/<to>/<css>/styles.css' %}

If you want to output any additional attributes in your html, do this:

{% vite '---.css' '--.js' crossorigin='anonymus' integrity='some-sha'%}

This will output:

<link rel="stylesheet" type="text/css" crossorigin="anonymus" integrity="some-sha" href="https://github.com/protibimbok/django-vite-plugin/blob/master/---.css"/>
<script src="https://github.com/protibimbok/django-vite-plugin/raw/master/---.js" type="module" crossorigin="anonymus" integrity="some-sha"></script>

Notice how <script> tag automatically includes type="module" attribute. You can change this behaviour from settings

Let's say you have two files your home app

└-- home
    └-- static
        └-- home
            |-- css
            |   └-- styles.css
            |
            └-- js
                └-- main.js

To include these files your Template file would look like:

{% load vite %}
<!DOCTYPE html>
<html lang="en">
    <head>
        <!--Other elements-->
        <!--Vite dev client for hmr (will not be displayed on production)-->
        {% vite %}
        {% vite 'home/css/styles.css' 'home/js/main.js' %}
    </head>
    <body>
        <!--Page content-->
    </body>
</html>

Notice instead of using home/static/home/*/*, we have used home/*/*. By default django_vite_plugin adds static/<app_name> after first segment of the path. This behaviour can be changed from settings

Vite

In your vite.config.js file add django-vite-plugin

//vite.config.js
import { defineConfig } from 'vite'
import { djangoVitePlugin } from 'django-vite-plugin'

export default defineConfig({
    plugins: [
        djangoVitePlugin([
            'home/js/app.js',
            'home/css/style.css',
        ])
    ],
});

Here, the argument is string or array of string that will be passed to build.rollupOptions.input.

Note: Automatic addition of static/<app_name> is also applied here

All of the entry points (used as {% vite '...' '...' %}) should be added here

Then run the following commands in two separate terminal

# Start the django development server
python manage.py runserver

# Start the vite dev server
npm run dev

And to build the assets for production, run

npm run build

Configuration

django_vite_plugin requires zero configuartion to develop or build your project. However, there are things you can customize

All the customizations are to be done in your settings.py file

The default configurations are:

DJANGO_VITE_PLUGIN = {
    'WS_CLIENT': '@vite/client',
    'DEV_MODE': getattr(settings, 'DEBUG', True),
    'BUILD_DIR': getattr(settings, 'STATIC_ROOT') or 'static',
    'MANIFEST': '<BUILD_DIR>/.vite/manifest.json',
    'BUILD_URL_PREFIX': getattr(settings, 'STATIC_URL'),
    'JS_ATTRS': {
        'type': 'module'
    },
    # 'JS_ATTRS_BUILD': Not present,
    'CSS_ATTRS': {
        'rel': 'stylesheet',
        'type': 'text/css'
    },
    'STATIC_LOOKUP': True
}

Javascript

The available js configuration options are:

{
    input: string | string[],
    root?: string,
    addAliases?: boolean,
    pyPath?: string,
    pyArgs?: string[],
    reloader?: boolean | (file: string) => boolean,
    watch?: string[],
    delay?: number,
}

Let's assume your vite.config.js file is in frontend directory

|-- home
|   └-- static
|       └-- home
|           |-- css
|           |   └-- styles.css
|           |
|           └-- js
|               └-- main.js
└-- frontend
    └-- vite.config.js

In this case your vite.config.js should look like this:

//vite.config.js
import { defineConfig } from 'vite'
import { djangoVitePlugin } from 'django-vite-plugin'

export default defineConfig({
    plugins: [
        djangoVitePlugin({
            input: [
                // Your inputs
            ],
            root: '..' // the parent directory 
        })
    ],
});

Features

1. Simple And elegant

You don't need a whole different set of setup to start using vite. All you need to do is install the packages and add them. And you are ready to go.

2. Static file lookup

As per Django's recommendation, static files and templates should be inside app_name/static/app_name and app_name/templates/app_name. When STATIC_LOOKUP is enabled in settings, static/app_name can be skipped from the import paths.

So, instead of writing

{% vite 'app_name/static/app_name/path/to/asset' %}

You can write

{% vite 'app_name/path/to/asset' %}

The behaviours of this setting are:

vite argument Include asset path
app_name/script.js app_name/static/app_name/script.js
app_name/static/script.js app_name/static/script.js
static/script.js static/script.js

To disable this behaviour set { STATIC_LOOKUP : False }

Note: This uses Django's built-in staticfinder under the hood

3. Auto Reload

This plugin reloads your browser window whenever a relavent file is changed!

4. JS Import helpers

Just like STATIC_LOOKUP, helpers are available in js too. It uses vite's alias under the hood.

The default aliases are:

Alias Points to
@ <root of the project>
@s: /static/
@t: /templates/

Why alias for templates? Do you keep your *.vue files in static directory?

import whatevs from '@/path/to/whatever'
// Output: import whatevs from '<project_root>/path/to/whatever'

import customAlert from '@s:ui/components/alert'
// Output: import customAlert from '<path_to_ui_app>/static/ui/components/alert'

import vueCounter from '@t:ui/vue/counter.vue'
// Output: import vueCounter from '<path_to_ui_app>/templates/ui/vue/counter.vue'

Setting { STATIC_LOOKUP : False } will result in

Alias Points to
@ <root of the project>
@s: /static
@t: /templates

5. Js import autocompletions

You can get autocompletions for these import aliases in the IDEs that support jsconfig.json

To enable this feature, add a jsconfig.json file in your projects root directory or in the same directory as vite.config.js

Note: If you are using typescript then it will automatically add the paths there while running dev command

6. Test for production

Do this to test if your build files works as expected before shipping it to the production

  1. In your projects urls.py add

    urlpatterns = [
        # some urls
        path('', include('django_vite_plugin.urls')),
        # other urls
    ]
    
  2. In settings.py set

    ...
    
    STATICFILES_DIRS = [
        BASE_DIR / 'build'
    ]
    
    ...
    
    DJANGO_VITE_PLUGIN = {
        # other options
        'DEV_MODE' : False,
        'BUILD_DIR': 'build'
    }

    Replace build with your build directory and make sure it's different from STATIC_ROOT if it's set

  3. If your BUILD_URL_PREFIX contains http:// or https:// comment that out.

  4. Run npm run build to build your assets and enjoy!