watch, webpack bundle-tracker/loader, Redux

Maik Luchtmeyer
6 min readNov 11, 2018
Photo by Vincent Botta on Unsplash

This article follows up on Part 3 of my Full Stack series, where we finished with our React integration. In this part we will further improve our setting with Django,React and webpack and then integrate Redux to our stack 😎.

watch

With a look to part 3, we have to call npm run dev everytime to generate a new bundle, which can easily take 5–10sek in development mode. This sucks. But of course webpack has something for us, watch . Edit the dev script in package.json :

If you now run npm run dev webpack is watching your files (from entrypoint). So having the Django dev-server active, change your “Hello,World!" message in your index.jsx , save and reload http://127.0.0.1:8000/. Cool. With watch=true webpack just commits the changes, so your new bundle will arrive at lightning speed.

webpack-bundle-tracker

Next thing is, if webpack now fails to bundle our app, we have to check our terminal for the webpack error traceback. This sucks. But there is help. First we need to install webpack-loader, which will output a file, that tells us the status of our bundle process.

npm install --save-dev webpack-bundle-tracker

and add the plugin into our webpack.config.js :

Now restart npm run dev and you will see, that webpack is now spitting out a webpack-stats.json file (do not add it to git). It tells if the bundling was successful, if webpack is still bundling or if there was any error etc. This will be helpful.

django-webpack-loader

To make any use of our webpacks-stats.json we need something, which consumes it. We use Django, hence we will use the django-webpack-loader.

Therefore,

pip install django-webpack-loader
pip freeze > requirements.txt

add webpack_loader to our settings.py :

add WEBPACK_LOADER settings inside settings.py :

now we can change our index.html template to include the webpack-loader tags:

Done! Now try to break your index.jsx syntax somewhere, save file and reload http://127.0.0.1:8000/ and look what happens

Django raises WebpackError

django-webpack-loader consumed the webpack-stats.json and raised an WebpackError, which is displayed by the django debug page. This makes things easier. However, django-webpack-loader does a lot more than that, like stopping request when webpack is bundling, see the docs.

You can also go a step further and use react-hot-loader, the webpack-dev-server to live edit your components (no page reloading anymore). See here. Maybe I will add this later, pretty neat .

Redux

Before we add Redux to our project, we need something more sophisticated than the react “Hello, World” example. And it should have any value within the blueprint. So lets create a login-component, so we can login into our api and store the results in our redux store. For this purpose we will test out the tokenAuthentication from Django-REST-framework , precisely the obtain_auth_token view. It’s purpose is, to create (if not existent) or receive a token for a user.

Therefore, our goal is to create a login-form-component, which triggers a redux action, that POST’s our credentials to the obtain_auth_token view and stores the obtained token in our redux store.

Caution : This setup’s purpose is solely to demonstrate the functionality of our projects components.

Always use Django’s standard login view when creating login pages. This will ensure your login views are properly protected. (Django-REST-framework, docs)

Okay, one step back. To enable tokenAuthentication we need to add some Django-REST-Framework settings inside settings.py :

And migrate to include a token table for our users,

$ python manage.py migrate 

Now use the obtain_auth_token view to register a new url inside backend/urls.py :

And try our api at http://127.0.0.1:8000/api/login/ . You should see the message {"detail”:Method\"GET\" not allowed."}. As step two we will now create a login-form to enter our credentials.

Create frontendapp/src/components/login.jsx

Login-Component

Inside login.jsx we define a react-component, which renders a standard login-form and onSubmit we use an action login , which we map to our props through react-redux ‘s connect .

Therefore, install the depency :

$ npm install --save react-redux

I also added some bootstrap classNames, so I don’t always have to look at those ugly boxes while creating this guide. You can ignore them or just include bootstrap at index.html like here.

But there is no store to connect to. So let’s setup a couple of things inside frontendapp/src/index.jsx :

Important rows:

  • 10 : Enable Redux-Dev-Tools, see here.
  • 11 : createStore from our Reducer (we still have to create this) and apply the middleware thunk, which allows us to use fetch in our action and dispatch an action if our api-response arrived (we still have to create our action).
  • 20–22 : Wrap a <Provider> around our Login-Component, which makes our store available to <Login> and all its children (in a more progressed project the provider would wrap the <RootComponent> or similar).

Hence, install the new dependencies,

$ npm install --save redux redux-thunk 

Since we applied thunk we can now create our login action within frontendapp/scr/actions/auth.js to fetch our api data :

Okay so let’s break down what happens in our auth.js :

  1. CSFR-Token : Since we are using POST (obtain_auth_token will create a new token if not existent) and CSFR middleware is activated by Django per default, we have to include the CSFR-Token . We do this like documented by Django here. We need jquery for that, therefore
$ npm install --save jquery

2. fetch : Since we grabbed our CSFR-Token , we include it in our header and send a POST request to our API-endpoint. See at row 22&25, that obtain_auth_token requires the credentials to be send inside the body .

3. dispatch : Depending on the response of our API-endpoint, we use dispatch to trigger an action and include the respective data. These actions will be consumed by our reducer (which we will implement next) and thus change our store’s state.

Therefore, last piece of our puzzle, create frontendapp/src/reducer/reducer.js :

We first created an initalState and then we defined for each action.type , what will happen to our state (compare actions/auth.js).

Finally, if you now use the credentials you used when you created your superuser (Django/Django-REST-Framework Part2) and hit login , you should see your token inside your redux-store.

Successfully fetched auth_token and stored in redux store

Conclusion

Ok we did it and used all technologies of our stack, which we need for development. I picked this functionality because from my perspective it shows how High-Order-Components like Redux’s connect help to seperate concerns. We can use our login action in every other component by connecting it, hence our components become smaller and can focus on displaying content.

We finish with the following structure in our frontendapp/src :

.
├── actions
│ └── auth.js
├── components
│ └── login.jsx
├── reducer
│ └── reducer.js
├── index.jsx

In the next part, we will extend our project with Docker and friends in order to deploy in on AWS’s Elastic Container Service.

--

--