Paulund

Reduce Nuxt Build Size

Recently I've created a NuxtJS application that will run in SSR mode, this is deployed to Cloud Run on GCP via a docker image.

In order to allow the autoscaling to work quicker and to allow quicker start ups I wanted to reduce the docker size of the application to as small as possible.

When you're first starting with NuxtJS they recommend a dockerfile you can use for your application, but it isn't optimized work size.

Below is the typical dockerfile for Nuxt applications.

FROM node:16

WORKDIR /usr/src/app

COPY . ./
RUN yarn

EXPOSE 8080

ENV HOST=0.0.0.0
ENV PORT=8080

RUN yarn build

CMD [ "yarn", "start" ]

On a standard application, this will create an image size around 500MB.

What can we do to reduce the docker image size?

Dependencies

The node module folder is one of the largest folders in the application. This is because the dockerfile above will install all the dependencies needed for both development and production.

But if you're deploying the application from this dockerfile you don't need development dependencies such as jest.

Use the --production option in the yarn install command.

yarn install --production

This will install all packages in the dependencies property and ignore all in devDependencies within your package.json.

Nuxt Build Standalone

When you run nuxt build it will create the client and server files the applications needs to run the application.

These are stored in the .nuxt/dist folder, but the server.js file will still depend on files stored in the node_modules folders.

Therefore you will need to install all the dependencies rather than just the dependencies needs to run the Nuxt application.

There is an option on the build command called Standalone. This will move the dependencies used from node_modules into the .nuxt/dist/server.js file, so we don't need the node_modules anymore.

If after the build is successful you get errors about modules missing from node_modules folder then you might have modules loaded in your nuxt.config.js modules property. For standalone to work correctly you need to move these over to buildModules.

Nuxt Start

The only package you would need to run nuxt is nuxt package itself, but you don't need the entire nuxt package you can use nuxt start to run your application.

There's a separate package that you can use which is optimized for running SSR bundles.

yarn add nuxt-start

Final Dockerfile

FROM node:16 as builder

WORKDIR /usr/src/builder

ADD . ./

RUN yarn install --production
RUN yarn build --standalone

FROM node:16-alpine as starter

WORKDIR /usr/src/app

RUN yarn add "[email protected]"

COPY --from=builder /usr/src/builder/.nuxt /usr/src/app/.nuxt
COPY --from=builder /usr/src/builder/nuxt.config.js /usr/src/app/
COPY --from=builder /usr/src/builder/static /usr/src/app/

ENV HOST=0.0.0.0
ENV PORT=8080

ENTRYPOINT ["npx", "nuxt-start"]
EXPOSE 8080