Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Transparently use webpack with django

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.txt
NotificationsYou must be signed in to change notification settings

django-webpack/django-webpack-loader

Repository files navigation

Build StatusCoverage Statuspyversionsdjversions

Integrate Webpack bundles in Django templates by using a simple template tag:

{%loadrender_bundlefromwebpack_loader%}<html>  <head>{%render_bundle'main''css'%}  </head></html>

Behind the scenes, Django Webpack Loader consumes astats file generated bywebpack-bundle-tracker and lets you use the generated bundles in Django.

Achangelog is available.

Compatibility

Generally, Python, Django, and Node LTS releases will be supported until EOL. Checktests/tox.ini for details.
Versions not listed intests/tox.ini may still work, but maintainers will not test them, nor solve issues with them.
Examples below are in Webpack 5.

Install

npm install --save-dev webpack-bundle-trackerpip install django-webpack-loader

Configuration

For kick-starting a full example project with opinionated development and production settings, you can check thedjango-react-boilerplate. For a more flexible configuration, keep reading.

Configuringwebpack-bundle-tracker

Before configuringdjango-webpack-loader, let's first configure what's necessary onwebpack-bundle-tracker side. Update your Webpack configuration file (it's usually onwebpack.config.js in the project root). Make sure your file looks like this (adapt to your needs):

constpath=require("path");constwebpack=require("webpack");constBundleTracker=require("webpack-bundle-tracker");module.exports={context:__dirname,entry:"./assets/js/index",output:{path:path.resolve(__dirname,"assets/webpack_bundles/"),publicPath:"auto",// necessary for CDNs/S3/blob storagesfilename:"[name]-[contenthash].js",},plugins:[newBundleTracker({path:__dirname,filename:"webpack-stats.json"}),],};

The configuration above expects theindex.js (the app entrypoint file) to live inside the/assets/js/ directory (this guide going forward will assume that all frontend related files are placed inside the/assets/ directory, with the different kinds of files arranged within its subdirectories).

The generated compiled files will be placed inside the/assets/webpack_bundles/ directory and thestats file with the information regarding the bundles and assets (webpack-stats.json) will be stored in the project root. You may addwebpack-stats.json to your.gitignore.

Configuring the Django settings file

First of all, addwebpack_loader toINSTALLED_APPS.

INSTALLED_APPS= (    ...'webpack_loader',    ...)

Below is the recommended setup for the Django settings file when usingdjango-webpack-loader.

STATICFILES_DIRS= (os.path.join(BASE_DIR,'assets'),)WEBPACK_LOADER= {'DEFAULT': {'BUNDLE_DIR_NAME':'webpack_bundles/','CACHE':notDEBUG,'STATS_FILE':os.path.join(BASE_DIR,'webpack-stats.json'),'POLL_INTERVAL':0.1,'IGNORE': [r'.+\.hot-update.js',r'.+\.map'],    }}

Note that you must set the path where you're keeping your static assets and Webpack bundles inSTATICFILES_DIRS.

For that setup, we're using theDEBUG variable provided by Django. Since in a production environment (DEBUG = False) the assets files won't constantly change, we can safely cache the results (CACHE=True) and optimize our flow, asdjango-webpack-loader will read the stats file only once and store the assets paths in memory. IfCACHE=False, we'll always read the stats file to get the assets paths.

TheSTATS_FILE parameter represents the output file produced bywebpack-bundle-tracker. Since in the Webpack configuration file we've named itwebpack-stats.json and stored it on the project root, we must replicate that setting on the backend side.

During development, the stats file will change often, therefore we want to always poll for its updated version (every 0.1s, as defined onPOLL_INTERVAL).

⚠️ In production (DEBUG=False), we'll only fetch the stats file once, soPOLL_INTERVAL is ignored.

IGNORE is a list of regular expressions. If a file generated by Webpack matches one of the expressions, the file will not be included in the template.

Compiling the frontend assets

Using Webpack, you must generate the frontend bundle along with the stats file usingwebpack-bundle-tracker before usingdjango-webpack-loader in Django templates. Note you'll probably want different configurations in development vs. production. The pipeline should look like this:

flowchart TD    A("Run webpack")    A --> |CSS, JS, imgs, fonts| B(Collect compiled assets)    A --> |webpack-stats.json| C(Read on Django templates)
Loading

In development, we can simply do:

# in one shellnpx webpack --mode=development --watch# in another shellpython manage.py runserver

Checkthe full example for development here.

Aditionally, hot reload is available through a specific config. Checkthis section.

⚠️ For compiling and serving the frontend assets in production, checkthis section.

Usage

In order to render the frontend code into the Django templates, we use therender_bundle template tag.

Its behavior is to accept a string with the name of an entrypoint from the stats file (in our case, we're usingmain, which isthe default) and it'll proceed to include all files under that entrypoint. You can read more about the entrypoints concepthere.

⚠️ You can also check an example on how to use multipleentry valueshere.

Below is the basic usage forrender_bundle within a template:

{%loadrender_bundlefromwebpack_loader%}<html>  <head>{%render_bundle'main''css'%}  </head></html>

That will render the proper<script> and<link> tags needed in your template.

Using in tests

To run tests whererender_bundle shows up, since we don't havewebpack-bundle-tracker at that point to generate the stats file, the calls to render the bundle will fail. The solution is to use theFakeWebpackLoader in your test settings:

WEBPACK_LOADER['DEFAULT']['LOADER_CLASS']='webpack_loader.loaders.FakeWebpackLoader'

Using in Production

The recommended apporach is to have a production pipeline that generates the frontend bundle along with the stats file during thedeployment phase. We recommend keeping the generated bundles and the stats file outside the version control. In other words, addwebpack-stats.json andassets/webpack_bundles/ to your.gitignore.

Assuming static files is properly configured using Django built-ins or something likedjango-storages, a simple production deployment can use Django's owncollectstatic. Remember the Django settings values ofSTATICFILES_DIRS,BUNDLE_DIR_NAME,STATS_FILE, and Webpack'soutput.path must all be compatible:

// webpack.config.jsmodule.exports={// ...context:__dirname,output:{// Emit bundle files at "assets/webpack_bundles/":path:path.resolve(__dirname,"assets/webpack_bundles/"),publicPath:"auto",// necessary for CDNs/S3/blob storagesfilename:"[name]-[contenthash].js",},plugins:[// Emit 'webpack-stats.json' in project root for Django to find it:newBundleTracker({path:__dirname,filename:"webpack-stats.json"}),],};
# app/settings.pyBASE_DIR=  ...# set to project rootSTATICFILES_DIRS= (# make Django collect all "assets/" and "assets/webpack_bundles"# to be served at "my-static-url.com/asset-name.png"# and "my-static-url.com/webpack_bundles/main.js"os.path.join(BASE_DIR,'assets'),)WEBPACK_LOADER= {'DEFAULT': {# Bundle directory, like in "my-static-url.com/webpack_bundles/main.js":'BUNDLE_DIR_NAME':'webpack_bundles/',# Absolute path to where 'webpack-stats.json' is in Django project root:'STATS_FILE':os.path.join(BASE_DIR,'webpack-stats.json'),# ...    }}

In your deployment script, you must first run your Webpack build in production-mode, before callingcollectstatic:

NODE_ENV=production webpack --progress --bail --mode=productionpython manage.py collectstatic --noinput

This means we're building the assets and, since we havewebpack-bundle-tracker in our Webpack building pipeline, thewebpack-stats.json stats file is also populated. If you followed the default configuration, thewebpack-stats.json will be at Django's project root (BASE_DIR) and therender_bundle template tag will be able to use it.

However, production usage for this package isfairly flexible, as the entire Django-Webpack integration depends only on thewebpack-stats.json file.

⚠️ Heroku is one platform that automatically runs collectstatic for you, so you need to set theDISABLE_COLLECTSTATIC=1 environment var and manually run collectstatic after running Webpack. In Heroku, this is achieved with apost_compile hook. Here'san example.

Advanced Usage

Hot reload

Hot reload (Hot Module Replacement) is critical for a improving the development workflow. In case you wish to enable for your project, please check outthis example, in particular howwebpack.config.js is configured. The key is to set thepublicPath anddevServer.

Dynamic Imports

In case you wish to useDynamic Imports, please check outthis example, in particular howwebpack.config.js is configured.

Extra options forwebpack-bundle-tracker

Checkwebpack-bundle-trackerREADME for all supported options, such as relative paths, integrity hashes, timestamp logging, etc.

ExtraWEBPACK_LOADER settings in Django

Set those extra settings inside like this:

WEBPACK_LOADER= {'DEFAULT': {# settings go here    }
  • TIMEOUT is the number of seconds webpack_loader should wait for Webpack to finish compiling before raising an exception.0,None or leaving the value out of settings disables timeouts

  • INTEGRITY is a flag enablingSubresource Integrity on rendered<script> and<link> tags. Integrity hash is fetched from the stats ofBundleTrackerPlugin. Theconfiguration optionintegrity: true is required.

  • CROSSORIGIN: If you use theintegrity attribute in your tags and you load your webpack generated assets from another origin (that is not the samehost:port as the one you load the webpage from), you can configure theCROSSORIGIN configuration option. The default value is'' (empty string), where an emptycrossorigin attribute will be emitted when necessary. Valid values are:'' (empty string),'anonymous' (functionally same as the empty string) anduse-credentials. For an explanation, seehttps://shubhamjain.co/2018/09/08/subresource-integrity-crossorigin/. A typical case for this scenario is when you develop locally and your webpack-dev-server runs with hot-reload on a local host/port other than that of django'srunserver.

  • CSP_NONCE: Automatically generate nonces for rendered bundles fromdjango-csp. DefaultFalse. Set this toTrue if you usedjango-csp and and'strict-dynamic'CSP mode.

  • LOADER_CLASS is the fully qualified name of a python class as a string that holds the custom Webpack loader. This is where behavior can be customized as to how the stats file is loaded. Examples include loading the stats file from a database, cache, external URL, etc. For convenience,webpack_loader.loaders.WebpackLoader can be extended. Theload_assets method is likely where custom behavior will be added. This should return the stats file as an object.

Here's a simple example of loading from an external URL:

importrequestsfromwebpack_loader.loadersimportWebpackLoaderclassExternalWebpackLoader(WebpackLoader):defload_assets(self):url=self.config['STATS_URL']returnrequests.get(url).json()
  • SKIP_COMMON_CHUNKS (Default:False) is a flag which prevents already generated chunks from being included again in the same page. This should only happen if you use more than one entrypoint per Django template (multiplerender_bundle calls). By enabling this, you can get the same default behavior of theHtmlWebpackPlugin. The same caveats apply as when usingskip_common_chunks onrender_bundle, see that section below for more details.

Rendering by file extension

render_bundle also takes a second argument which can be a file extension to match. This is useful when you want to render different types for files in separately. For example, to render CSS in head and JS at bottom we can do something like this:

{%loadrender_bundlefromwebpack_loader%}<html>  <head>{%render_bundle'main''css'%}  </head>  <body>    ....{%render_bundle'main''js'%}  </body></head>

Using preload

Theis_preload=True option in therender_bundle template tag can be used to addrel="preload" link tags:

{%loadrender_bundlefromwebpack_loader%}<html>  <head>{%render_bundle'main''css'is_preload=True%}{%render_bundle'main''js'is_preload=True%}{%render_bundle'main''css'%}  </head>  <body>{%render_bundle'main''js'%}  </body></html>

Accessing other webpack assets

webpack_static template tag provides facilities to load static assets managed by Webpack in Django templates. It is like Django's built instatic tag but for Webpack assets instead.

In the example below,logo.png can be any static asset shipped with any npm package:

{%loadwebpack_staticfromwebpack_loader%}<!-- render full public path of logo.png--><imgsrc="{% webpack_static 'logo.png' %}"/>

The public path is based onwebpack.config.jsoutput.publicPath.

Please note that this approach will use the original asset file, and not a post-processed one from the Webpack pipeline, in case that file had gone through such flow (e.g.: You've imported an image on the React side and used it there, the file used within the React components will probably have a hash string on its name, etc. This processed file will be different than the one you'll grab withwebpack_static).

Useskip_common_chunks onrender_bundle

You can use the parameterskip_common_chunks=True orskip_common_chunks=False to override the globalSKIP_COMMON_CHUNKS setting for a specific bundle.

In order for this option to work,django-webpack-loader requires therequest object to be in the template context. Therequest object is passed by default via thedjango.template.context_processors.request context processor, so make sure you have that.

If you don't haverequest in the context for some reason (e.g. usingTemplate.render orrender_to_string directly without passing the request), you'll get warnings on the console and the common chunks will remain duplicated.

Appending file extensions

Thesuffix option can be used to append a string at the end of the file URL. For instance, it can be used if your Webpack configuration emits compressed.gz files.

{%loadrender_bundlefromwebpack_loader%}<html>  <head>    <metacharset="UTF-8">    <title>Example</title>{%render_bundle'main''css'%}  </head>  <body>{%render_bundle'main''js'suffix='.gz'%}  </body></html>

Multiple Webpack configurations

django-webpack-loader also supports multiple Webpack configurations. Assuming you have different Webpack configs, each with a differentoutput.path, the following configuration defines 2 Webpack stats files in settings and uses theconfig argument in the template tags to influence which stats file to load the bundles from:

WEBPACK_LOADER= {'DEFAULT': {'BUNDLE_DIR_NAME':'bundles/','STATS_FILE':os.path.join(BASE_DIR,'webpack-stats.json'),    },'DASHBOARD': {'BUNDLE_DIR_NAME':'dashboard_bundles/','STATS_FILE':os.path.join(BASE_DIR,'webpack-stats-dashboard.json'),    }}
{%loadrender_bundlefromwebpack_loader%}<html>  <body>    ....{%render_bundle'main''js''DEFAULT'%}{%render_bundle'main''js''DASHBOARD'%}<!-- or render all files from a bundle-->{%render_bundle'main'config='DASHBOARD'%}<!-- the following tags do the same thing-->{%render_bundle'main''css''DASHBOARD'%}{%render_bundle'main'extension='css'config='DASHBOARD'%}{%render_bundle'main'config='DASHBOARD'extension='css'%}<!-- add some extra attributes to the tag-->{%render_bundle'main''js''DEFAULT'attrs='async charset="UTF-8"'%}  </body></head>

File URLs instead of HTML tags

If you need the URL to an asset without the HTML tags, theget_files template tag can be used. A common use case is specifying the URL to a custom CSS file for a Javascript plugin.

get_files works exactly likerender_bundle except it returns a list of matching files and lets you assign the list to a custom template variable.

Each object in the returned list has 2 properties:

  1. name, which is the name of a chunk from the stats file;
  2. url, which can be:
  3. ThepublicPath if the asset has one;
  4. Thepath to the asset in the static files storage, if the asset doesn't have apublicPath.

For example:

{%loadget_filesfromwebpack_loader%}{%get_files'editor''css'aseditor_css_files%}CKEDITOR.config.contentsCss = '{{ editor_css_files.0.url }}';<!-- or list down name and url for every file--><ul>{%forcss_fileineditor_css_files%}    <li>{{ css_file.name }} : {{ css_file.url }}</li>{%endfor%}</ul>

Jinja2 Configuration

If you need to output your assets in a jinja template, we provide a Jinja2 extension that's compatible withdjango-jinja.

To install the extension, add it to theTEMPLATES configuration in the["OPTIONS"]["extension"] list.

fromdjango_jinja.builtinsimportDEFAULT_EXTENSIONSTEMPLATES= [  {"BACKEND":"django_jinja.backend.Jinja2","OPTIONS": {"extensions":DEFAULT_EXTENSIONS+ ["webpack_loader.contrib.jinja2ext.WebpackExtension",      ],    }  }]

Then in your base jinja template, do:

{{ render_bundle('main') }}

Note:get_files in Jinja2 is calledwebpack_get_files.

Migrating from version < 1.0.0

In order to usedjango-webpack-loader>=1.0.0, you must ensure thatwebpack-bundle-tracker@1.0.0 is being used on the JavaScript side. It's recommended that you always keep at least minor version parity across both packages for full compatibility.

Contributing

This project includes a Makefile that provides several useful commands for building, installing, and publishing the project. Please feel free to open PRs or create issues!

Available Commands

  • clean: Removes generated files and directories.
  • build: Cleans the project and builds the distribution packages.
  • test: Run the tests.
  • install: Installs the project's build dependencies. Will initialize a virtual environment if one does not exist.
  • publish: Builds the distribution packages and publishes them to the specified repository.
  • register: Registers the package on the specified repository.

To execute a command, runmake <command> in the project's root directory.

Virtual Environment Settings

  • ENV: The name of the virtual environment. (Default:venv)
  • REPOSITORY: The repository to publish the distribution packages to. (Default:pypi)

Special Thanks

Django Webpack Loader was originally created byOwais Lone and received contributions from more than 50 developers since its inception, as well as many others who assisted with issues, comments, articles, talks, etc. Thanks for everyone who's been part of Django Webpack Loader community!

Commercial Support

alt text

This project is currently maintained byVinta Software and is used in products of Vinta's clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch:contact@vinta.com.br

About

Transparently use webpack with django

Topics

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.txt

Stars

Watchers

Forks

Packages

No packages published

Contributors63


[8]ページ先頭

©2009-2026 Movatter.jp