webpack解决使用window.open方法打开history路由页面提示404的问题

时间:2024-10-26 07:17:24

问题:

一般情况下应该使用history.push('/ssh')打开history路由页面

但项目中使用window.open('/ssh'),然后使用new WebSocket进行通信

开发环境下启动项目后,/ssh页面打开却显示cannot get /ssh,控制台提示404

排查问题:

在React开发环境中使用 window.open 打开路由页面时,如果出现404错误,通常是由于以下几个原因导致的:

  • 开发服务器配置问题:默认情况下,webpack-dev-server 只能处理根路径的请求。如果你尝试打开一个路由页面,而该路径没有对应的静态文件,就会返回404错误。
  • HTML5 History API:如果你使用了HTML5 History API(例如 react-router-dom 的 BrowserRouter),浏览器会尝试直接请求该路径,而不是通过React应用的入口点。

1.路由是否有:

App.tsx文件

import React from 'react';
import {Switch, Route} from 'react-router-dom';
import Login from './pages/login';
import WebSSH from './pages/ssh';
import Layout from './layout';

const App = () => {
  return (
    <Switch>
        <Route path="/" exact component={Login} />
        <Route path="/ssh" exact component={WebSSH} />
        <Route component={Layout} />
      </Switch>
  )
}

export default App;

答案是有

2.使用的是history路由还是hash路由

index.tsx文件

import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router-dom';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/es/locale/zh_CN';
import './index.less';
import App from './App';
import moment from 'moment';
import 'moment/locale/zh-cn';
import * as serviceWorker from './serviceWorker';
import { history, updatePermissions } from 'libs';

moment.locale('zh-cn');
updatePermissions();

ReactDOM.render(
  <Router history={history}>
    <ConfigProvider locale={zhCN} getPopupContainer={() => document.fullscreenElement || document.body}>
      <App/>
    </ConfigProvider>
  </Router>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

答案是history路由

解决方案:

1.在devServer对象中设置historyApiFallback: true

webpack开发环境配置示例:

const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { publicPath } = require('./paths.js')

module.exports = smart(webpackCommonConf, {
    mode: 'development',
    devtool: 'eval-source-map', // 快速生成源映射,适合开发环境
    module: {
        rules: [
            {
                test: /\.(png|jpg|jpeg|gif|svg)$/,
                use: 'file-loader'
            },
            {
                test: /\.module\.css$/,
                use: [
                    'style-loader',
                    {
                        loader: "css-loader",
                        options: {
                            modules: true,
                        },
                    },
                    // 'postcss-loader'
                ],
            },
            {
                test: /\.css$/,
                // loader 的执行顺序是:从后往前
                use: ['style-loader', 'css-loader'],
                exclude: /\.module\.css$/,
            },
            {
                test: /\.module\.less$/,
                // 增加 'less-loader' ,注意顺序
                use: [
                    'style-loader',
                    {
                        loader: "css-loader",
                        options: {
                            modules: true,
                        },
                    },
                    {
                        loader: 'less-loader',
                        options: {
                            javascriptEnabled: true
                        }
                    }
                ],
            },
            {
                test: /\.less$/,
                // 增加 'less-loader' ,注意顺序
                use: ['style-loader', 'css-loader', {
                    loader: 'less-loader',
                    options: {
                        javascriptEnabled: true
                    }
                }],
                exclude: /\.module\.less$/,
            },
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            // 'development'
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
            }
        })
    ],
    devServer: {
        host: '0.0.0.0',
        port: 8112,
        hot: true,
        // 输出 source-map 方便直接调试 ES6 源码
        sockHost: process.env.WDS_SOCKET_HOST, // WebSocket 主机地址
        sockPort: process.env.WDS_SOCKET_PORT, // WebSocket 端口号
        // sockHost: '127.0.0.1', // WebSocket 主机地址
        // sockPort: '9002', // WebSocket 端口号
        progress: true,  // 显示打包的进度条
        contentBase: publicPath,  // 根目录
        open: true,  // 自动打开浏览器
        compress: true,  // 启动 gzip 压缩
        historyApiFallback: true, // 是否开发 HTML5 History API 网页
        profile: true, // 是否捕捉 Webpack 构建的性能信息,用于分析什么原因导致构建性能不佳
        // 设置代理
        proxy: {
            // 将本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': {
                target: 'http://127.0.0.1:8000',
                changeOrigin: true,
                ws: true,
                headers: {'X-Real-IP': '1.1.1.1'},
                pathRewrite: {
                  '^/api': ''
                }
            },
        }
    }
})

2.使用window.location.href='路由路径'代替window.open

缺点:

  • 可能项目中有多处需要修改,比较麻烦
  • 可能业务就是需要window.open的新开一个tab页的效果,所以window.location.href不符合要求

总结:

所以修改webpack开发环境配置比较好,修改地方少,好控制