-
Notifications
You must be signed in to change notification settings - Fork 12
feat: add @netlify/vite-plugin-tanstack-start
#455
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: add @netlify/vite-plugin-tanstack-start
#455
Conversation
| "@tanstack/react-start": "alpha", | ||
| "@tanstack/solid-start": "alpha", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME before merge (or fast follow, depending on how timing plays out)
these should be something like >=1.132.0
| "@netlify/dev": "4.5.9", | ||
| "@netlify/dev-utils": "^4.1.3" | ||
| "@netlify/dev-utils": "^4.1.3", | ||
| "dedent": "^1.7.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
26 KB, zero dependencies, maintained: https://node-modules.dev/#install=dedent
worth it for proper syntax highlighting and syntax parsing in IDEs
af6ec5e to
a2a0061
Compare
This adds a framework-agnostic Vite build plugin that prepares a Vite app for deployment to Netlify. It expects that the Vite app has an `ssr` environment (and no other server environments to deploy) that has exactly one bundle entry and that this entry is a server request entry point, a module with a default export containing a Web Fetch handler under the `fetch` property. TanStack Start meets all these conditions. This build plugin can be opted into via the intentionally private, undocumented `build.enabled` option, passed into `@netlify/vite-plugin`. This also adds a new `@netlify/vite-plugin-tanstack-start` which just wraps `@netlify/vite-plugin` with this enabled. At the moment, this only supports TanStack Start `alpha`, but this will be released imminently (presumably v.1.132 or so). As such, it inherits its requirements: - Vite 7+ - Node.js 22.12.0+
715c821 to
f148fa5
Compare
| "zod": "^3.24.2" | ||
| }, | ||
| "devDependencies": { | ||
| "@netlify/vite-plugin-tanstack-start": "file:../../..", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☝🏼 one of the only changes to the starter
| }), | ||
| tanstackStart(), | ||
| viteReact(), | ||
| netlify(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☝🏼 one of the only changes to the starter
| [build] | ||
| command = "npm run build" | ||
| publish = "dist/client" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☝🏼 the last change to the starter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will be able to remove need for this once netlify/build#6669 ships, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, framework detection doesn't occur on netlify deploy. this uses an existing site.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File copied from remix-compute, simplified, and refactored away unnecessary dependencies
We're probably overdue for a shared helper in a package somewhere...
| "description": "Vite plugin for TanStack Start on Netlify", | ||
| "type": "module", | ||
| "engines": { | ||
| "node": "^22.12.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is going to be TanStack Start's supported range, so no use in supporting any greater
| "peerDependencies": { | ||
| "@tanstack/react-start": "alpha", | ||
| "@tanstack/solid-start": "alpha", | ||
| "vite": ">=7.0.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is going to be TanStack Start's supported range, so no use in supporting any greater
packages/vite-plugin/src/main.ts
Outdated
| */ | ||
| middleware?: boolean | ||
|
|
||
| /** @private */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, this could be a separate export from @netlify/vite-plugin? like /internal or something. or not exposed at all, one way or another. I liked this approach, but I don't feel strongly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know the intended behavior with @private, but this doesn't seem to prevent from build option from being shown to users (unless it requires some specific configuration, this was just default behavior in empty project I checked after installing npm packed version of vite plugin from this PR):
I don't necessarily think we shouldn't do it like this, but maybe we could duplicate
* This is currently only supported for TanStack Start projects.
to apply to build property as well and not just build.enabled? (or maybe move it there)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hrm. well, I added a more explicit callout: 84225cb. I think this is fine for now? we can always refactor later. I think it's fine to change it without majors.
| "prepack": "npm run build", | ||
| "test": "vitest run", | ||
| "test:dev": "vitest", | ||
| "test:ci": "npm run build && vitest run", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this wasn't necessary. it was building twice in CI.
| export default defineConfig({ | ||
| test: { | ||
| testTimeout: 15_000, | ||
| hookTimeout: 90_000, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did have to bump this even more when trying to debug it on windows ... so maybe this is just still not enough ( I did see you bumped it at least once already )
But after that I did get
FAIL test/e2e/build.test.ts > build output when deployed to Netlify
Error: Could not extract the URL from the build logs
❯ deploySite test/support/netlify-deploy.ts:65:11
63| const [url] = new RegExp(/https:.+\.netlify\.app/gm).exec(stdout) ?? []
64| if (!url) {
65| throw new Error('Could not extract the URL from the build logs')
| ^
66| }
67| console.log(`🌍 Deployed site is live: ${url}`)
❯ test/e2e/build.test.ts:18:21
And checking _deploy.log I see CLI formatted the thing we match on like so:
╭───────────────────────── ⬥ Draft deploy is live ⬥ ─────────────────────────╮
│ │
│ Deployed draft to https://68cd7cef1a39c99933013541--phenomenal-hummingbi │
│ rd-d567fe.netlify.app │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
... but even ignoring all that and checking deployed site - https://68cd7cef1a39c99933013541--phenomenal-hummingbird-d567fe.netlify.app/ it crashes with:
Sep 19, 05:59:36 PM: ERROR Uncaught Exception {"errorType":"Error","errorMessage":"Cannot find package 'react' imported from /var/task/.netlify/v1/functions/server.mjs","code":"ERR_MODULE_NOT_FOUND","stack":["Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'react' imported from /var/task/.netlify/v1/functions/server.mjs"," at Object.getPackageJSONURL (node:internal/modules/package_json_reader:268:9)"," at packageResolve (node:internal/modules/esm/resolve:774:81)"," at moduleResolve (node:internal/modules/esm/resolve:860:18)"," at moduleResolveWithNodePath (node:internal/modules/esm/resolve:990:14)"," at defaultResolve (node:internal/modules/esm/resolve:1033:79)"," at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:780:12)"," at #cachedDefaultResolve (node:internal/modules/esm/loader:704:25)"," at ModuleLoader.resolve (node:internal/modules/esm/loader:687:38)"," at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:305:38)"," at ModuleJob._link (node:internal/modules/esm/module_job:137:49)"]}
Sep 19, 05:59:36 PM: INIT_REPORT Init Duration: 271.73 ms Phase: invoke Status: error Error Type: Runtime.Unknown
Sep 19, 05:59:36 PM: f47e870f Duration: 341.44 ms Memory Usage: 106 MB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh, it looks like we don't test on Windows in remix-compute, where I copied the test helper from: https://github.com/netlify/remix-compute/tree/573bb9494e13bd1a4e858b76322ab112984db994/.github/workflows. so there are probably some latent issues there.
the url thing is easy to fix... looks like the boxen thing makes it sometimes wrap over two lines. Adding --json (but kept the rest of the logic) should fix that: d7b644e.
also bumped timeout even higher... let's see if we can at least fix the first 2 of 3 issues: 3962b51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could switch it from pnpm to something else...? let me try changing it to npm.
or maybe one of these pnpm options could help 😕:
--package-import-method auto Clones/hardlinks or copies packages. The selected method depends from the file system
--package-import-method clone Clone (aka copy-on-write) packages from the store
--package-import-method copy Copy packages from the store
--package-import-method hardlink Hardlink packages from the store
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
welp, I did fix the first two issues but debugging the third is a rabbit hole I can't afford right now, so I skipped Windows tests for now :(
pnpm seems to be problematic on Windows CI...
We'll do this in a separate PR to be safe.
follow-up to d117f25 You can't use `overrides` for a direct dependency unless the values are identical...
Because we now have framework-specific plugins that load our generic plugin, we should make sure nothing bad happens if a user also includes our generic plugin directly. I went down a few different paths here and this ended up seeming like the best approach: just warn when we detect multiple instances in dev. Build is tricky because by design our plugin will be instantiated once per environment (e.g. client + ssr). And it ends up generally not being a problem if it's duplicated in build anyway, just dev.
math is hard
also fix technically incorrect node version check
Summary
This adds a framework-agnostic Vite build plugin that prepares a Vite app for deployment to Netlify. It expects that the Vite app has an
ssrenvironment (and no other server environments to deploy) that has exactly one bundle entry and that this entry is a server request entry point—a module with a default export containing a Web Fetch handler under thefetchproperty. TanStack Start meets all these conditions.This build plugin can be opted into via the intentionally private, undocumented
build.enabledoption, passed into@netlify/vite-plugin.This also adds a new
@netlify/vite-plugin-tanstack-startwhich just wraps@netlify/vite-pluginwith this enabled.At the moment, this only supports TanStack Start
alpha, but this will be released imminently (presumably v.1.132 or so). As such, it inherits its requirements:Note that by wrapping
@netlify/vite-plugin,@netlify/vite-plugin-tanstack-startalso inherits all the former's dev functionality.Just in case someone were to (unnecessarily) configure both, this PR adds some logic to detect this and print an actionable warning.
To do
@netlify/vite-pluginrunning twice?[ ] add edge SSR support if easy