Confident Asset Deployments with Webpack & Django, part 3

Confident Asset Deployments with Webpack & Django, part 3

django-logo-positive

In the previous posts in this series, we've explored why we've switched to delivering front-end assets with Webpack and how we configure our Webpack builds.

Here, we're going to cover how to integrate our Webpack builds into Django so that our site serves links to the newest version of our front-end assets.

Previously

You may recall that we've configured our Webpack builds to produce small JSON files capturing the status of the build using webpack-bundle-tracker. These files look something like:

This file describes fully what Webpack produced during its build process. The important parts are the status key (if a build fails, this property will be `error`) and the chunks produced. Our webpack.config.js file specifies only a single entry point and thus only one chunk is built although multiple files were produced for that chunk.

Most important is the name of each file produced. Because the output of our webpack config is [name]-[hash], a unique hash based on the contents of the bundle is appended to the name. Any and all code changes (whether ours or third-party libraries) will produce a different hash.

New call-to-action 

Integrating with Django

Ultimately, in our Django templates, we need <link> and <script> tags to point to the current version of our assets. As we've seen above, every front-end code change and subsequent build will produce new files with new hashes. Instead of manually copy/pasting new hashes into our templates (error-prone and if done incorrectly means disaster) we use django-webpack-loader to read the webpack stats files at runtime and produce the correct links.

To install, we use pip:

$ pip install django-webpack-loader

We must edit our settings.py (or whatever module you use to specify site settings) and add a few important pieces.

First and foremost, we should add it to our INSTALLED_APPS:

INSTALLED_APPS = [
...
'webpack_loader',
...
]

Next, we need to describe the location of our stats files in WEBPACK_LOADER:

WEBPACK_LOADER = {
'APP': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(SITE_ROOT, 'static', 'webpack-stats-app.prod.json'),
},
}

SITE_ROOT was specified higher up in settings.py to point to the directory in which the important Django files like urls.py, wsgi.py, etc. live. django-webpack-loader accepts many more settings fully described in the documentation.

The named bundles (in this case APP) allow us to specify multiple stats files for use in the site which can be helpful for large sites with many different front-ends. This is analogous to how DATABASES allows for multiple named database connections.

`django-webpack-loader` integrates with the staticfiles application so we need to make sure that the folder in which Webpack is producing bundles is in a directory specified in STATICFILES_DIRS:

STATICFILES_DIRS = (
...
os.path.join(SITE_ROOT, 'static', 'bundles'),
...
)

With these changes in settings.py, we're now ready to alter our templates to use webpack_loader.

 

Tweaking Templates

django-webpack-loader includes a template tag that will produce the correct <link> or <script> tag based on arguments.

So, our base template can look something like this:


...

The first argument for render_bundle is the name of the chunk in the Webpack build, the second is the file type to include. The third specifies the name of the bundle and is only necessary if you have multiple webpack.stats.json files specified in your project settings.

At this point, the necessary <link> or <script> tags will be built during template rendering based on the contents of the webpack.stats.json files. Hooray for no copy/pasting!

 

Deploying to Production

Because a single file directs which version of our assets we use for a site, the only thing that needs to change during a deploy is the webpack.stats.json file. Whenever we deploy, the smaller a change the better because if issues arise we can easily roll-back to a previous version of our assets by reverting the changes to the stats file.

Also, because we're only ever producing new assets (versioned by the hash in their name), we never need to modify existing assets. Modifying existing assets during a deploy can cause weird, hard-to-debug issues due to browsers not fetching the modifications.

In our final post of this series, we'll describe a few integrations we've built for testing the stats files and distributing the built bundles.

 New call-to-action

Article by Scott Burns, VP of Engineering for Stratasan

If you would like to learn more about Stratasan and how we could equip your team to maximize strategic growth potential, email us at sales@stratasan.com.

Connect with Stratasan on LinkedIn or follow Stratasan on Twitter and Facebook.

app application Blog code coding developer devolopers Django DjangoCon engineer Engineering health care healthcare Javascript tech technology web