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

refactor: singular middleware #9776

Merged
merged 4 commits into from
Jan 25, 2024

Conversation

lilnasy
Copy link
Contributor

@lilnasy lilnasy commented Jan 23, 2024

Changes

  • The onRequest function is internally re-exported from each page and endpoint, and loaded after the request matches a particular one.
  • The middleware is singular in astro and the current arrangement prevents enhancement that require the middleware to be independent.
  • This PR moves onRequest from page chunks to the manifest, where it can be loaded sooner than route data.

Testing

Does not affect behavior. Existing tests should pass.

Docs

Does not affect usage.

Copy link

changeset-bot bot commented Jan 23, 2024

🦋 Changeset detected

Latest commit: 59b97de

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

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

@github-actions github-actions bot added the pkg: astro Related to the core `astro` package (scope) label Jan 23, 2024
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

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

Here's some feedback:

  • let's revert the changes around i18n, they are intentional, and they aren't part of the middleware work
  • I don't like that we create a middleware by default because this will always create a middleware.mjs file, which is weird is a user doesn't use a middleware at all. The fact that onRequest can be undefined was a good compromise
  • I have some concerns on how this change affects edge middleware

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need a changeset if the code is just a refactor and it doesn't change/fix anything for the users

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went back and forth on this. We can't say ever say for sure, there won't be regression and the changelog comes in handy. At the end, it's just another entry in the changelog.

@@ -263,7 +248,7 @@ function buildManifest(
clientDirectives: Array.from(settings.clientDirectives),
entryModules,
assets: staticFiles.map(prefixAssetPath),
i18n: i18nManifest,
i18n: settings.config.i18n,
Copy link
Member

Choose a reason for hiding this comment

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

Let's revert this change. It's intentional to pass only a subset of information in the SSR manifest.

Comment on lines -77 to -84
// The middleware should not be imported by the pages
if (shouldBundleMiddleware(opts.settings)) {
const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID);
if (middlewareModule) {
imports.push(`import { onRequest } from "${middlewareModule.id}";`);
exports.push(`export { onRequest };`);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Why was this logic removed? A middleware shouldn't be part of an Astro route/page when we are in the edge

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 middleware is now never part of an Astro route/page

Copy link
Contributor

Choose a reason for hiding this comment

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

Curious why too. Related to edge?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To detach middleware from routes. We had to import a route before importing middleware. Now, middleware lives in the manifest instead.

The snippet here serves the purpose of excluding middleware when it is supposed to go into edge middleware. That purpose is served by this line now.

https://github.com/withastro/astro/pull/9776/files#diff-524e25c0bd5feda71ed7489963414a0c1f06da3caa327933574a72b85b668bddR245

packages/astro/src/core/middleware/vite-plugin.ts Outdated Show resolved Hide resolved
@@ -139,6 +129,9 @@ export function createDevelopmentManifest(settings: AstroSettings): SSRManifest
? new URL(settings.config.base, settings.config.site).toString()
: settings.config.site,
componentMetadata: new Map(),
i18n: i18nManifest,
i18n: settings.config.i18n,
Copy link
Member

Choose a reason for hiding this comment

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

To revert

@lilnasy
Copy link
Contributor Author

lilnasy commented Jan 23, 2024

let's revert the changes around i18n

This is a stop-gap change. Soon enough, it will not even be in the manifest.

I don't like that we create a middleware by default

There is a good reason for it. Middleware is a no-op in this PR but will soon contain internal rendering logic that goes in the "middle".

As a bonus, we get to delete several nested if-else branches dealing with the undefined that are duplicated in multiple places.

I have some concerns on how this change affects edge middleware

Could you elaborate?

@ematipico
Copy link
Member

ematipico commented Jan 23, 2024

let's revert the changes around i18n

This is a stop-gap change. Soon enough, it will not even be in the manifest.

I want to revert these changes: i18n: settings.config.i18n,. This was intentional, I wanted to store in the manifest only information that are needed by the astro/app. For example, i18n.fallback isn't needed, so we shouldn't store it.

I have some concerns on how this change affects edge middleware

Could you elaborate?

In the adapters, we create an edge middleware if edgeMiddleware is true and if middlewareEntryPoint exists. With this change, we now emit a middlewareEntryPoint because it always contains at least a no-op function. This means that now we always create an edge function, even if there isn't a middleware.

@lilnasy lilnasy force-pushed the refactor-singular-middleware branch from 9459137 to 054460e Compare January 23, 2024 14:51
@lilnasy
Copy link
Contributor Author

lilnasy commented Jan 23, 2024

This means that now we always create an edge function, even if there isn't a middleware.

That's true, unfortunately. I'll take a look.

@@ -145,10 +145,12 @@ export async function generatePages(opts: StaticBuildOptions, internals: BuildIn
const baseDirectory = getOutputDirectory(opts.settings.config);
const renderersEntryUrl = new URL('renderers.mjs', baseDirectory);
const renderers = await import(renderersEntryUrl.toString());
const { onRequest: middleware } = await import(new URL('middleware.mjs', baseDirectory).toString());
Copy link
Contributor

Choose a reason for hiding this comment

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

This is new, can you explain why this is imported this way? I can see that it's passed into createBuildManifest, how was the middleware previously imported in generation? I don't see an old import() that was removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Previously, manifest was picked up from ssrEntry.

https://github.com/withastro/astro/pull/9776/files#diff-10cec9990a82f35ed4ce5e0137005fc5035b0291910a4162f1ff0c5adbf2a8efL253

Here, it is being imported in the same way as renderers.

@ematipico
Copy link
Member

This means that now we always create an edge function, even if there isn't a middleware.

That's true, unfortunately. I'll take a look.

We could also cheat, and set middleEntrypoint to undefined if we know that we are emitting a no-op

@lilnasy
Copy link
Contributor Author

lilnasy commented Jan 23, 2024

We could also cheat, and set middleEntrypoint to undefined if we know that we are emitting a no-op

That's my temptation as well!

I want to sit on it for a day. If nothing else pops up in my head, I'll go ahead with that.

@lilnasy lilnasy force-pushed the refactor-singular-middleware branch from 054460e to 2e6008a Compare January 25, 2024 15:31
@lilnasy
Copy link
Contributor Author

lilnasy commented Jan 25, 2024

I want to sit on it for a day. If nothing else pops up in my head, I'll go ahead with that.

Implemented a no-compromise solution - the middleware function will always exist, middleware.mjs may not.

packages/astro/src/core/build/generate.ts Outdated Show resolved Hide resolved
@lilnasy lilnasy force-pushed the refactor-singular-middleware branch from 88cb7b3 to 59b97de Compare January 25, 2024 18:03
Copy link
Member

@natemoo-re natemoo-re left a comment

Choose a reason for hiding this comment

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

LGTM! Nice refactors and I'm satisfied that you've addressed all feedback.

];

const contents = [
edgeMiddleware ? `const middleware = (_, next) => next()` : '',
Copy link
Member

Choose a reason for hiding this comment

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

Clever! I think this makes a lot of sense.

@lilnasy lilnasy merged commit dc75180 into withastro:main Jan 25, 2024
13 checks passed
@lilnasy lilnasy deleted the refactor-singular-middleware branch January 25, 2024 19:38
@astrobot-houston astrobot-houston mentioned this pull request Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: astro Related to the core `astro` package (scope)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants