This post will go through how to add hot module reloading to Next.js running a docker environment. This is critical to development for your Next.js application because you want the app to reload your webpage as you change files in application’s folder. When we are finished, any changes that you make to your React codebase will automatically be reloaded and you should see the changes show up in your development environment within 1 second of the change.
Video of what we are doing:
Step 1: Create a Dockerfile for your Next.js application.
We’ve previously built a Dockerfile
for our Next.js application in a previous blog post, but if you are trying to dockerize your application for the first time, you need to create a Dockerfile
.
FROM node:10.16.0
RUN mkdir /app
WORKDIR /app
COPY package*.json ./
RUN npm install
CMD [ "npm", "run", "dev" ]
The idea here is to start with a base ubuntu image and copy the package.json
and package-lock.json
files into the directory and running an npm install
command.
Step 2: Add a volume mount between your host and docker environment.
We are using docker-compose to create a volume mount between the /app
directory and our actual working directory on our native operating system (/frontend
). The service block for this application looks like this- where frontend is the directory that our Next.js application lives in.
frontend:
container_name: frontend
ports:
- '3000:3000'
build:
context: frontend
dockerfile: Dockerfile
volumes:
- ./frontend:/app
- /app/node_modules
- /app/.next
Step 3: Add docker volumes for your node_modules and .next folders.
As we allude to in Step 2, we also need to add docker volumes for the node_modules
and .next
folders so that docker will use the docker folders instead of the host OS folders.
Step 4: Modify our webpack middleware for our Next.js app.
In the frontend/next.config.js
file, we need to give the webpack middleware, instructions for when to reload itself. If your app does not have a next.config.js file, you can simply add the following code:
module.exports = {
webpackDevMiddleware: config => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
}
return config
},
}
For our previous project, we don’t need to create an entire new object to export, we can instead just add the webpackDevMiddleware
block to our already existing configuration object:
const withCSS = require('@zeit/next-css')
module.exports = withCSS({
target: 'serverless',
env: {
BACKEND_URL: process.env.BACKEND_URL,
},
webpackDevMiddleware: config => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
}
return config
},
})
That should be it- you should now see that as you update your react components from within Next.js, that they instantly show up as changed in your web browser without having to run a docker-compose down
followed by docker-compose up
.