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

feat(vercel): ISR #9714

Merged
merged 21 commits into from
Feb 7, 2024
Merged

feat(vercel): ISR #9714

merged 21 commits into from
Feb 7, 2024

Conversation

lilnasy
Copy link
Contributor

@lilnasy lilnasy commented Jan 17, 2024

Changes

  • Introduces a project level config that enables persistent caching for all on-demand rendered routes.
  • website-wide isr
  • website-wide revalidate
  • website-wide bypassToken
  • exclude paths from isr
  • route-specific configuration out of scope
  • dev mode should not allow query params when isr is enabled

Usage

Basic usage - enough for 80% of the users - caches all pages on first request and saves forever
export default defineConfig({
    output: "server",
    adapter: vercel({ isr: true })
})
Time based invalidation - caches all pages on first request and saves for 1 day
export default defineConfig({
    output: "server",
    adapter: vercel({
        isr: {
            expiration: 60 * 60 * 24
        }
    })
})
Manual invalidation - caches all pages on first request and lets you create an endpoint where you clear it
export default defineConfig({
    output: "server",
    adapter: vercel({
        isr: {
            // A random string that you create. Its presence in the `__prerender_bypass` cookie will result in fresh responses being served, bypassing the cache.
            bypassToken: "005556d774a8" // I created this using crypto.randomUUID(),
            // Paths that will always be served fresh.
            exclude: [ "/api/invalidate" ] 
        }
    })
})

Testing

Added isr.test.js with a fixture

Docs

Copy link

changeset-bot bot commented Jan 17, 2024

🦋 Changeset detected

Latest commit: 44d4ced

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 pkg: example Related to an example package (scope) pkg: integration Related to any renderer integration (scope) pkg: astro Related to the core `astro` package (scope) labels Jan 17, 2024
@github-actions github-actions bot removed pkg: example Related to an example package (scope) pkg: astro Related to the core `astro` package (scope) labels Jan 17, 2024
@lilnasy lilnasy force-pushed the vercel-isr branch 2 times, most recently from d3d25b4 to a9cc77c Compare January 25, 2024 17:10

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev
@lilnasy lilnasy marked this pull request as ready for review January 25, 2024 22:26
@lilnasy
Copy link
Contributor Author

lilnasy commented Jan 25, 2024

!preview isr

Copy link
Contributor

Snapshots have been released for the following packages:

  • @astrojs/rss@experimental--isr
  • astro@experimental--isr
  • @astrojs/node@experimental--isr
  • @astrojs/alpinejs@experimental--isr
  • create-astro@experimental--isr
  • @astrojs/vercel@experimental--isr
Publish Log
🦋  warn ===============================IMPORTANT!===============================
🦋  warn Packages will be released under the experimental--isr tag
🦋  warn ----------------------------------------------------------------------
🦋  info npm info astro
🦋  info npm info @astrojs/prism
🦋  info npm info @astrojs/rss
🦋  info npm info create-astro
🦋  info npm info @astrojs/alpinejs
🦋  info npm info @astrojs/lit
🦋  info npm info @astrojs/markdoc
🦋  info npm info @astrojs/mdx
🦋  info npm info @astrojs/node
🦋  info npm info @astrojs/partytown
🦋  info npm info @astrojs/preact
🦋  info npm info @astrojs/react
🦋  info npm info @astrojs/sitemap
🦋  info npm info @astrojs/solid-js
🦋  info npm info @astrojs/svelte
🦋  info npm info @astrojs/tailwind
🦋  info npm info @astrojs/vercel
🦋  info npm info @astrojs/vue
🦋  info npm info @astrojs/internal-helpers
🦋  info npm info @astrojs/markdown-remark
🦋  info npm info @astrojs/telemetry
🦋  info npm info @astrojs/underscore-redirects
🦋  info npm info @astrojs/upgrade
🦋  info astro is being published because our local version (0.0.0-isr-20240125224234) has not been published on npm
🦋  warn @astrojs/prism is not being published because version 3.0.0 is already published on npm
🦋  info @astrojs/rss is being published because our local version (0.0.0-isr-20240125224234) has not been published on npm
🦋  info create-astro is being published because our local version (0.0.0-isr-20240125224234) has not been published on npm
🦋  info @astrojs/alpinejs is being published because our local version (0.0.0-isr-20240125224234) has not been published on npm
🦋  warn @astrojs/lit is not being published because version 4.0.1 is already published on npm
🦋  warn @astrojs/markdoc is not being published because version 0.8.3 is already published on npm
🦋  warn @astrojs/mdx is not being published because version 2.1.0 is already published on npm
🦋  info @astrojs/node is being published because our local version (0.0.0-isr-20240125224234) has not been published on npm
🦋  warn @astrojs/partytown is not being published because version 2.0.4 is already published on npm
🦋  warn @astrojs/preact is not being published because version 3.1.0 is already published on npm
🦋  warn @astrojs/react is not being published because version 3.0.9 is already published on npm
🦋  warn @astrojs/sitemap is not being published because version 3.0.5 is already published on npm
🦋  warn @astrojs/solid-js is not being published because version 4.0.1 is already published on npm
🦋  warn @astrojs/svelte is not being published because version 5.0.3 is already published on npm
🦋  warn @astrojs/tailwind is not being published because version 5.1.0 is already published on npm
🦋  info @astrojs/vercel is being published because our local version (0.0.0-isr-20240125224234) has not been published on npm
🦋  warn @astrojs/vue is not being published because version 4.0.8 is already published on npm
🦋  warn @astrojs/internal-helpers is not being published because version 0.2.1 is already published on npm
🦋  warn @astrojs/markdown-remark is not being published because version 4.2.0 is already published on npm
🦋  warn @astrojs/telemetry is not being published because version 3.0.4 is already published on npm
🦋  warn @astrojs/underscore-redirects is not being published because version 0.3.3 is already published on npm
🦋  warn @astrojs/upgrade is not being published because version 0.2.2 is already published on npm
🦋  info Publishing "astro" at "0.0.0-isr-20240125224234"
🦋  info Publishing "@astrojs/rss" at "0.0.0-isr-20240125224234"
🦋  info Publishing "create-astro" at "0.0.0-isr-20240125224234"
🦋  info Publishing "@astrojs/alpinejs" at "0.0.0-isr-20240125224234"
🦋  info Publishing "@astrojs/node" at "0.0.0-isr-20240125224234"
🦋  info Publishing "@astrojs/vercel" at "0.0.0-isr-20240125224234"
🦋  success packages published successfully:
🦋  [email protected]
🦋  @astrojs/[email protected]
🦋  [email protected]
🦋  @astrojs/[email protected]
🦋  @astrojs/[email protected]
🦋  @astrojs/[email protected]
🦋  Creating git tags...
🦋  New tag:  [email protected]
🦋  New tag:  @astrojs/[email protected]
🦋  New tag:  [email protected]
🦋  New tag:  @astrojs/[email protected]
🦋  New tag:  @astrojs/[email protected]
🦋  New tag:  @astrojs/[email protected]
Build Log

> [email protected] build /home/runner/work/astro/astro
> turbo run build --filter=astro --filter=create-astro --filter="@astrojs/*" --filter="@benchmark/*"

• Packages in scope: @astrojs/alpinejs, @astrojs/cloudflare, @astrojs/internal-helpers, @astrojs/lit, @astrojs/markdoc, @astrojs/markdown-remark, @astrojs/mdx, @astrojs/netlify, @astrojs/node, @astrojs/partytown, @astrojs/preact, @astrojs/prism, @astrojs/react, @astrojs/rss, @astrojs/sitemap, @astrojs/solid-js, @astrojs/svelte, @astrojs/tailwind, @astrojs/telemetry, @astrojs/underscore-redirects, @astrojs/upgrade, @astrojs/vercel, @astrojs/vue, @benchmark/timer, astro, create-astro
• Running build in 26 packages
• Remote caching enabled
::group::@astrojs/telemetry:build
cache miss, executing 1c016d3e37518589

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/telemetry
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/internal-helpers:build
cache miss, executing e25be05d3a847557

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/internal-helpers
> astro-scripts build "src/**/*.ts" && tsc -p tsconfig.json

::endgroup::
::group::@astrojs/upgrade:build
cache miss, executing e87558f8d7175f95

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/upgrade
> astro-scripts build "src/index.ts" --bundle && tsc

