Use relative paths for lexically static assets (#671)
Summary: This is the first observable step toward #643. Assets whose paths are known as literals at server-side rendering time are now referenced via relative paths. This means that the favicon and JavaScript bundle can be loaded from an arbitrary gateway. The actual bundle code will still only work when loaded from `/`. This commit stands alone so that the enclosing change to the Webpack config can be in as small a change as possible. 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 favicon and JavaScript are correctly noted, but that the router raises an error because it is trying to load a non-existent route. (This behavior is unchanged.) wchargin-branch: relative-lexically-static
This commit is contained in:
parent
094582be32
commit
91f0459753
|
@ -18,17 +18,10 @@ const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
|
|||
const paths = require("./paths");
|
||||
const getClientEnvironment = require("./env");
|
||||
|
||||
// Webpack uses `publicPath` to determine where the app is being served from.
|
||||
// It requires a trailing slash, or the file assets will get an incorrect path.
|
||||
const publicPath = paths.servedPath;
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||
// `publicUrl` is just like `publicPath`, but we will provide it to our app
|
||||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
|
||||
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
|
||||
const publicUrl = publicPath.slice(0, -1);
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(publicUrl);
|
||||
const env = getClientEnvironment(/* publicUrl: */ "");
|
||||
|
||||
function makeConfig(mode /*: "production" | "development" */) {
|
||||
return {
|
||||
|
@ -71,8 +64,6 @@ function makeConfig(mode /*: "production" | "development" */) {
|
|||
// We don't currently advertise code splitting but Webpack supports it.
|
||||
filename: "static/js/[name].[chunkhash:8].js",
|
||||
chunkFilename: "static/js/[name].[chunkhash:8].chunk.js",
|
||||
// We inferred the "public path" (such as / or /my-project) from homepage.
|
||||
publicPath: publicPath,
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: (
|
||||
info /*:
|
||||
|
|
|
@ -9,3 +9,13 @@ if (root == null) {
|
|||
throw new Error("Unable to find root element!");
|
||||
}
|
||||
ReactDOM.hydrate(<App />, root);
|
||||
|
||||
// In Chrome, relative favicon URLs are recomputed at every pushState,
|
||||
// although other assets (like the `src` of an `img`) are not. We don't
|
||||
// want to have to keep the shortcut icon's path up to date as we
|
||||
// transition; it's simpler to make it absolute at page load.
|
||||
for (const el of document.querySelectorAll('link[rel="shortcut icon"]')) {
|
||||
const link: HTMLLinkElement = (el: any);
|
||||
// (Appearances aside, this is not a no-op.)
|
||||
link.href = link.href;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import ReactDOMServer from "react-dom/server";
|
|||
import {match, RouterContext} from "react-router";
|
||||
|
||||
import Page from "./Page";
|
||||
import {Assets, rootFromPath} from "./assets";
|
||||
import ExternalRedirect from "./ExternalRedirect";
|
||||
import {createRoutes} from "./createRoutes";
|
||||
import {resolveRouteFromPath, resolveTitleFromPath} from "./routeData";
|
||||
|
@ -16,6 +17,8 @@ export default function render(
|
|||
callback: (error: ?mixed, result?: string) => void
|
||||
): void {
|
||||
const path = locals.path;
|
||||
const root = rootFromPath(path);
|
||||
const assets = new Assets(root);
|
||||
{
|
||||
const route = resolveRouteFromPath(path);
|
||||
if (route && route.contents.type === "EXTERNAL_REDIRECT") {
|
||||
|
@ -42,7 +45,7 @@ export default function render(
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="shortcut icon" href="/favicon.png" />
|
||||
<link rel="shortcut icon" href="${assets.resolve("/favicon.png")}" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet">
|
||||
<title>${resolveTitleFromPath(path)}</title>
|
||||
|
@ -51,7 +54,7 @@ export default function render(
|
|||
</head>
|
||||
<body style="overflow-y:scroll">
|
||||
<div id="root">${html}</div>
|
||||
<script src="${bundlePath}"></script>
|
||||
<script src="${assets.resolve(bundlePath)}"></script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
@ -80,7 +83,7 @@ export default function render(
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta http-equiv="refresh" content="0;url=${redirectTo}" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="shortcut icon" href="${assets.resolve("favicon.png")}" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet">
|
||||
<title>${resolveTitleFromPath(path)}</title>
|
||||
|
|
Loading…
Reference in New Issue