My Docker+NestJS+Webpack development environment is not running as efficiently as I would like.
Current behavior
Using Webpack with Hot Module Replacement Plugin is slower than using Nest-CLI with watch:
nest build --webpack --webpackPath webpack-hmr.config.js --watch
is slower than nest start --debug --watch
.
It keeps rebuilding my source files; I'm assuming it keeps rebuilding the entire source, instead of hot module replacing; with a new project with a couple of files, it is much faster, and only replaces what is needed.
Input Code
Dockerfile:
# Get current Node Alpine Linux image.
FROM node:erbium-alpine AS base
# Install essential packages to prepare for bcrypt.
# https://github.com/kelektiv/node.bcrypt.js/wiki/Installation-Instructions#alpine-linux-based-images
RUN apk --no-cache add --virtual builds-deps builds-deps build-base gcc wget python
# Install is-docker to make sure the installations are only done within the container.
RUN yarn global add is-docker
# Set our node environment, either development or production;
# defaults to production, docker-compose overrides this to development on build and run.
ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV
# Expose port 3000 for node as default, unless otherwise stated.
ARG PORT=3000
ENV PORT $PORT
EXPOSE $PORT
# Install dependencies first, in a different location for easier app bind mounting for local development;
# we need to keep node_modules and its affiliated packages in
# due to default /opt permissions we have to create the dir with root and change perms
WORKDIR /home/node/
# Copy files to prepare for installation.
COPY --chown=node:node package.json yarn.lock tsconfig.json tsconfig.build.json nest-cli.json ./
FROM base AS debug
# Expose port 9229 for debugging.
EXPOSE 9229
# Install git for husky hooks.
RUN apk --no-cache add git
# The official node image provides an unprivileged user as a security best practice
# but we have to manually enable it. We put it here so npm installs dependencies as the same
# user who runs the app.
# https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md#non-root-user
USER node
# Continue copy files to prepare for installation.
COPY --chown=node:node ./webpack/webpack-hmr-debug.config.js .run-if-changedrc ./
ADD --chown=node:node .husky .husky/
ADD --chown=node:node .git .git/
# Install dependencies.
RUN yarn
# Copy source files last.
ADD --chown=node:node src src/
# Start debugging!
CMD [ "yarn", "debug" ]
docker-compose.yml:
version : "3.7"
services:
backend_debug:
build:
context: ..
target: debug
dockerfile: ./docker/Dockerfile
args:
- NODE_ENV=development
profiles:
- debug
stop_signal : SIGINT
container_name: project_backend_debug
restart : unless-stopped
ports :
- "3000:3000"
- "9229:9229"
environment:
- MONGO_URI
stdin_open : true # Keep stdin open regardless.
tty : true # Show output with syntax highlighting support.
command: ['ash']
volumes :
- "../webpack/webpack-hmr-debug.config.js:/home/node/webpack-hmr-debug.config.js"
- "../tsconfig.build.json:/home/node/tsconfig.build.json"
- "../.run-if-changedrc:/home/node/.run-if-changedrc"
- "../nest-cli.json:/home/node/nest-cli.json"
- "../tsconfig.json:/home/node/tsconfig.json"
- "../node_modules:/home/node/node_modules/"
- "../package.json:/home/node/package.json"
- "../yarn.lock:/home/node/yarn.lock"
- "../.husky/:/home/node/.husky/"
- "../.git/:/home/node/.git/"
- "../dist:/home/node/dist/"
- "../src/:/home/node/src/"
webpack-hmr.config.js
const
{ RunScriptWebpackPlugin } = require('run-script-webpack-plugin'),
nodeExternals = require('webpack-node-externals');
module.exports = function (options, webpack) {
return {
...options,
entry: ['webpack/hot/poll?100', options.entry],
devtool: 'inline-source-map',
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?100'],
}),
],
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin({
paths: [/\.js$/, /\.d\.ts$/],
}),
new RunScriptWebpackPlugin(
{
name: options.output.filename,
nodeArgs: ['--inspect=0.0.0.0:9229'] // Added to enable debugging.
}
),
]
};
};
Expected behavior
HMR should speed up development and show that HMR rebuilds by changing the specific files only.
Environment
Docker-Compose: 1.29.2 Webpack: 5.28.0 Docker: 20.10.8 Nest: 7.5.5
For Tooling issues:
- Node: 12.22.6
- Platform: MacOS Big Sur 11.5.2