Django Webpack Loader settings tips

Django Webpack Loader settings tips

Sometimes we can face an issue, where we want to use Django and React together, and we need something to connect them. These such tools as Django-webpack-loader and webpack-bundle-tracker can provide a convenient and flexible workflow, where you can set different environments and packages for your local, testing, and production servers. Down below, you can find examples of setting files, which will be useful for quick and confident start of development.

Directories structure

Here you can see the directory structure, which will be used in our example and will help you to understand how all files work together. Feel free to change this structure for your purposes and preferences.

frontend
|
|__node_modules
|__src
|  |__index.js
|
|__static
|  |__forntend
|     |__bundles
|     
|__webpack
|  |__stats
|  |  |__base.json
|  |  |__watch.json
|  |
|  |__base.config.js
|  |__development.config.js
|  |__production.config.js
|  |__watch.config.js
|
|__package.json
|__server.js

Setting base.config.js

Let's start with base.config.json config file, which provides all common settings for the other three modes: local, develop, and production. Here you should define the entry file for your project, output directory path and the filename for the frontend builds, additional modules, plugins, and others.

The base code example looks like this:

module.exports = {
    entry: "./src/index.js",
    output: {
        path: path.resolve(__dirname, "../static/frontend/bundles/"),
         filename: "[name]-[hash].js",
    },
    module: {
    },
    resolve: {
        extensions: ["*", ".js", ".jsx"],
    },
    optimization: {
        minimize: true,
    },
    plugins: [
        new BundleTracker({ filename: "./webpack/stats/base.json" }),
        new Dotenv(),
    ],
};

The output.path path.resolve(__dirname, "../static/frontend/bundles/") saves build's files in a static folder for the frontend app, which will be collected into the general static folder on the development or production server after the command manage.py collectstatic And plugin BundleTracker({ filename: "./webpack/stats/base.json" }) which will track all frontend changes and gather all of them in the static files folder.

Setting development.config.js and production.config.js

These files are needed to describe the change of mode ("development", "production"). They are inherited from the webpack/base.config.js file, and you can define or modify specific settings for your work environment, like variables, local paths, environment, etc.

var config = require("./base.config.js");

const NODE_ENV = process.env.NODE_ENV || "production";

config.mode = NODE_ENV;

config.optimization = {
    minimize: true,
    splitChunks: {
        chunks: "all",
    },
};

module.exports = config;

Setting watch.config.js

This file is used for local development. It allows you to run npm run watch command in a terminal, and the site will run on your local server. It is like base.config.js, and has its settings, depending on the developer's needs.

config.target = "web";
config.mode = NODE_ENV;
config.entry = [
    "webpack/hot/only-dev-server",
    path.join(srcPath, "index.js"), 
];

config.output = {
    path: distPath,
    filename: "js/[name]-[hash].js",
    sourceMapFilename: "js/[name]-[hash].js.map",
    publicPath: "http://" + host + ":" + port + "/static/dist/",
};

config.plugins = config.plugins.concat([
    //tells webpack where to store data about your bundles.
    new BundleTracker({ filename: "./webpack/stats/watch.json" }),
]);

config.devServer = {
    host: host,
    port: port,
    hot: true,
    historyApiFallback: true,
    allowedHosts: "all",
    headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Headers":
            "Origin, X-Requested-With, Content-Type, Accept",
        "Access-Control-Allow-Credentials": "true",
        "X-Custom-Header": "yes",
    },
};

Setting server.js

This file is required for local development to automatically track and update the site when the code is changed.

The 'config' variable contains a path to the watch.config.js file.

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

var config = require('./webpack/watch.config');

var compiler = webpack(config);
var server = new WebpackDevServer(compiler, config.devServer);


server.start(
  config.devServer.port,
  config.devServer.host,
  function (err, result) {
    if (err) {
      console.log(err);
    }
    console.log('Listening at localhost:' + config.devServer.port);
  }
);

Setting package.json

Also, we have to define our scripts in package.json file. Which will be launched by the command npm run <script>

{
    "scripts": {
        "build-dev": "webpack --config webpack/development.config.js --mode development",
        "build-prod": "webpack --config webpack/production.config.js --mode production",
        "watch": "node server.js"
      }
}

"build-dev" - is responsible for building the site on the test environment, where the "--config" flag specifies the path for configuring this type of build, and the "--mode" option specifies the mode in which the build is created.

"build-prod" - Similar to the test environment.

"watch" - for local development, with the path to the server.js file.

Setting WEBPACK_LOADER in Django settings.py

And finally, we have to set webpack in Django settings according to the documentation.

STATIC_ROOT = "/data/static/"

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'frontend/bundles/',
        'STATS_FILE': os.path.join(
            FRONTEND_DIR, 'webpack/stats/base.json'),
    },
}

BUNDLE_DIR_NAME - is the path to build files on production or develop server relative to STATIC_ROOT, which you can set as you need. In our case STATIC_ROOT = "/data/static/", so the full path to our app's staticfiles on the server will look like "data/static/frontend/", and the path to building files: "data/static/frontend/bundles/".

STATS_FILE - is the path to base.json file in our project for development and production servers, which we already have defined in base.config.json.

plugins: [
    new BundleTracker({ filename: "./webpack/stats/base.json" }),
],

This path we have to define fully. And FRONTEND_DIR, which contains path to the "frontend" directory joined the rest of the path.

For local development, you should change STATS_FILE path to watch.json instead of base.json, which we also have defined in watch.config.json.

config.plugins = config.plugins.concat([
    new BundleTracker({ filename: "./webpack/stats/watch.json" }),
]);
line

Looking for an enthusiastic team?