Use relative paths for router links (#672)
Summary: As the next step for #643, this patch enables the app to be rendered at non-root gateways by incorporating the relative-path history implementation developed in #666. The app is not fully functional: our React components do not yet know how to resolve assets, and so fetches of resources like the repository will be against the wrong URLs. Test Plan: - Note that `yarn start` still works. - Run `./scripts/build_static_site.sh` to build the site into, say, `/tmp/gateway`. - Run a static web server from `/tmp/gateway/` and note that (a) the paths listed in the page source are relative, and (b) everything works as intended, with no console messages in either Chrome or Firefox. - Run a static web server from `/tmp/` and navigate to `/gateway/` in the browser. Note that the app loads properly, and that refreshes work (i.e., the `pushState` paths are real paths). Note that the repository registry cannot yet be loaded, and so PageRank cannot be run. wchargin-branch: relative-router
This commit is contained in:
parent
91f0459753
commit
ce2867a8d5
|
@ -1,16 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Router, browserHistory} from "react-router";
|
import {Router} from "react-router";
|
||||||
|
import type {History /* actually `any` */} from "history";
|
||||||
|
|
||||||
import {createRoutes} from "./createRoutes";
|
import {createRoutes} from "./createRoutes";
|
||||||
import {resolveTitleFromPath} from "./routeData";
|
import {resolveTitleFromPath} from "./routeData";
|
||||||
|
|
||||||
export default class App extends React.Component<{}> {
|
export default class App extends React.Component<{|+history: History|}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Router
|
<Router
|
||||||
history={browserHistory}
|
history={this.props.history}
|
||||||
routes={createRoutes()}
|
routes={createRoutes()}
|
||||||
onUpdate={function() {
|
onUpdate={function() {
|
||||||
const router = this;
|
const router = this;
|
||||||
|
|
|
@ -1,14 +1,31 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import "./index.css";
|
import createBrowserHistory from "history/lib/createBrowserHistory";
|
||||||
|
|
||||||
|
import createRelativeHistory from "./createRelativeHistory";
|
||||||
|
import normalize from "../util/pathNormalize";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
|
||||||
const root = document.getElementById("root");
|
import "./index.css";
|
||||||
if (root == null) {
|
|
||||||
|
const target = document.getElementById("root");
|
||||||
|
if (target == null) {
|
||||||
throw new Error("Unable to find root element!");
|
throw new Error("Unable to find root element!");
|
||||||
}
|
}
|
||||||
ReactDOM.hydrate(<App />, root);
|
|
||||||
|
let initialRoot: string = target.dataset.initialRoot;
|
||||||
|
if (initialRoot == null) {
|
||||||
|
console.error(
|
||||||
|
`Initial root unset (${initialRoot}): this should not happen! ` +
|
||||||
|
'Falling back to ".".'
|
||||||
|
);
|
||||||
|
initialRoot = ".";
|
||||||
|
}
|
||||||
|
const basename = normalize(`${window.location.pathname}/${initialRoot}/`);
|
||||||
|
const history = createRelativeHistory(createBrowserHistory(), basename);
|
||||||
|
|
||||||
|
ReactDOM.hydrate(<App history={history} />, target);
|
||||||
|
|
||||||
// In Chrome, relative favicon URLs are recomputed at every pushState,
|
// In Chrome, relative favicon URLs are recomputed at every pushState,
|
||||||
// although other assets (like the `src` of an `img`) are not. We don't
|
// although other assets (like the `src` of an `img`) are not. We don't
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import {StyleSheetServer} from "aphrodite/no-important";
|
import {StyleSheetServer} from "aphrodite/no-important";
|
||||||
|
import createMemoryHistory from "history/lib/createMemoryHistory";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOMServer from "react-dom/server";
|
import ReactDOMServer from "react-dom/server";
|
||||||
import {match, RouterContext} from "react-router";
|
import {match, RouterContext} from "react-router";
|
||||||
|
|
||||||
import Page from "./Page";
|
import Page from "./Page";
|
||||||
import {Assets, rootFromPath} from "./assets";
|
import {Assets, rootFromPath} from "./assets";
|
||||||
|
import createRelativeHistory from "./createRelativeHistory";
|
||||||
import ExternalRedirect from "./ExternalRedirect";
|
import ExternalRedirect from "./ExternalRedirect";
|
||||||
import {createRoutes} from "./createRoutes";
|
import {createRoutes} from "./createRoutes";
|
||||||
import {resolveRouteFromPath, resolveTitleFromPath} from "./routeData";
|
import {resolveRouteFromPath, resolveTitleFromPath} from "./routeData";
|
||||||
|
@ -19,6 +21,7 @@ export default function render(
|
||||||
const path = locals.path;
|
const path = locals.path;
|
||||||
const root = rootFromPath(path);
|
const root = rootFromPath(path);
|
||||||
const assets = new Assets(root);
|
const assets = new Assets(root);
|
||||||
|
const history = createRelativeHistory(createMemoryHistory(path), "/");
|
||||||
{
|
{
|
||||||
const route = resolveRouteFromPath(path);
|
const route = resolveRouteFromPath(path);
|
||||||
if (route && route.contents.type === "EXTERNAL_REDIRECT") {
|
if (route && route.contents.type === "EXTERNAL_REDIRECT") {
|
||||||
|
@ -31,7 +34,7 @@ export default function render(
|
||||||
function renderStandardRoute() {
|
function renderStandardRoute() {
|
||||||
const bundlePath = locals.assets["main"];
|
const bundlePath = locals.assets["main"];
|
||||||
const routes = createRoutes();
|
const routes = createRoutes();
|
||||||
match({routes, location: path}, (error, redirectLocation, renderProps) => {
|
match({history, routes}, (error, redirectLocation, renderProps) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if (renderProps) {
|
} else if (renderProps) {
|
||||||
|
@ -53,7 +56,7 @@ export default function render(
|
||||||
<style data-aphrodite>${css.content}</style>
|
<style data-aphrodite>${css.content}</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="overflow-y:scroll">
|
<body style="overflow-y:scroll">
|
||||||
<div id="root">${html}</div>
|
<div id="root" data-initial-root="${root}">${html}</div>
|
||||||
<script src="${assets.resolve(bundlePath)}"></script>
|
<script src="${assets.resolve(bundlePath)}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue