feat: create new middleware mode "on-request"#15686
Conversation
🦋 Changeset detectedLatest commit: 505f298 The changes in this PR will be included in the next version bump. This PR includes changesets to release 396 packages
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 |
Merging this PR will degrade performance by 23.7%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing |
|
This is for sure not done yet, but the changes in the core and node lib seem to be functional in the example project. Therefore I wanted to check in what you think of the direction I'm taking, before I start streamlining/cleaning things up, writing docs, etc. |
|
Hello! We require new features to be accepted through our RFC process in https://github.com/withastro/roadmap/ first, so I’m closing this until the discussions there are concluded. |
|
For this it's not necessary, and I already spoke with @leekeh about this feature and it was ok to land it. It's an enhancement of something we already have, so an RFC isn't needed |
|
Sorry about that, I didn't have that context. Thanks for reopening @ematipico and thanks for the work @leekeh! |
Thanks and no worries! I will try to put some more effort into this one soon also 🙏 Initial feedback is already welcome :) |
# Conflicts: # packages/astro/src/core/pages/handler.ts
- Make ResolvedRenderOptions.getStaticAsset optional and drop the now-redundant getStaticAsset: undefined from test literals - Remove vestigial process.env.PRERENDER from node prerender tests (never read) - Clarify #renderStaticAsset status logic (200 treated as unset)
"always" and "on-request""on-request"
| fixture = await loadFixture({ | ||
| root: './fixtures/middleware-static/', | ||
| output: 'server', | ||
| outDir: './dist/middleware-static', | ||
| adapter: testAdapter({ | ||
| extendAdapter: { | ||
| adapterFeatures: { | ||
| buildOutput: 'server', | ||
| middlewareMode: 'on-request', | ||
| }, | ||
| }, | ||
| }), | ||
| }); | ||
| await fixture.build(); | ||
| app = await fixture.loadTestAdapterApp(); |
There was a problem hiding this comment.
I don't think we need a fixture. We have middleware-app.test.ts, which simulates a full-fledge app. Since middleware is purely routing, and we don't need any build artefact, we can unit test things
| * @param {string} pathname - The current request pathname (base-stripped). | ||
| * @returns {Promise<Response | undefined>} A prerendered response, or undefined if not found. | ||
| */ | ||
| getStaticAsset?: (route: RouteData, pathname: string) => Promise<Response | undefined>; |
There was a problem hiding this comment.
This is a new feature, so it needs a changeset. Also, why would the function return undefined? Worth mentioning it in the docs. I would also expand the type and return | undefined
| /** | ||
| * Whether this pipeline runs during `astro build` static generation | ||
| * (i.e. real prerendering). `false` for dev and request-time pipelines. | ||
| * Overridden to `true` by `BuildPipeline`. Used to decide whether | ||
| * `on-request` middleware should be skipped (skipped at build, run at | ||
| * request time). | ||
| */ | ||
| readonly isBuildTime: boolean = false; |
There was a problem hiding this comment.
We already have a isDev function. We should mimic that instead.
| body, | ||
| logger: self.logger, | ||
| isPrerendered: matchedRoute.routeData.prerender, | ||
| isPrerendered: matchedRoute.routeData.prerender && !middlewareHandlesPrerendered, |
There was a problem hiding this comment.
Isn't there another way to add this check? We're polluting isPrerendered with a value that doesn't belong to it
| const response = await readPageFromDisk( | ||
| client, | ||
| getStaticAssetPath('/500', { | ||
| base: app.manifest.base, | ||
| buildFormat: app.manifest.buildFormat, | ||
| }), | ||
| ); |
There was a problem hiding this comment.
This code seems to have lost functionality. Before, we were checking two files
const filePaths = [`${status}.html`, `${status}/index.html`];Now this functionality seems to be lost or ... I don't know, somewhere I can't see?
Implement the work needed to make middleware run properly on request of static pages. Prerendered pages are stored and read from the disk, but the middleware will run first, if the user has turned on one of these new middleware modes.
Changes
on-requestmiddleware modeContext
Currently, middleware runs on static pages during build, and on dynamic pages after build. There is the need to customize this behavior, specifically to run middleware on static pages, for example to add an authentication check.
A first step was to refactor the code a bit to create the
middlewareModeadapter feature in #15495This PR implements the
on-requestandalwaysmiddleware modes."classic"(default)"always""on-request""edge"edgeMiddlewareconfig option.Related discussions:
Testing
Test cases were added on the core lib, expanding the app middleware tests and adding a static middleware test.
Tests were added for node, adding onto the prerendering fixture.
Docs
Docs added/updated :) For now in draft, want to see what you guys think of the implementation first.
withastro/docs#14117
/cc @withastro/maintainers-docs for feedback!