关于react 在打包后:“找不到资源路径”的问题、部署到服务器二级目录 “打开为空白” 的问题

一、打包后 部署访问,报错404,找不到对应的main.js或main.css

  • 参考stackoverflow上类似问题
    1. 初次直接通过 npm run build打包react webapp后将文件夹build(通常改名为对应项目名称)整个部署到服务器,浏览器通过www.xxx.com/build/访问时,报错如下:
      报错图

1.1 原因分析:

react打包后的项目默认是跑在服务器根目录的,当将打包后的项目放到次级目录下(如:myuser.github.io/myproject)时,自然就会提示404


注意create-react-app创建的项目中 public/index.html中注释所说:

<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
  Notice the use of %PUBLIC_URL% in the tags above.
  It will be replaced with the URL of the `public` folder during the build.
  Only files inside the `public` folder can be referenced from the HTML.

-->
  • 以上注释说明:%PUBLIC_URL%在项目build时,会自动替换为一个正确的绝对路径指向public,只有在public文件夹内的文件才能被
    正确引用到html中
  • 官方还提示:在js中可以通过 process.env.PUBLIC_URL 来同样引用到public目录

我所使用的create-react-app脚手架默认的 打包后的 文件会将域名作为项目的根目录,如:
- http://www.xxxx.com 根路由就是’/’


但实际情况是,我们在部署时通常将各个项目以文件夹作为区分如:

  • 项目a所在服务器目录是: www.xxx.com/projectA 根路由是 /projectA
  • 项目b所在服务器目录是: www.xxx.com/projectB 根路由是/projectB
1.2 问题解决:

package.json中,设置homepage

"homepage":"."
  • 以上设置会将 index.html中的%PUBLIC_URL%替换为 .,从而拼接为:./main.123456.js这样的一个相对index.html的资源路径

二、react使用的browserHistory模式项目,部署到服务器上的子目录中,访问时页面空白,没有报错

  • segmentDefault上同类问题
    原因:我们使用react-router-dom里的BrowserRouter as Router时,是用浏览器history对象的方法去请求服务器,如果服务器没有相对于的路由去指向对应的页面路由会找不到资源。
    解决: 两种方案:要么改用HashRouter,要么让运维对nginx.conf进行新的配置(其他代理服务器同理)
2.1 使用HashRouter解决

从react-router-dom升级到v4后,官方文档中推荐使用的是BrowserRouter(常见URL格式com/home/xxx),但是此方式需要服务器配合,且重定向只能到首页,无法停留在当前页。


**BrowserRouter**:使用于现代浏览器,支持H5 history API,但使用它还需要和服务器部署联系,修改对应的服务器配置 **HashRouter**:常用于旧款浏览器(兼容性更好),格式如`come/index.html#/home`
import {HashRouter as Router,Route} from 'react-router-dom';

<Router >
    <div>
         <Header />
         <Route path="/" component={Container}></Route>
     </div>
 </Router>

2.2 仍使用BrowserRouter,但配合服务端改配置

以nginx为例:
假设部署到 www.test.com域名下,项目文件目录:/mnt/h5/reactApp,reactApp就是npm run build生成的build文件夹

server {
    listen 80;
    server_name  test.com;
    root /mnt/h5/reactApp;
    index index.html;
    location ~ ^/favicon\.ico$ {
        root /mnt/h5/reactApp;
    }

    location / {
        try_files $uri $uri/ @fallback;
        index index.html;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto  $scheme;
    }
    location @fallback {
        rewrite ^.*$ /index.html break;
    }
    access_log  /mnt/logs/nginx/access.log  main;
}
  • 备注:react-router有一个basename:string属性,用于为所有位置添加一个基准URL。使用场景:假如你需要把页面部署到服务器的二级目录,你可以使用 basename 设置到此目录。
<BrowserRouter basename="/calendar"/>
<Link to="/today"/> // 将渲染为 <a href="/calendar/today">

猜你喜欢

转载自blog.csdn.net/Sophie_U/article/details/80006723