Skip to content

Commit

Permalink
WIP - Cloudflare bindings in dev mode
Browse files Browse the repository at this point in the history
  • Loading branch information
petebacondarwin committed Nov 24, 2023
1 parent 8c42697 commit adb4e86
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 14 deletions.
11 changes: 11 additions & 0 deletions packages/remix-dev/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { pathToFileURL } from "node:url";
import fse from "fs-extra";
import PackageJson from "@npmcli/package-json";
import type { NodePolyfillsOptions as EsbuildPluginsNodeModulesPolyfillOptions } from "esbuild-plugins-node-modules-polyfill";
import type { AppLoadContext } from "@remix-run/server-runtime";

import type { RouteManifest, DefineRoutesFunction } from "./config/routes";
import { defineRoutes } from "./config/routes";
Expand Down Expand Up @@ -187,6 +188,13 @@ export interface AppConfig {
? // Partial<FutureConfig> doesn't work when it's empty so just prevent any keys
{ [key: string]: never }
: Partial<FutureConfig>;

/**
* The load context to use in dev mode is provided to the request handler.
*
* Adapters could set this to be used at dev time.
*/
devLoadContext?: AppLoadContext;
}

/**
Expand Down Expand Up @@ -353,6 +361,8 @@ export interface RemixConfig {
tsconfigPath: string | undefined;

future: FutureConfig;

devLoadContext?: AppLoadContext;
}

/**
Expand Down Expand Up @@ -652,6 +662,7 @@ export async function resolveConfig(
watchPaths,
tsconfigPath,
future,
devLoadContext: appConfig.devLoadContext,
};
}

Expand Down
14 changes: 10 additions & 4 deletions packages/remix-dev/vite/node/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { splitCookiesString } from "set-cookie-parser";
import { Readable } from "stream";
import { File, FormData, Headers, Request as BaseNodeRequest } from "undici";
import { type ServerBuild, installGlobals } from "@remix-run/node";
import { createRequestHandler as createBaseRequestHandler } from "@remix-run/server-runtime";
import {
type AppLoadContext,
createRequestHandler as createBaseRequestHandler,
} from "@remix-run/server-runtime";

installGlobals();

Expand Down Expand Up @@ -202,12 +205,15 @@ export let createRequestHandler = (
}: {
mode?: string;
criticalCss?: string;
}
},
devLoadContext?: AppLoadContext
) => {
let handler = createBaseRequestHandler(build, mode);
let handler = createBaseRequestHandler(build, mode, devLoadContext);
return async (req: IncomingMessage, res: ServerResponse) => {
let request = createRequest(req);
let response = await handler(request, {}, { __criticalCss: criticalCss });
let response = await handler(request, {
__criticalCss: criticalCss,
});
handleNodeResponse(response, res);
};
};
17 changes: 13 additions & 4 deletions packages/remix-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const supportedRemixConfigKeys = [
"routes",
"serverBuildPath",
"serverModuleFormat",
"devLoadContext",
] as const satisfies ReadonlyArray<keyof RemixUserConfig>;
type SupportedRemixConfigKey = typeof supportedRemixConfigKeys[number];
type SupportedRemixConfig = Pick<RemixUserConfig, SupportedRemixConfigKey>;
Expand Down Expand Up @@ -83,6 +84,7 @@ type ResolvedRemixVitePluginConfig = Pick<
| "routes"
| "serverBuildPath"
| "serverModuleFormat"
| "devLoadContext"
>;

let serverEntryId = VirtualModule.id("server-entry");
Expand Down Expand Up @@ -297,6 +299,7 @@ export const remixVitePlugin: RemixVitePlugin = (options = {}) => {
serverBuildPath,
serverModuleFormat,
relativeAssetsBuildDirectory,
devLoadContext,
} = await resolveConfig(config, { rootDirectory });

return {
Expand All @@ -313,6 +316,7 @@ export const remixVitePlugin: RemixVitePlugin = (options = {}) => {
future: {
v3_fetcherPersist: options.future?.v3_fetcherPersist === true,
},
devLoadContext,
};
};

Expand Down Expand Up @@ -757,15 +761,20 @@ export const remixVitePlugin: RemixVitePlugin = (options = {}) => {
if (!vite.config.server.middlewareMode) {
vite.middlewares.use(async (req, res, next) => {
try {
let pluginConfig = await resolvePluginConfig();
let locals = localsByRequest.get(req);
invariant(locals, "No Remix locals found for request");

let { build, criticalCss } = locals;

let handle = createRequestHandler(build, {
mode: "development",
criticalCss,
});
let handle = createRequestHandler(
build,
{
mode: "development",
criticalCss,
},
pluginConfig.devLoadContext
);

await handle(req, res);
} catch (error) {
Expand Down
14 changes: 8 additions & 6 deletions packages/remix-server-runtime/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,19 @@ import { createServerHandoffString } from "./serverHandoff";

export type RequestHandler = (
request: Request,
loadContext?: AppLoadContext,
args?: {
/**
* @private This is an internal API intended for use by the Remix Vite plugin in dev mode
*/
__criticalCss?: string;
}
},
loadContext?: AppLoadContext
) => Promise<Response>;

export type CreateRequestHandlerFunction = (
build: ServerBuild | (() => Promise<ServerBuild>),
mode?: string
mode?: string,
devLoadContext?: AppLoadContext
) => RequestHandler;

function derive(build: ServerBuild, mode?: string) {
Expand Down Expand Up @@ -72,7 +73,8 @@ function derive(build: ServerBuild, mode?: string) {

export const createRequestHandler: CreateRequestHandlerFunction = (
build,
mode
mode,
devLoadContext = {}
) => {
let _build: ServerBuild;
let routes: ServerRoute[];
Expand All @@ -82,8 +84,8 @@ export const createRequestHandler: CreateRequestHandlerFunction = (

return async function requestHandler(
request,
loadContext = {},
{ __criticalCss: criticalCss } = {}
{ __criticalCss: criticalCss } = {},
loadContext = devLoadContext
) {
_build = typeof build === "function" ? await build() : build;
if (typeof build === "function") {
Expand Down
6 changes: 6 additions & 0 deletions templates/cloudflare-pages/remix.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ export default {
// appDirectory: "app",
// assetsBuildDirectory: "public/build",
// publicPath: "/build/",
defaultLoadContext: {
// Example Cloudflare binding that could be made available to Remix
env: {
SOME_ENV: "some value",
},
},
};

0 comments on commit adb4e86

Please sign in to comment.