构建应用后,React路由无法正常工作

时间:2020-07-07 16:10:52

标签: reactjs nginx webpack react-router-dom craco

我正在准备要发布的React应用,但是react-router-dom无法正常工作。确实,当我转到主页时,我被重定向到登录页面,登录页面之后和登录后被重定向到主页。但是,没有显示基于React Router的主页

Dockerfile


# build environment
FROM node:11.13.0-alpine as build


WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH

RUN apk --no-cache add curl

COPY package.json ./
COPY yarn.lock ./

# Add the two entries below
RUN mkdir -p node_modules/node-sass/vendor/linux_musl-x64-79
RUN curl -L https://github.com/sass/node-sass/releases/download/v4.14.1/linux_musl-x64-79.node -o node_modules/node-sass/vendor/linux_musl-x64-79/binding.node

RUN yarn

RUN npm rebuild node-sass

COPY . /app
RUN yarn build

# production environment
FROM nginx:stable-alpine


COPY ./docker/etc/conf.d/ /etc/nginx/
COPY ./docker/etc/nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/build /usr/share/nginx/html

nginx.conf


user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    #sendfile          on;
    #tcp_nopush        on;
    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;
}

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

server {
    listen       80;
    server_name  localhost;
    server_name  simplenlg.localhost;

    gzip on;
    charset utf-8;
    access_log  /var/log/nginx/host.access.log  main;

    location /static {
      root          /usr/share/nginx/html;
      gzip_static   always;
      expires       max;
      try_files $uri $uri/;
    }

    location ~* \.jss {
      root          /usr/share/nginx/html;
      gzip_static   on;
      expires       max;
      try_files     $uri.gz $uri;

      sendfile      on;
      types {}      default_type "application/javascript";
      add_header    Content-Encoding          gzip;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
        expires -1; # Set it to different value depending on your standard requirements
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }


    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

/etc/nginx/conf.d/gzip.conf

gzip on;
gzip_static on;
gzip_http_version  1.0;
gzip_comp_level    5; # 1-9
# gzip_min_length    256;
gzip_proxied       any;
gzip_vary          on;

# MIME-types
gzip_types
  application/atom+xml
  application/javascript
  application/json
  application/rss+xml
  application/vnd.ms-fontobject
  application/x-font-ttf
  application/x-web-app-manifest+json
  application/xhtml+xml
  application/xml
  font/opentype
  image/svg+xml
  image/x-icon
  text/css
  text/javascript
  text/plain
  text/x-component;


App.tsx

import React, { useEffect } from 'react';
import { HashRouter as Router, Switch, Link, Route, Redirect } from 'react-router-dom';
import { connect, ConnectedProps } from "react-redux";

import {Col, Layout, Menu, Row, Space} from 'antd';
import ErrorBoundary from "antd/lib/alert/ErrorBoundary";
import { LogoutOutlined } from "@ant-design/icons/lib";

import Login from '@pages/Login/Login';
import { logout, loadUserProfile } from "@shared/api/auth/auth";


import { routes, RouteWithSubRoutes } from './Routes';
import './App.less';


const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated,
  username: state.auth.user?.username,
  first_name: state.auth.user?.first_name,
  last_name: state.auth.user?.last_name,
});
const mapDispatchToProps = dispatch => {
  return {
    logout: () => {
      return dispatch(logout());
    },
    loadUserProfile: () => {
      return dispatch(loadUserProfile());
    },
  }
};

const connector = connect(mapStateToProps, mapDispatchToProps);
// The inferred type will look like:
type HomeProps = ConnectedProps<typeof connector>


export const Home: React.FC<HomeProps> = (props) => {
  // TODO Load user information after component being mounted, and redirect the user to the login page if necessary
  useEffect(() => {
    // const timer = setTimeout(() => {
    //   props.loadUserProfile();
    // }, 1000);
    // return () => clearTimeout(timer);
    props.loadUserProfile();
  });

  return (
    <div className="main">
      <Layout className='layout'>
        <Layout.Header>
          <Row>
            <Col flex="41%">
              <Menu theme='dark' mode='horizontal'>
                {routes.filter((route) => route.name).map((route, i) => {
                  return <Menu.Item key={i}><Link to={route.path}>{route.name}</Link></Menu.Item>
                })}
              </Menu>
            </Col>

            <Col flex={.01}>
              <Space>
                <span style={{ color: "white", fontSize: "18px" }}>Hi {props.username}</span>
                <LogoutOutlined
                    onClick={ () => props.logout()}
                    style={{ color: "white", fontSize: "15px" }}
                />
              </Space>
            </Col>
          </Row>
        </Layout.Header>

        <Layout.Content style={{ padding: '0 50px' }}>
          <div className='site-layout-content'>
            <Switch>
              { !props.isAuthenticated ? <Redirect to='/login' /> : (
                  routes.map((route, i) => (
                    <RouteWithSubRoutes key={i} {...route} />
                  ))
              )}
            </Switch>
          </div>
        </Layout.Content>
      </Layout>
    </div>
  );
};

