Skip to content

Commit

Permalink
Merge pull request #48 from zth/preloading
Browse files Browse the repository at this point in the history
Preloading
  • Loading branch information
zth committed Jun 27, 2022
2 parents c8c0f27 + 51d24fa commit b5c312f
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 93 deletions.
13 changes: 7 additions & 6 deletions RescriptRelayVitePlugin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,13 @@ export let rescriptRelayVitePlugin = ({
let loc = await findGeneratedModule(moduleName);

if (loc != null) {
// This transforms the found loc to a URL relative to the project
// root. That's also what vite uses internally as URL for src
// assets.
let locRelativeToProjectRoot = loc.replace(config.root, "");
didReplace = true;
// TODO: Source maps
return `__$rescriptChunkName__: "${loc}"`;
return `__$rescriptChunkName__: "${locRelativeToProjectRoot}"`;
}
}
}
Expand All @@ -203,11 +207,8 @@ export let rescriptRelayVitePlugin = ({
generateBundle(_, bundle) {
for (let file in bundle) {
let chunk = bundle[file];
if (chunk.type === "chunk" && chunk.facadeModuleId != null) {
let moduleName = path.basename(chunk.facadeModuleId).split(".")[0];
if (moduleName != null) {
manifest[moduleName] = chunk.fileName;
}
if (chunk.type === "chunk" && chunk.isDynamicEntry) {
manifest[chunk.name] = chunk.fileName;
}
}

Expand Down
2 changes: 2 additions & 0 deletions cli/RescriptRelayRouterCli__Codegen.res
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@ ${route.queryParams
{
path: "${route.path->RoutePath.getPathSegment}",
name: "${route.name->RouteName.getFullRouteName}",
chunk: "${route.name->RouteName.getRouteRendererName}",
loadRouteRenderer,
preloadCode: (
. ~environment: RescriptRelay.Environment.t,
Expand Down
4 changes: 3 additions & 1 deletion cli/RescriptRelayRouterCli__Types.res
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module RouteName: {
let getRouteName: t => string
let getFullRouteName: t => string
let getFullRouteAccessPath: t => string
let getRouteRendererName: t => string
let getRouteRendererFileName: t => string
let toGeneratedRouteModuleName: t => string
let getLoc: t => range
Expand All @@ -54,7 +55,8 @@ module RouteName: {
let getFullRouteName = t => t.routeNamePath->Belt.List.toArray->Js.Array2.joinWith("__")
let getFullRouteAccessPath = t =>
t.routeNamePath->Belt.List.toArray->Js.Array2.joinWith(".") ++ ".Route"
let getRouteRendererFileName = t => t->getFullRouteName ++ "_route_renderer.res"
let getRouteRendererName = t => t->getFullRouteName ++ "_route_renderer"
let getRouteRendererFileName = t => t->getRouteRendererName ++ ".res"
let toGeneratedRouteModuleName = t => "Route__" ++ t->getFullRouteName ++ "_route"
let getLoc = t => t.loc
}
Expand Down
47 changes: 0 additions & 47 deletions lookup.mjs

This file was deleted.

25 changes: 14 additions & 11 deletions router/RelayRouter.res
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ module Router = {
@val
external origin: string = "window.location.origin"

let make = (~routes, ~routerEnvironment as history, ~environment) => {
let make = (~routes, ~routerEnvironment as history, ~environment, ~preloadAsset=?, ()) => {
// This holds a map of all assets we've preloaded, so we can track that we
// don't try to preload the same thing multiple times.
let preparedAssetsMap = Js.Dict.empty()
Expand All @@ -93,6 +93,18 @@ module Router = {
let initialQueryParams = QueryParams.parse(location.search)
let initialMatches = matchLocation(location)->Belt.Option.getWithDefault([])

// Emit preload tags for initial matching route renderers.
//
// TODO: This and a bunch of other side effects should probably go
// elsewhere...
switch preloadAsset {
| None => ()
| Some(preloadAsset) =>
initialMatches->Belt.Array.forEach(({route}) => {
preloadAsset(#JsModule(route.name ++ "_route_renderer", route.chunk))
})
}

let preparedMatches =
initialMatches->prepareMatches(~environment, ~queryParams=initialQueryParams, ~location)

Expand Down Expand Up @@ -153,10 +165,7 @@ module Router = {
| None =>
preparedAssetsMap->Js.Dict.set(assetIdentifier, true)
switch (asset, priority) {
| (Component({eagerPreloadFn}), Default | Low) =>
// TODO: Re-enable this once we've cracked the Rollup plugin for it.
// PreloadAssets.preloadAssetViaLinkTag(asset)
eagerPreloadFn()
| (Component(_), Default | Low) => PreloadAssets.preloadAssetViaLinkTag(asset)
| (Component({eagerPreloadFn}), High) => eagerPreloadFn()
| _ => // Unimplemented
()
Expand Down Expand Up @@ -235,12 +244,6 @@ module Router = {
routerEventListeners.contents->Belt.Array.forEach(cb => cb(event))
},
},
() => {
initialMatches
->Belt.Array.map(({route}) => route.loadRouteRenderer())
->Js.Promise.all
->Js.Promise.then_(_ => Js.Promise.resolve(), _)
},
)
}
}
Expand Down
4 changes: 3 additions & 1 deletion router/RelayRouter.resi
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ module Router: {
~routes: array<Types.route>,
~routerEnvironment: RouterEnvironment.t,
~environment: RescriptRelay.Environment.t,
) => (Types.cleanupFn, Types.routerContext, Types.awaitAllRouteRenderers)
~preloadAsset: [#JsModule(string, string)] => unit=?,
unit,
) => (Types.cleanupFn, Types.routerContext)
}

module Provider: {
Expand Down
3 changes: 2 additions & 1 deletion router/RelayRouter__Types.res
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type preloadAsset =
@live
type rec route = {
path: string,
name: string,
@as("__$rescriptChunkName__") chunk: string,
loadRouteRenderer: unit => Js.Promise.t<unit>,
preloadCode: (
. ~environment: RescriptRelay.Environment.t,
Expand Down Expand Up @@ -51,7 +53,6 @@ type subFn = currentRouterEntry => unit
type unsubFn = unit => unit
type cleanupFn = unit => unit
type callback = unit => unit
type awaitAllRouteRenderers = unit => Js.Promise.t<unit>

type routerEvent =
| OnBeforeNavigation({currentLocation: RelayRouter__Bindings.History.location})
Expand Down
25 changes: 9 additions & 16 deletions server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { fileURLToPath } from "url";
import path from "path";
import fetch from "node-fetch";
import stream from "stream";
import { findGeneratedModule } from "./lookup.mjs";
import PreloadInsertingStream from "./PreloadInsertingStream.mjs";

global.fetch = fetch;
Expand Down Expand Up @@ -53,7 +52,6 @@ async function createServer() {
preloadInsertingStream.write(start);

preloadInsertingStream.on("finish", () => {

strm.end();
});

Expand Down Expand Up @@ -111,28 +109,23 @@ async function createServer() {
id
)}`
);
preloadInsertingStream.onQuery(id)
preloadInsertingStream.onQuery(id);
},
// Handle asset preloading. Ideally this should be handled in ReScript
// code instead, giving that handler the server manifest.
async (asset) => {
switch (asset.type) {
case "component": {
// TODO: In prod this should look up via SSR manifest
const rescriptModuleLoc = await findGeneratedModule(
asset.moduleName,
"module"
// TODO: This is for dev only. In prod this should look up via SSR
// manifest
let viteModule = await vite.moduleGraph.getModuleByUrl(
asset.chunk
);
let url = viteModule?.url ?? asset.chunk;

if (rescriptModuleLoc != null) {
const mod = vite.moduleGraph.getModuleById(rescriptModuleLoc);

if (mod != null) {
preloadInsertingStream.onAssetPreload(
`<script type="module" src="${mod.url}" async></script>`
);
}
}
preloadInsertingStream.onAssetPreload(
`<script type="module" src="${url}" async></script>`
);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/EntryClient.res
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ let boot = () => {
Js.log("[debug] Doing boot")

RelaySSRUtils.bootOnClient(~rootElementId="root", ~render=() => {
let (_, routerContext, _) = RelayRouter.Router.make(
let (_, routerContext) = RelayRouter.Router.make(
~routes,
~environment=RelayEnv.environment,
~routerEnvironment,
(),
)

<Main environment=RelayEnv.environment routerContext />
Expand Down
27 changes: 18 additions & 9 deletions src/EntryServer.res
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,34 @@ let getStream = (
~onQueryInitiated,
~onEmitPreloadAsset: (. {..}) => unit,
) => {
let preloadAsset = asset => {
switch asset {
| RelayRouter.Types.Component({chunk, moduleName}) =>
onEmitPreloadAsset(. {"type": "component", "chunk": chunk, "moduleName": moduleName})
| Image(_) => () // onEmitPreloadAsset(. {"type": "image", "url": url})
}
}

let environment = RelayEnv.makeServer(~onResponseReceived, ~onQueryInitiated)
let routerEnvironment = RelayRouter.RouterEnvironment.makeServerEnvironment(~initialUrl=url)

let routes = RouteDeclarations.make()

let (_cleanup, routerContext, _) = RelayRouter.Router.make(
let (_cleanup, routerContext) = RelayRouter.Router.make(
~routes,
~environment,
~routerEnvironment,
)
renderToPipeableStream(
<RelaySSRUtils.AssetRegisterer.Provider
value={asset => {
~preloadAsset={
asset =>
switch asset {
| RelayRouter.Types.Component({moduleName}) =>
onEmitPreloadAsset(. {"type": "component", "moduleName": moduleName})
| Image(_) => () // onEmitPreloadAsset(. {"type": "image", "url": url})
| #JsModule(moduleName, chunk) =>
onEmitPreloadAsset(. {"type": "component", "chunk": chunk, "moduleName": moduleName})
}
}}>
},
(),
)
renderToPipeableStream(
<RelaySSRUtils.AssetRegisterer.Provider value=preloadAsset>
<Main environment routerContext />
</RelaySSRUtils.AssetRegisterer.Provider>,
options,
Expand Down
6 changes: 6 additions & 0 deletions src/test/routes/__generated__/RouteDeclarations.res

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b5c312f

Please sign in to comment.