如果从头开始搭建React项目,create-react-app通常是开发者的首选。毕竟不是谁都有精力去了解WebPack的复杂配置,而CRA将配置隐藏开箱即用的特性必然会受到普遍欢迎。
根目录访问
到了部署阶段,我通常使用nginx作为web容器,将项目部署到一个根目录下访问。如
# nginx配置
server {
listen 80;
server_name my.website.com;
...
location / {
alias /data/www/react-project/dist;
index index.html
}
}
那么只要我们将项目文件放到对应的目录下,重启nginx即可开始访问web页面。
二级目录访问
有时我们有多个web项目,多个项目不可能同时挂在根目录下,所以我们会划分二级目录来分别访问各个web项目。如
- http://my.website.com/project1 => 访问react-project1项目
- http://my.website.com/project2 => 访问react-project2项目
问题1:CSS等资源加载失败
此时,如果简单将nginx配置的location改为/project1,则会出现网页无法访问的错误。
# nginx配置
server {
listen 80;
server_name my.website.com;
...
# location / {
location /project1 {
alias /data/www/react-project/dist;
index index.html
}
}
现象
从dev工具可以看出,html文件有取得,但css、js等资源引用失败。css和js的文件路径都是http://my.website.com/static/...(或css)。
分析
CRA(create-react-app)的项目配置默认是跑在根目录下的。如果查看dist目录下的html会发现,所有的css或js文件的引用路径都是/开头的绝对路径。
解决
将打包路径从绝对路径改为相对路径:
# package.json
{
...
"homepage": ".", // 添加homepage属性,将路径改为当前目录
...
}
重新编译后看到,所有的资源文件路径都改过来了。
问题2:加载成功,网页空白
重新上传到服务器,更新dist目录下的文件,重启nginx后访问网页。
现象
结果发现,网页仍然是空白一片。查看html的渲染结果,发现似乎js并没有执行。
分析
在react-router-dom的例子中,通常使用的是BrowserRouter。这种类型的Router在向服务器发送请求时,如果相对于二级目录的路由去指向对应的页面路由,就会找不到资源,因此也就不会渲染。
解决
BrowserRouter有一个属性叫做basename,就是用于解决此类问题。
...
import { Route, BrowserRouter as Router, Switch, Redirect } from 'react-router-dom';
...
...
<Router basename='/project1'>
<Switch>
<Redirect exact key='index' path='/' to='/home' />
{ routes }
</Switch>
</Router>
...
问题3:访问成功,刷新后404
修改以上配置并编译部署,重启nginx后可正常访问网页。但刷新后,网页变为一片空白。
现象
网页显示,在请求页面路由如http://my.website.com/project... 时,该路由的请求状态为404。
分析
还是因为BrowserRouter的问题,之前能正常访问时因为路由中设置了Redirect,所以能访问到根目录并自动跳转到/home。但直接访问则会访问失败。
解决
在nginx配置中加入try_files命令
location /project1 {
alias /data/www/react-project/dist;
# index index.html
try_files $uri /project1/index.html
}
这样,在请求$uri时如果找不到对应的资源,会fallback回去加载index.html。
问题解决。