const Main = connector(Home);

function App() {
  return (
    <Router basename="/">
      <ErrorBoundary>
        <Switch>
          <Route path='/login' component={Login} />
          <Route path='/' component={Main} />
        </Switch>
      </ErrorBoundary>
    </Router>
  );
}

export default App;

craco.config.js

const path = require('path');


const CracoLessPlugin = require('craco-less');
const sassResourcesLoader = require('craco-sass-resources-loader');
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const WebpackBar = require("webpackbar");

var webpack = require('webpack');
var CompressionPlugin = require('compression-webpack-plugin');
var DuplicatePackageCheckerPlugin = require("duplicate-package-checker-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');


module.exports = {
  webpack: {
    optimization: {
      minimizer: [
        // we specify a custom UglifyJsPlugin here to get source maps in production
        new UglifyJsPlugin({
          cache: true,
          parallel: true,
          uglifyOptions: {
            compress: false,
            ecma: 6,
            mangle: true
          },
          sourceMap: true
        })
      ]
    },
    plugins: [
      new WebpackBar({ profile: true }),
      ...(process.env.NODE_ENV === "development"
        ? [new BundleAnalyzerPlugin({ openAnalyzer: true })]
        : []),
        new webpack.DefinePlugin({ //<--key to reduce React's size
        'process.env': {
          'NODE_ENV': JSON.stringify('production')
        }
      }),
      new DuplicatePackageCheckerPlugin(),
      new webpack.optimize.AggressiveMergingPlugin(),
      new CompressionPlugin({
        filename: "[path].gz[query]",
        algorithm: "gzip",
        test: /\.js$|\.css$|\.html$/,
        threshold: 10240,
        minRatio: 0.8
      })
    ],
  },
  plugins: [
    {
      plugin: CracoAlias,
      options: {
        source: 'tsconfig',
        baseUrl: "./src",
        tsConfigPath: './tsconfig.paths.json'
      }
    },
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          modifyVars: { '@primary-color': '#1DA57A' },
          javascriptEnabled: true,
        },
      },
    },
  ],
};

package.json

{
  "name": "editor",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@ant-design/icons": "^4.1.0",
    "@reduxjs/toolkit": "^1.3.6",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@types/jest": "^24.0.0",
    "@types/node": "^12.0.0",
    "@types/react": "^16.9.0",
    "@types/react-dom": "^16.9.0",
    "antd": "^4.2.4",
    "cerialize": "^0.1.18",
    "enzyme": "^3.11.0",
    "enzyme-adapter-react-16": "^1.15.2",
    "lodash": "^4.17.15",
    "prop-types": "^15.7.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-redux": "7.1.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.1",
    "react-splitter-layout": "^4.0.0",
    "redux-thunk": "^2.3.0",
    "typescript": "~3.7.2"
  },
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test"
  },
  "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"
    ]
  },
  "devDependencies": {
    "@craco/craco": "^5.6.4",
    "@types/lodash": "^4.14.155",
    "@types/react-router": "^5.1.7",
    "@types/react-router-dom": "^5.1.5",
    "compression-webpack-plugin": "^4.0.0",
    "craco-alias": "^2.1.1",
    "craco-antd": "^1.18.0",
    "craco-less": "^1.16.0",
    "craco-sass-resources-loader": "^1.1.0",
    "duplicate-package-checker-webpack-plugin": "^3.0.0",
    "node-sass": "^4.14.1",
    "redux-mock-store": "^1.5.4",
    "serve": "^11.3.2",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "webpack-bundle-analyzer": "^3.8.0",
    "webpackbar": "^4.0.0"
  }
}

我注意到的一件奇怪的事情是,当我在firefox上打开网站时,最大的javascript文件被截断了,请参阅附有截图的屏幕截图。enter image description here

任何想法可能是什么问题?

0 个答案:

没有答案