- 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
splitChunksto control the splitting behavior. - Load bundle file with
splitChunksand Djangostatictemplatetag.
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
vendorgroup in theoptimization.splitChunks.cacheGroups - The
testmeans it would work on all packages which are innode_modules - The
namefunction 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.jqueryandnpm.bootstrapchunks 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
vendorgroup which has namevendor - We created a
jquerygroup, which has namejquery, thetestwould 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
jquerychunk contains code fromjquery - The
vendorschunk 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
chunkfile. - And then, we can config Webpack to remove
hashfrom 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