базовое имя и домашняя страница не работают должным образом для обслуживания /static/ файлов в разработке

Не уверен, что это проблема Kubernetes, ingress-nginx или ReactJS (create-react-app)...

Структура проекта

new-app/
  client/
    src/
      App.js
      index.js
      Test.js
    package.json
  k8s/
    client.yaml
    ingress.yaml
  server/
  skaffold.yaml

Проблема

  • Внешний интерфейс ReactJS должен работать на 192.168.64.5/client, когда кластер развернут с помощью Skaffold.
  • Перейдите к 192.168.64.5/client и пустому экрану
  • Консоль разработчика показывает:

введите здесь описание изображения введите здесь описание изображения

По сути, он пытается обслуживать статические файлы из /static, но мне нужно, чтобы они поступали из /client/static.

Предлагаемые решения

Предполагая, что это проблема ReactJS, решения были следующими:

Ни один из них не работает в моем случае. По-прежнему отображаются объекты, которые пытаются обслуживать из /static вместо /client/static.

Код приложения ReactJS

// App.js

import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import './App.css';

import Test from './Test';

const App = () => {
  return (
    <BrowserRouter
      basename='/client'>
        <>
          <Route exact path='/' component={Test} />
        </>
    </BrowserRouter>

  );
}

export default App;
// Test.js

import React, { useState, useEffect } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';

const Test = () => {

  const [data, setData] = useState('');

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios('/api/auth/test/');
      setData(result.data);
    };
    fetchData();
  }, []);

  return (
    <div className='App'>
    <header className='App-header'>
      <img src={logo} className='App-logo' alt='logo' />
      <p>
        Edit <code>src/App.js</code> and save to reload!
      </p>
      <p>
        {data}
      </p>
      <a
        className='App-link'
        href='https://reactjs.org'
        target='_blank'
        rel='noopener noreferrer'
      >
        Learn React
      </a>
    </header>
    </div>    
  )

};

export default Test;
{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "homepage": "/client",
  "dependencies": {
    "axios": "^0.19.0",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.2.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Манифесты Kubernetes/Skaffold и Docker

# Dockerfile.dev

FROM node:alpine
EXPOSE 3000
WORKDIR '/app'
COPY ./client/package.json ./
RUN npm install
COPY ./client .
CMD ["npm", "run", "start"]
# ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/add-base-url: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /client/?(.*)
            backend:
              serviceName: client-cluster-ip-service
              servicePort: 3000
# client.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: client-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      component: client
  template:
    metadata:
      labels:
        component: client
    spec:
      containers:
        - name: client
          image: clientappcontainers.azurecr.io/client
          ports:
            - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: client-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: client
  ports:
    - port: 3000
      targetPort: 3000
# skaffold.yaml

apiVersion: skaffold/v1beta15
kind: Config
build:
  local:
    push: false
  artifacts:
    - image: clientappcontainers.azurecr.io/client
      docker:
        dockerfile: ./client/Dockerfile.dev
      sync:
        manual:
          - src: "***/*.js"
            dest: .
          - src: "***/*.html"
            dest: .
          - src: "***/*.css"
            dest: .
deploy:
  kubectl:
    manifests:
      - manifests/ingress.yaml 
      - manifests/client.yaml

Так что я делаю неправильно здесь?

ИЗМЕНИТЬ:

Я должен отметить, что при этом все работает нормально:

- path: /?(.*)
  backend:
    serviceName: client-cluster-ip-service
    servicePort: 3000

Репо для демонстрации проблемы:

https://github.com/eox-dev/subdir-issue


person cjones    schedule 19.12.2019    source источник


Ответы (3)


По-видимому, в настоящее время это невозможно в CRA в среде разработки:

https://github.com/facebook/create-react-app/issues/8222#issuecomment-568308139

person cjones    schedule 23.12.2019

Create React App предполагает, что ваше приложение размещено в корневом каталоге обслуживающего веб-сервера или в подпути, как указано в package.json (домашняя страница). Обычно приложение Create React игнорирует имя хоста. Вы можете использовать эту переменную, чтобы принудительно ссылаться на активы дословно по предоставленному вами URL-адресу (включая имя хоста). Это может быть особенно полезно при использовании CDN для размещения вашего приложения.

Есть три способа решить эту проблему:

  1. Добавьте свое базовое имя в вывод webpack -> publicPath (если вы отклонили свой проект create-react-app и у вас уже есть доступ к файлу конфигурации webpack)
  2. Добавьте PUBLIC_URL="/client" в файл .env.production.
  3. Добавьте свойство homepage в файл package.json следующим образом:
{
  ...
  homepage: "/client"
  ...
}

Ссылка:

https://create-react-app.dev/docs/advanced-configuration/
person Ali Torki    schedule 19.12.2019
comment
Я использую create-react-app, поэтому у меня нет доступа к webpack.config.js, если я не npm eject. - person cjones; 19.12.2019
comment
Я обновил свой ответ и написал вам, как вы можете решить эту проблему. - person Ali Torki; 19.12.2019
comment
Хорошо, я выполнил эти шаги вместе с несколькими другими вещами и все еще получаю тот же результат: активы поступают от /static вместо /client/static. - person cjones; 20.12.2019
comment
Какой из них вы реализовали? другое решение — добавить PUBLIC_URL=/client в файл .env вместо .env.production, потому что эта переменная env используется только в рабочем режиме, тогда как .env или .env.production должны работать так, как хотелось бы. - person Ali Torki; 20.12.2019
comment
Я пробовал 2) и 3). Я также пробовал PUBLIC_URL="/client" в .env и то же самое. На данный момент я просто пробую npm start и пропускаю все skaffold и Kubernetes. - person cjones; 20.12.2019

В настоящее время, чтобы иметь другую домашнюю страницу в производственной среде с CRA (или craco), вам необходимо установить

# .env.production
PUBLIC_URL="/client" 

внутри файла .env.production (или .env.development, если корневой путь отличается в dev), а затем вы меняете базовое имя маршрутизатора:

<BrowserRouter basename={process.env.PUBLIC_URL}>
  ...
</BrowserRouter>
person disgra    schedule 31.05.2021