- Introduction
- Setup Webpack Project with Django
- Load Webpack bundles in Django
- Linting in Webpack
- Load Webpack hash bundle in Django
- Code splitting with Webpack
- How to config HMR with Webpack and Django
- How to use HtmlWebpackPlugin to load Webpack bundle in Django
If you want a quick start with Webpack and Django, please check python-webpack-boilerplate
Objective
By the end of this chapter, you should be able to:
- Understand the code splitting workflow in Webpack.
- Config
splitChunks
to control the splitting behavior. - Load bundle file with
splitChunks
and Djangostatic
templatetag.
Background
What should we do When the bundle file grow? (new features, new 3-party library)
It's also good practice to extract third-party libraries, such as lodash or react, to a separate vendor chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date.
This can be done by using the splitChunks option of the SplitChunksPlugin
splitChunks
Let's update webpack/webpack.common.js
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
// get the name. E.g. node_modules/packageName/not/this/part.js
// or node_modules/packageName
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1];
// npm package names are URL-safe, but some servers don't like @ symbols
return `npm.${packageName.replace("@", "")}`;
}
},
}
},
},
Notes:
- We created a
vendor
group in theoptimization.splitChunks.cacheGroups
- The
test
means it would work on all packages which are innode_modules
- The
name
function would be used to generate name for the chunk.
(frontend)$ npm run build
(frontend)$ cat webpack-stats.json
{
"status": "done",
"chunks": {
"app": [
"js/npm.jquery.e2d46062.js",
"js/npm.bootstrap.a31ec5e3.js",
"js/app.fd53aa41.js",
"css/app-e3e173a2b456b7aaf3a4.css"
]
},
}
- As we can see,
npm.jquery
andnpm.bootstrap
chunks are generated. - Actually, if we import new packages in the
src/index.js
(such asAxios
), new chunks would be also generated.
The above config is to help us better understand the cacheGroups
Manual config
In some cases, we can use cacheGroups
to control the code splitting behavior.
Let's update webpack/webpack.common.js
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
},
jquery: {
test: /[\\/]node_modules[\\/](jquery)[\\/]/,
name: 'jquery',
},
}
},
},
Notes:
- We created a
vendor
group which has namevendor
- We created a
jquery
group, which has namejquery
, thetest
would make sure the chunk only matchjquery
. - If we want the test match multiple packages, you can use Regex like this
/[\\/]node_modules[\\/](react|react-dom)[\\/]/
{
"status": "done",
"chunks": {
"app": [
"js/jquery.5007ce70.js",
"js/vendors.1acdbaad.js",
"js/app.44ab1a1c.js",
"css/app-e3e173a2b456b7aaf3a4.css"
]
},
"publicPath": "/static/",
"assets": {
"js/app.44ab1a1c.js": {
"name": "js/app.44ab1a1c.js",
"publicPath": "/static/js/app.44ab1a1c.js"
},
"js/jquery.5007ce70.js": {
"name": "js/jquery.5007ce70.js",
"publicPath": "/static/js/jquery.5007ce70.js"
},
"js/vendors.1acdbaad.js": {
"name": "js/vendors.1acdbaad.js",
"publicPath": "/static/js/vendors.1acdbaad.js"
},
"public/.gitkeep": {
"name": "public/.gitkeep",
"publicPath": "/static/public/.gitkeep"
},
"js/jquery.5007ce70.js.LICENSE.txt": {
"name": "js/jquery.5007ce70.js.LICENSE.txt",
"publicPath": "/static/js/jquery.5007ce70.js.LICENSE.txt"
},
"js/vendors.1acdbaad.js.LICENSE.txt": {
"name": "js/vendors.1acdbaad.js.LICENSE.txt",
"publicPath": "/static/js/vendors.1acdbaad.js.LICENSE.txt"
},
"js/app.44ab1a1c.js.map": {
"name": "js/app.44ab1a1c.js.map",
"publicPath": "/static/js/app.44ab1a1c.js.map"
},
"js/jquery.5007ce70.js.map": {
"name": "js/jquery.5007ce70.js.map",
"publicPath": "/static/js/jquery.5007ce70.js.map"
},
"js/vendors.1acdbaad.js.map": {
"name": "js/vendors.1acdbaad.js.map",
"publicPath": "/static/js/vendors.1acdbaad.js.map"
},
"css/app-e3e173a2b456b7aaf3a4.css": {
"name": "css/app-e3e173a2b456b7aaf3a4.css",
"publicPath": "/static/css/app-e3e173a2b456b7aaf3a4.css"
},
"css/app-e3e173a2b456b7aaf3a4.css.map": {
"name": "css/app-e3e173a2b456b7aaf3a4.css.map",
"publicPath": "/static/css/app-e3e173a2b456b7aaf3a4.css.map"
},
}
}
Notes:
- The
jquery
chunk contains code fromjquery
- The
vendors
chunk contains code from thebootstrap
It is also recommended to use webpack-bundle-analyzer if you want to customize splitChunks
.
Django
In the previous chapters, when our JS code size is small, we can use Django static
templatetag to import js code like this
<script src="{% static 'js/vendors.js' %}"></script>
<script src="{% static 'js/app.js' %}"></script>
- When the JS code size grow bigger, we can config code splitting to generate some specific
chunk
file. - And then, we can config Webpack to remove
hash
from the generated bundle file. - In the end, we can import JS in Django template like this
<script src="{% static 'js/vendors-aaa.js' %}"></script>
<script src="{% static 'js/vendors-bbb.js' %}"></script>
<script src="{% static 'js/vendors-ccc.js' %}"></script>
<script src="{% static 'js/app.js' %}"></script>
Conclusion
- Introduction
- Setup Webpack Project with Django
- Load Webpack bundles in Django
- Linting in Webpack
- Load Webpack hash bundle in Django
- Code splitting with Webpack
- How to config HMR with Webpack and Django
- How to use HtmlWebpackPlugin to load Webpack bundle in Django
If you want a quick start with Webpack and Django, please check python-webpack-boilerplate