Open LoeiFy opened 7 years ago
SPA 项目基本上都会用到路由 router。react 还有 vue 对应有其路由插件。 react-router 还有 vue-router 都有 hashHistory 和 browserHistory 模式。这里大概说一下两者区别
router
大多数情况下,browserHistory 模式明显是优于 hashHistory 模式的,但 browserHistory 需要一定的配置
可以看出,hashHistory 不需要什么配置,但 browserHistory 需要服务端支持,这里简单说一下两种方式做支持,其它方式基本上都是类似
const app = express() app.get('*', function (request, response){ response.sendFile(path.resolve(__dirname, 'index.html')) })
server { ... location / { try_files $uri /index.html } }
这里说明一下为什么要这样设置,browserHistory 模式下,URL 是指向真实 URL 的资源路径,当通过真实 URL 访问网站的时候(首页),这个时候可以正常加载我们的网站资源,而用户在非首页下手动刷新网页时,由于路径是指向服务器的真实路径,但该路径下并没有相关资源,用户访问的资源不存在,返回给用户的是 404 错误
通过上面所说的原理,简单起来说就是 browserHistory 模式下,需要每个路由下都要有对应的资源存在,就不会产生 404 错误,所以如果不借助服务端的话,又要实现这种模式,这种场景在自己不能配置服务器时候会碰到,例如把项目部署到 GitHub pages 上。那该怎么办呢
GitHub pages
那么就产生 对应资源
所以,我们的做法就是在每个 路由路径 下,都放置一个跟首页一样的 index.html
index.html
下面是做法,当然也是有各种方式的,都是可以类推的
假定我们有以下的路由设定,这里以 react-router 为例子
export default ( <Route path="/" component={App}> <IndexRoute component={HomePage} /> <Route path="contact-us" component={ContactPage} /> <Route path="dashboard"> <IndexRoute component={Verify(Dashboard)} /> <Route path="inbox" component={Verify(Inbox)} /> <Route path="conversation" component={Verify(ComposeMessage)} /> </Route> <Route path="*" component={NotFound} /> </Route> )
那么就可以路由路径为
// routes.js const routes = [ 'contact-us', 'dashboard', 'dashborad/inbox', 'dashboard/conversation' ] module.exports = routes
接下来我们就把生成的 index.html 复制到这几个路径下就可以了
// deploy.js const fs = require('fs-extra') const routes = require('routes.js') const path = require('path') routes.forEach((route) => { fs.copySync('index.html', path.join(route, 'index.html')) })
这样用户访问就不会出现 404 了,SPA 的功能也不受影响,为了方便我们可以把这个生成工具集成到 package.json
package.json
{ "script": { "build": "NODE_ENV=production webpack --progress && node deploy.js" } }
ok, 当我们运行 npm run build 时候,就会同时生成对应路径下的 index.html,这样就可以了完成我们所需要的功能了
npm run build
看到这里,应该会有一个疑问,如果 routes 中有一些是不能穷举的路径要怎么办?例如 <Route path="posts/:id" component={Verify(Inbox)} />。这时候是没办法生成对应资源的
<Route path="posts/:id" component={Verify(Inbox)} />
不过还是可以使用以下 hack 方式:
直接使用服务端 404 页面了,如果是用 GitHub pages 的话,我们可以直接生成一个 404.html 即可,直接把 404 页面弄成跟 index 内容一样,404 时候就是正常的内容页面,这时候页面功能是正常的,并且不需要前面的一堆做法了。
404.html
这篇文章很有帮助,感谢。 我想解决这个问题一段时间了,之前是用这个方法解决的:spa-github-pages。 但是楼主这个创建路由路径的方式是比上述的方法和404.html都要优的,因为这样就不会返回404的状态码,有利于seo。 这个issue里有很多人在讨论这个问题,但是似乎都没有人提出这个好方法。
SPA 项目基本上都会用到路由
router
。react 还有 vue 对应有其路由插件。 react-router 还有 vue-router 都有 hashHistory 和 browserHistory 模式。这里大概说一下两者区别大多数情况下,browserHistory 模式明显是优于 hashHistory 模式的,但 browserHistory 需要一定的配置
配置 browserHistory
可以看出,hashHistory 不需要什么配置,但 browserHistory 需要服务端支持,这里简单说一下两种方式做支持,其它方式基本上都是类似
使用 express
使用 nginx
这里说明一下为什么要这样设置,browserHistory 模式下,URL 是指向真实 URL 的资源路径,当通过真实 URL 访问网站的时候(首页),这个时候可以正常加载我们的网站资源,而用户在非首页下手动刷新网页时,由于路径是指向服务器的真实路径,但该路径下并没有相关资源,用户访问的资源不存在,返回给用户的是 404 错误
通过上面所说的原理,简单起来说就是 browserHistory 模式下,需要每个路由下都要有对应的资源存在,就不会产生 404 错误,所以如果不借助服务端的话,又要实现这种模式,这种场景在自己不能配置服务器时候会碰到,例如把项目部署到
GitHub pages
上。那该怎么办呢所以,我们的做法就是在每个 路由路径 下,都放置一个跟首页一样的
index.html
下面是做法,当然也是有各种方式的,都是可以类推的
假定我们有以下的路由设定,这里以 react-router 为例子
那么就可以路由路径为
接下来我们就把生成的
index.html
复制到这几个路径下就可以了这样用户访问就不会出现 404 了,SPA 的功能也不受影响,为了方便我们可以把这个生成工具集成到
package.json
ok, 当我们运行
npm run build
时候,就会同时生成对应路径下的index.html
,这样就可以了完成我们所需要的功能了问题 & 思考
看到这里,应该会有一个疑问,如果 routes 中有一些是不能穷举的路径要怎么办?例如
<Route path="posts/:id" component={Verify(Inbox)} />
。这时候是没办法生成对应资源的不过还是可以使用以下 hack 方式:
直接使用服务端 404 页面了,如果是用
GitHub pages
的话,我们可以直接生成一个404.html
即可,直接把 404 页面弄成跟 index 内容一样,404 时候就是正常的内容页面,这时候页面功能是正常的,并且不需要前面的一堆做法了。