Search code examples
reactjsdeploymentvitegoogle-cloud-runcontinuous-deployment

React/Vite/Cloud Run : Failed to load module script (and/or fails to reach .js files) after each deployment


I am deploying a React App using Vite, and I have a Github Actions workflow to automatically deploy my app an serve it on Cloud Run after each push.

Every time I deploy a new version of the app, my app is obviously rebuilt and script chunks (index-XXX.js, with XXX a random number) are changing.

However, the browser usually still tries to reach out the old index-XXX.js if I previously visited my app.

As a result (I believe), I obtain two types of errors:

  • either a "Expected a Javascript module script but the server responded with a MIME type of "text/html"" error
  • either it tries to reach out to previous index-XXX.js but it fails to do so (because they do not exist anymore).

In both cases, a hard refresh (F5/Cmd+R) is enough to load the app correctly. Then the app works without any problem, until the next deployment.

vite.config.ts :

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return id
              .toString()
              .split('node_modules/')[1]
              .split('/')[0]
              .toString();
          }
        },
      },
    },
  },
  plugins: [react(), svgr()],
  server: {
    proxy: {
      '/api/': {
        target: 'http://localhost:8000',
        changeOrigin: true,
      },
      '/socket.io/': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        secure: false,
        ws: true,
      },
    },
  },
  resolve: {
    alias: {
      '@': '/src',
    },
  },
});

github action :

name: Deploy dev moove front platform to Google Cloud Run

on:
  push:
    branches: [dev]

env:
  PROJECT_ID: ${{ secrets.GCLOUD_PROJECT_ID }}
  REPO_NAME: moove-front-dev
  ENV: ${{ secrets.CLOUD_DEV_ENV }}

jobs:
  deploy:
    name: Deploy
    permissions:
      contents: 'read'
      id-token: 'write'
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - id: 'auth'
        name: 'Authenticate with Google Cloud'
        uses: 'google-github-actions/auth@v1'
        with:
          workload_identity_provider: 'projects/391421406778/locations/global/workloadIdentityPools/moove-identity-pool/providers/github-provider'
          service_account: '[email protected]'

      - name: Set up Cloud SDK
        run: gcloud auth configure-docker

      - name: Create env
        run: |-
          echo "${{ env.ENV }}" > .env

      - name: Build and tag the docker image
        run: |-
          docker build . --tag gcr.io/$PROJECT_ID/$REPO_NAME:$GITHUB_SHA

      - name: Push the image to the Google Container Registry
        run: |-
          docker push gcr.io/$PROJECT_ID/$REPO_NAME:$GITHUB_SHA

      - id: 'deploy'
        name: 'Deploy'
        uses: 'google-github-actions/deploy-cloudrun@v0'
        with:
          service: 'moove-front-dev'
          image: gcr.io/${{ env.PROJECT_ID }}/${{ env.REPO_NAME }}:${{ github.sha }}
          region: 'europe-west1'
          flags: '--port=80'

Dockerfile :

# BUILD
FROM node:19.5 as build

WORKDIR /front

COPY package*.json ./

RUN npm ci

COPY . .
COPY .env .env

RUN npm run build

# PRODUCTION
FROM nginx:stable-alpine AS production

COPY --from=build /front/dist /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Solution

  • The browser is caching your index.html file, which is the entrypoint to the rest of your application, hence it will have stale entries to previously deployed versions of the application.

    There are multiple ways to tackle this, one of which since you are using nginx is to inform the browser to not cache index.html.