Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add server + route middleware functionality #5343

Closed
wants to merge 9 commits into from

Conversation

brophdawg11
Copy link
Contributor

@brophdawg11 brophdawg11 commented Feb 1, 2023

Wire up Remix to new React Router middleware

Proposal: remix-run/react-router#9564
React Router PR: remix-run/react-router#9975

Note: CI will fail here until we can point to an experimental or prerelease version of the RR branch. They pass locally if you build the RR branch into the Remix node_modules directory.

@changeset-bot
Copy link

changeset-bot bot commented Feb 1, 2023

🦋 Changeset detected

Latest commit: 3b12c41

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
Name Type
@remix-run/dev Minor
@remix-run/express Minor
@remix-run/node Minor
@remix-run/server-runtime Minor
create-remix Minor
@remix-run/css-bundle Minor
@remix-run/serve Minor
@remix-run/architect Minor
@remix-run/netlify Minor
@remix-run/testing Minor
@remix-run/vercel Minor
@remix-run/cloudflare Minor
@remix-run/deno Minor
@remix-run/react Minor
@remix-run/cloudflare-pages Minor
@remix-run/cloudflare-workers Minor
remix Minor
@remix-run/eslint-config Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@@ -14,7 +14,8 @@
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"dependencies": {
"@remix-run/node": "1.12.0"
"@remix-run/node": "1.12.0",
"@remix-run/router": "1.3.1"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adapters will now include the router as a dependency so they can re-export MiddlewareContext/createMiddlewareContext alongside their own serverMiddleware concepts

next: express.NextFunction
) => {
let response: NodeResponse | undefined;
let context = createMiddlewareStore();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth noting that at the moment, since our context is keyed by object instances for strong-typing, users can run into cross-boundary CJS/ESM instance issues when using serverMiddleware. This is solveable by either (1) bundling your entire server via the remix.config.js server option, or (2) potentially using import maps in your application package.json (untested)

}

export interface MiddlewareFunction {
(args: DataFunctionArgsWithMiddleware): DataFunctionReturnValue;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's bikeshed these names a bit - should they be LoaderFunction_V2, etc.?

Comment on lines +97 to +100
if (
unstable_middleware !== true &&
build.entry.module.handleDataRequest
) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just like we will now ignore getLoadContext when you opt into middleware, we will also ignore handleDataRequest since you can operate on responses via the serverMiddleware. If folks need to decipher between document and data requests they should be able to do that via looking at response headers or the _data query param

Comment on lines +94 to +96
let request = createRemixRequest(req, res);
response = (await handleRequest(request)) as NodeResponse;
await sendRemixResponse(res, response);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you turn on unstable_middleware and don't provide a serverMiddleware we just call through directly without any concept of getLoadContext

Comment on lines +86 to +92
if (!response) {
// User never called next(), so doesn't need to do any post-processing
response = await callRemix();
}
if (!res.headersSent) {
await sendRemixResponse(res, response);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things going on here:

  • If the user never calls context.next() we automatically call the rest of the pipeline. You cannot short circuit by skipping the call. The only way to short circuit is to throw
  • If the user actually responds via the express Response in the middleware (and thus res.headersSent === true) then we skip sendRemixResponse(). This allows them to take full control if they want to.

"/parent-response",
"routes/parent-response"
);
expect(response.headers.get("x-count")).toBe("2");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are OK, but I think you could be more explicit than a number. What about something like this?

expect(response.headers.get("x-processed-by")).toBe("parent")
…
expect(response.headers.get("x-processed-by")).toBe("parent,child")
…
expect(response.headers.get("x-processed-by")).toBe("parent,child,grandchild")

That makes it clearer which middleware are being invoked for each request.

@brophdawg11
Copy link
Contributor Author

Closing temporarily - we'll be revisiting shortly after v2 releases

@MichaelDeBoey MichaelDeBoey deleted the brophdawg11/middleware branch May 6, 2023 21:40
@pspeter3
Copy link

pspeter3 commented Oct 6, 2023

Now that V2 is out, is there a place to track this work?

@brophdawg11
Copy link
Contributor Author

Yep! These are on the Roadmap as remix-run/react-router#12695 and #7645

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants