Snowpack: Finalize SSR & JS API

Created on 16 Oct 2020  路  6Comments  路  Source: snowpackjs/snowpack

Background

We've been doing a lot of work to support the Snowpack SSR story over the last couple of weeks, and at this point are in a pretty good spot. This issue serves to document the last known work needed before we can consider this work "done" and can remove the__unstable prefix from our new JS API.

Work Needed

  • [x] Need a way to detect if you are in browser or Node.js: This should probably be something like import.meta.env.CLIENT or import.meta.env.ENVIRONMENT. We already have `import.meta.env.MODE for "development" vs. "production".
  • [x] requestHandler() should return errors: Right now, this middleware only calls next() on a 404. Instead, we should call next(err) with an error so that it can be handled as needed by the integrator. Currently, we'll just handle the 500 silently.
  • [x] Refactor out the "server" from the JS API (as much as possible): Currently, loadByUrl() is literally making an HTTP request to localhost behind the scenes. We have all the tools to make this call via JS instead, and not have to deal with serializing success/errors over HTTP. Lets remove as much of the "HTTP" logic from our JS API, and just make direct function calls instead.
  • [x] Document new JS API
  • [x] Document SSR Story (for both dev & build) and anything else mentioned above

Nice to Have

  • [ ] Figure out SSR story for ESM loading in Node.js: Svelte team is using a special ESM loader for Node.js, that loads files by URL into Node.js. It's dark magic, but it works impressively well. Pull this into it's own package or pull this into Snowpack itself.
  • [x] Easier --ssr builds?: Right now, a Snowpack SSR build is something that needs to be run聽in addition to a non-SSR run. Basically, you end up having to do this yourself on every build: snowpack build --out build/client && snowpack build --ssr --out build/server. Instead, in --ssr mode, it can be assumed that you always want both. I don't believe that we have a current use-case where you only want one, although we could certainly add --ssr-only for those few weirdos :)

    • Open question: how much does this blow out our config surface area? What extra config is needed? If possible, I'd really like to be a sensible default and then use --ssr-only if you really need to configure stuff yourself.

  • [x] Finalize experiment.middleware: Related to SSR is the idea of connecting some server.js file to your final build. We already have the ability to pass a custom server to Snowpack via experiment.middleware. If possible, I'd like to explore the idea of giving Snowpack an entrypoint file/plugin, and having it automatically create a build/server.js file that can be automatically run for SSR. Not blocking this larger issue, but I'd love to do some more exploration here.
  • anything else?
help wanted v3

Most helpful comment

I'm not sure what their plans are to share the beta @svelte/kit repo, but hopefully its open sourced soon!

All 6 comments

馃憖

Figure out SSR story for ESM loading in Node.js: Svelte team is using a special ESM loader for Node.js, that loads files by URL into Node.js. It's dark magic, but it works impressively well. Pull this into it's own package or pull this into Snowpack itself.

Is there more information about this that I can find somewhere?

I'm not sure what their plans are to share the beta @svelte/kit repo, but hopefully its open sourced soon!

@Rich-Harris I'm planning to close out this issue as a part of v3.0 release, and had two questions for you:

  1. SvelteKit's loader: are you happy with the import rewriting you have built on top of meriyah ? Would it help to output CJS instead of ESM in SSR mode? It would be more difficult to scan/rewrite imports, but the thinking is that instead of rewriting imports you could pass in your own require() function connected directly to sp.loadUrl
  2. --ssr output: just confirming that we're planning to go forward with changing snowpack build --ssr to create two outputs at the same time: build/client and build/server. This should let us run both builds in parallel and share resources across both, giving a nice speed boost. snowpack build --ssr-only (or something similar) will be added to match current behavior of server-only SSR output. Nevermind, I'd hoped we could just run the build twice in parallel in the same process, but not sure its that straightforward anymore. Will push this off to post v3

This is cool!

Would it help to output CJS instead of ESM in SSR mode?

I don't think so, no:

  • Every Snowpack transformer plugin would need to be able to emit CJS in addition to ESM, _or_ Snowpack would need to apply an additional transformation from ESM to CJS (which would be equivalent to the transformation currently happening inside the runtime) _just in case_ it was to be consumed by the runtime (as opposed to e.g. a bundler, which would rather have ESM)
  • In order to implement live bindings, that transformation would have to be rather bloaty
  • I'm not entirely convinced it's even possible? A function call would need to return synchronously (unless we did some _real_ dark magic), but module loading is generally going to be async

Yea I'm definitely only thinking about scoping this to static build output & a post-build transform so that plugins don't need to worry about it. Maybe a better way to frame this would be an opt-in buildOptions.format: "esm" | "cjs" option.

We could also just ship this as a plugin to start, something like this (just a wip for now) and then see if people want it built-in: https://github.com/snowpackjs/snowpack/commit/9f7da17939c0f4483987e206401bea2901b85f77#diff-1abfc525c64c76b319e3c8a5c3ff8df1b345e67cefa274f5a0230bcf9ea9fff8R6

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mfolkeseth picture mfolkeseth  路  5Comments

FredKSchott picture FredKSchott  路  7Comments

backspaces picture backspaces  路  5Comments

devongovett picture devongovett  路  4Comments

FredKSchott picture FredKSchott  路  6Comments