一、打包后 部署访问,报错404,找不到对应的main.js或main.css
- 参考stackoverflow上类似问题:
- 初次直接通过
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">