Webpack & NGINX configuration for React app with set path prefix

Viewed 40

I'm working on a React app and I have it working when I deploy it as a Docker container, in a Rancher cluster, to what I'll call a "normal" endpoint. Meaning if I set up the endpoint to be test.site.com, everything works fine. The problem is my company is insisting on using path to direct traffic to different services. For example, test.site.com/my-site will direct traffic to my React app, but test.site.com/other-site directs traffic to another service. I'm having an issue where when I deploy my site to test.site.com/my-site, my app can't seem to resolve some of its assets. Opening the console in the browser gives errors such as:

GET https://test.site.com/cesium/Cesium.js net::ERR_ABORTED 405 
GET https://test.site.com/cesium/Widgets/widgets.css net::ERR_ABORTED 404
GET https://test.site.com/bundle.js net::ERR_ABORTED 404

(Cesium is a library I'm using in my app https://cesium.com/blog/2018/03/05/integrating-cesium-and-react/)

I've only recently started working with webpack, so I think there's probably some configuration there to fix this? Here's the relevant config files.

webpack.config.js

const path = require('path')
const HtmlWebPackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const HtmlPlugin = require('html-webpack-plugin')
const HtmlTagsPlugin = require('html-webpack-tags-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const dotenv = require('dotenv')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/',
  },
  resolve: {
    modules: [path.join(__dirname, 'src'), 'node_modules'],
    alias: {
      react: path.join(__dirname, 'node_modules', 'react'),
    },
    extensions: ['.jsx', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
        ],
      },
      {
        test: /\.(png|svg|jpe?g|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
    ],
  },
  devServer: {
    historyApiFallback: {
      index: '/',
    },
  },
  externals: {
    cesium: 'Cesium',
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
    }),
    new webpack.DefinePlugin({
      'process.env': JSON.stringify(dotenv.config().parsed), // it will automatically pick up key values from .env file
    }),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'node_modules/cesium/Build/Cesium',
          to: 'cesium',
        },
      ],
    }),
    new HtmlPlugin({
      template: './src/index.html',
    }),
    new HtmlTagsPlugin({
      append: false,
      tags: ['cesium/Widgets/widgets.css', 'cesium/Cesium.js'],
    }),
    new webpack.DefinePlugin({
      CESIUM_BASE_URL: JSON.stringify('/cesium'),
    }),
  ],
}

Dockerfile

FROM node:14-slim AS builder
ENV NODE_ENV production
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build

FROM nginx:1.21.0-alpine as production
ENV NODE_ENV production
COPY --from=builder /app/build /usr/share/nginx/html
RUN echo $(ls -1 /usr/share/nginx/html)
RUN chown nginx:nginx -R /usr/share/nginx
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN echo $(ls -1 /etc/nginx/conf.d/)

EXPOSE 80

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

nginx.conf

server {

  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri /index.html;
  }

  error_page   500 502 503 504  /50x.html;

  location = /50x.html {
    root   /usr/share/nginx/html;
  }

}
0 Answers
Related