::endgroup::
::group::@astrojs/prism:build
cache miss, executing 525d688a9dfc3924

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/astro-prism
> astro-scripts build "src/**/*.ts" && tsc -p ./tsconfig.json

::endgroup::
::group::create-astro:build
cache miss, executing 440570bd8def9142

> [email protected] build /home/runner/work/astro/astro/packages/create-astro
> astro-scripts build "src/index.ts" --bundle && tsc

::endgroup::
::group::@astrojs/markdown-remark:build
cache miss, executing 20b1d6baeaeefad6

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/markdown/remark
> astro-scripts build "src/**/*.ts" && tsc -p tsconfig.json

::endgroup::
::group::astro:build
cache miss, executing 2d2dc45f0876f76b

> [email protected] build /home/runner/work/astro/astro/packages/astro
> pnpm run prebuild && astro-scripts build "src/**/*.{ts,js}" && tsc && pnpm run postbuild


> [email protected] prebuild /home/runner/work/astro/astro/packages/astro
> astro-scripts prebuild --to-string "src/runtime/server/astro-island.ts" "src/runtime/client/{idle,load,media,only,visible}.ts"


> [email protected] postbuild /home/runner/work/astro/astro/packages/astro
> astro-scripts copy "src/**/*.astro" && astro-scripts copy "src/**/*.wasm"

::endgroup::
::group::@astrojs/lit:build
cache miss, executing 8a4e9b95ceea1270

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/lit
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/react:build
cache miss, executing c83a485c6049ea50

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/react
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@benchmark/timer:build
cache miss, executing 7b583fb60757e9b0

> @benchmark/[email protected] build /home/runner/work/astro/astro/benchmark/packages/timer
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/alpinejs:build
cache miss, executing 9c4ffd3d760094cf

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/alpinejs
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/partytown:build
cache miss, executing 919d4228e501867d

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/partytown
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/solid-js:build
cache miss, executing dae9a8f0d376bf28

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/solid
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/node:build
cache miss, executing 31621b866325cbe0

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/node
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/vercel:build
cache miss, executing 5f009e633c086b74

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/vercel
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/preact:build
cache miss, executing ea8fb29620e2c3bd

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/preact
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/mdx:build
cache miss, executing ab862889d9dd61ee

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/mdx
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/rss:build
cache miss, executing 4c19bd8feac79cae

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/astro-rss
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/underscore-redirects:build
cache miss, executing c61d2ce25a4973f2

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/underscore-redirects
> astro-scripts build "src/**/*.ts" && tsc -p tsconfig.json

::endgroup::
::group::@astrojs/markdoc:build
cache miss, executing 88b89728b68ee1be

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/markdoc
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/tailwind:build
cache miss, executing 115ed063ebf41ea0

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/tailwind
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/svelte:build
cache miss, executing 8de0468229fe5447

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/svelte
> astro-scripts build "src/index.ts" && astro-scripts build "src/editor.cts" --force-cjs --no-clean-dist && tsc

::endgroup::
::group::@astrojs/sitemap:build
cache miss, executing 03d94b3bff8cdc82

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/sitemap
> astro-scripts build "src/**/*.ts" && tsc

::endgroup::
::group::@astrojs/vue:build
cache miss, executing f7fa52d849198c33

> @astrojs/[email protected] build /home/runner/work/astro/astro/packages/integrations/vue
> astro-scripts build "src/index.ts" && astro-scripts build "src/editor.cts" --force-cjs --no-clean-dist && tsc

::endgroup::

 Tasks:    24 successful, 24 total
Cached:    0 cached, 24 total
  Time:    46.328s 

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.

Great work! I'd love at least one other approval before we merge this given what a big feature this is!

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.

