You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Express部署测试:非根路由返回404错误求助

问题:React + Express 部署后仅根路由可访问,其他路由返回404

我搭建了React与Express项目用于部署测试,但只有Express的根路由("/")能正常响应,其他所有路由都返回404错误。比如在React的Detail页面中,点击向/hello路由发送请求的按钮时,就会返回404错误。


React Home.tsx

export default function Home() {
  const [loading, setLoading] = useState(true);
  const [movies, setMovies] = useState<Movie[] | null>(null);
  useEffect(() => {
    getMovies();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const getMovies = async () => {
    const response: GetMoviesResponse = await axios.get(
      'https://flyio-server3001.fly.dev'
    );
    setMovies(response.data.movies);
    setLoading(false);
  };

  return (
    <div>
      <h1>안녕하세요~ 최근 영화를 소개합니다!</h1>
      <h5>이미지를 클릭 시 영화 상세 정보를 확인할 수 있습니다.</h5>
      <MovieList>
        {loading && <li>영화 리스트 로딩 중...</li>}
        {movies &&
          movies.map((movie) => (
            <li key={movie.id}>
              <Link
                to={
                  process.env.NODE_ENV === 'development'
                    ? `/movies/${movie.id}`
                    : process.env.PUBLIC_URL + `/movies/${movie.id}`
                }
                state={{ movie }}
              >
                <img src={movie.medium_cover_image} alt={movie.title} />
              </Link>
              <Title>{movie.title}</Title>
            </li>
          ))}
      </MovieList>
    </div>
  );
}

React Detail.tsx

export default function Detail() {
  const [loading, setLoading] = useState(true);
  const [movie, setMovie] = useState<Movie | null>(null);
  const { state } = useLocation();

  useEffect(() => {
    const movie: Movie = state.movie;
    setMovie(movie);
    setLoading(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const hello = async (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    const response = await axios.get('https://flyio-server3001.fly.dev/hello');
    console.log(response);
  };

  return (
    <div>
      <Link
        to={
          process.env.NODE_ENV === 'development'
            ? `/`
            : process.env.PUBLIC_URL + `/`
        }
      >{`<= 홈으로`}</Link>
      <button onClick={hello}>메시지 받기</button>
      {loading && <div>영화 상세 정보 로딩 중.....</div>}
      {movie && (
        <div>
          <img src={movie.medium_cover_image} alt={movie.title} />
          <h1>{movie.title}</h1>
          <h5>{movie.year}년 개봉</h5>
          <h5>상영 시간 : {movie.runtime}분</h5>
          <h5>줄거리 : </h5>
          <p>{movie.summary}</p>
        </div>
      )}
    </div>
  );
}

Node.js app.ts

import express from 'express';
import fetch from 'node-fetch';
import cors from 'cors';

const app = express();
const PORT = process.env.PORT || 3001;

app.use(cors());
app.use('/', require('./index'));

app.listen(PORT, () => `✅ ${PORT} port server connected success`);

Node.js index.ts

import express from 'express';

const indexRouter = express.Router();

indexRouter.get('/', async (req, res) => {
  const response = await (
    await fetch('https://yts.mx/api/v2/list_movies.json')
  ).json();
  return res.status(304).json({ movies: response.data.movies });
});

indexRouter.get('/hello', (req, res) => {
  return res.json({ message: 'Hello Fly.io Server !!!' });
});

module.exports = indexRouter;

解决方案

问题出在Express的路由导入导出语法不兼容:你在index.ts中用ES模块语法编写,但app.ts里用CommonJS的require导入,导致除根路由外的其他路由未被正确注册。

修复步骤:

  1. 修改index.ts的导出方式为ES模块:
// index.ts
import express from 'express';

const indexRouter = express.Router();

indexRouter.get('/', async (req, res) => {
  const response = await (
    await fetch('https://yts.mx/api/v2/list_movies.json')
  ).json();
  return res.status(304).json({ movies: response.data.movies });
});

indexRouter.get('/hello', (req, res) => {
  return res.json({ message: 'Hello Fly.io Server !!!' });
});

export default indexRouter; // 替换原module.exports
  1. 修改app.ts的导入方式为ES模块:
// app.ts
import express from 'express';
import fetch from 'node-fetch';
import cors from 'cors';
import indexRouter from './index'; // 替换原require导入

const app = express();
const PORT = process.env.PORT || 3001;

app.use(cors());
app.use('/', indexRouter);

app.listen(PORT, () => console.log(`✅ ${PORT} port server connected success`));
  1. 在项目的package.json中添加"type": "module",明确告诉Node.js使用ES模块:
{
  "type": "module"
}

修改完成后,Express就能正确注册所有路由,/hello等路由即可正常响应。

内容的提问来源于stack exchange,提问作者pickle23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:24:53