Great work! I'd love at least one other approval before we merge this given what a big feature this is!

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev
// isr functions do not have access to search params, this middleware removes them for the dev mode
if (isr) {
const exclude_ = typeof isr === "object" ? isr.exclude ?? [] : [];
const exclude = exclude_.concat("/_image").map(ex => new RegExp(ex));
Copy link
Member

Choose a reason for hiding this comment

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

Instead of a regex expression, should we be a little accurate here? Looks like if it's passed ['/foo'], it could also match requests for /other/foo.

If we want to allow marking entire directories to exclude, maybe we can accept (string | RegExp)[] instead?

Copy link
Member

Choose a reason for hiding this comment

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

+1 from me too. Also, if a user passes a string, we should do an equality check, and not create a regex.

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 agree we should be stricter.

It's a RegExp here because that's how vercel processes the routes file.

I'll look into making the exclude paths behave as literal paths.

isr,
});
}
if (isr === false || (isr && typeof isr === "object" && isr.exclude)) {
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit confused about this check, should this be an else block because we already check isr above?

I'm not sure why this is checking isr.exclude specifically to create another function folder which could've been already generated above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The condition here checks whether a normal function needs to be created. Even when ISR is enabled, the excluded paths would need to create one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

/**
* Expiration time (in seconds) before the pages will be re-generated.
*
* By default, as long as the current deployment is in production.
Copy link
Member

@ematipico ematipico Jan 29, 2024

Choose a reason for hiding this comment

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

I don't understand this phrase. By default, what? It's not a boolean, so the default should be a number

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The default javascript value is false, but that just doesn't communicate anything.

Copy link
Member

@ematipico ematipico Jan 29, 2024

Choose a reason for hiding this comment

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

That's false because the parent object is optional, right? But if I pass an object, this field must have a default as stated in the docs. Which means I don't understand what's the default value in numbers of this option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does this help?

image

prerender-config.json

Copy link
Contributor Author

Choose a reason for hiding this comment

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

New lines 146-153.

revalidate?: number;

/**
* Paths that will always be served fresh.
Copy link
Member

Choose a reason for hiding this comment

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

I would add a longer documentation here. From the implementation, I inferred that paths can be regex, but here I couldn't figure it out. I thought only strings were accepted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is correct. Only strings are accepted. Vercel would interpret the string as a regex but that's a vercel implementation detail. I will look into adding a processing step so that they really only ever act like strings.

// isr functions do not have access to search params, this middleware removes them for the dev mode
if (isr) {
const exclude_ = typeof isr === "object" ? isr.exclude ?? [] : [];
const exclude = exclude_.concat("/_image").map(ex => new RegExp(ex));
Copy link
Member

Choose a reason for hiding this comment

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

+1 from me too. Also, if a user passes a string, we should do an equality check, and not create a regex.

packages/integrations/vercel/src/serverless/adapter.ts Outdated Show resolved Hide resolved
packages/integrations/vercel/src/serverless/adapter.ts Outdated Show resolved Hide resolved

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Verified

This commit was signed with the committer’s verified signature.
develar Vladimir Krivosheev

Unverified

This user has not yet uploaded their public signing key.
@lilnasy lilnasy marked this pull request as draft January 29, 2024 18:22
@lilnasy
Copy link
Contributor Author

lilnasy commented Jan 29, 2024

Converting to draft because there's something about routing I need to confirm after these changes, but I can't today.

Update: I had erika confirm - /_image would always need to be excluded because we never know what query params an image service may read.

@lilnasy lilnasy marked this pull request as ready for review January 29, 2024 19:08
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.

Looks good!

@sarah11918
Copy link
Member

I was asked to review the typed documentation here, and it's looking pretty good! Right now, there's nothing here that would show up in docs itself, nor a changeset to edit. But, I'd say this is a good basis for API docs. Carry on! 🫡

@lilnasy
Copy link
Contributor Author

lilnasy commented Feb 1, 2024

Oh, didn't even realise I missed the changeset.

Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

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

Thanks @lilnasy ! Looking good! Here are my initial thoughts!

Also noting: there is more info here than you put in the actual docs PR. So... all this stuff should end up over there!

.changeset/flat-snakes-hammer.md Outdated Show resolved Hide resolved
.changeset/flat-snakes-hammer.md Outdated Show resolved Hide resolved
.changeset/flat-snakes-hammer.md Outdated Show resolved Hide resolved
.changeset/flat-snakes-hammer.md Outdated Show resolved Hide resolved
@lilnasy lilnasy merged commit e2fe51c into withastro:main Feb 7, 2024
13 checks passed
@lilnasy lilnasy deleted the vercel-isr branch February 7, 2024 13:36
@astrobot-houston astrobot-houston mentioned this pull request Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: integration Related to any renderer integration (scope)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants