Open benmccann opened 4 years ago
I don't think when certain parts of the current compiler run would be problematic here, we can just use different hooks in order to do certain work at certain times. What currently happens in create_app
, we would want to run during the options
hook, so that we could inject options before rollup processes them. The css extraction happens both on every module and at the end for the final build, we can use the transform
hook and one of writeBundle
or generateBundle
, although a better CSS code-splitting solution would be preferable, not sure how possible that is.
If we went down this route, plugins should be split by concern rather than when they happen, assuming rollup can support that. The Router config generation could be a plugin, the Client builder could be a plugin, the Server builder could be a plugin, etc.
I have a few ideas about how this could work it isn't clear in my mind.
The bigger question in my mind is can we orchestrate things such that we we know which parts of the client bundle are required for a given server route, in order to include the correct assets when server rendering pages, but also in order to give the correct information to the router (if the router config is only finalised at the end of the build then this seems possible). Currently sapper has complete control over how it builds everything, doing things in whatever order it needs to to get the necessary information. We need the client bundle before we generate the server code in order to intelligently fetch assets.
We have access to everything at the end of the bundling process and can still perform whatever steps we need to at that point, if we are splitting per route as a default then it might be reasonable to inspect the output at the end of the bundling process to get the information and make that available to the server-renderer as required. But I'm not sure, I haven't thought it through properly.
One tricky point @ajbouh pointed out is that you probably only want to run create_app
once despite creating two bundles (client and server)
@pngwn I'm not sure I completely understand your comment, though based on my recent explorations and refactorings, I believe sapper already has this information (which client resources are needed for each server route). In fact it depends on this to properly load the associated client code and (when possible) issue the proper preload headers.
Overview
Right now we execute Rollup from the Sapper binary. This is causes a few issues.
Firstly, it's been the source of a few bugs where we haven't reproduced the Rollup CLI faithfully enough. A couple of these have been fixed, but at least one remains: https://github.com/sveltejs/sapper/issues/1266
More importantly though, it makes it difficult to integrate with projects like Nollup (https://github.com/sveltejs/sapper/issues/1207) and Snowpack (https://github.com/sveltejs/sapper/issues/1204). Today there's no way to use an alternative bundler like Nollup with Sapper because Sapper must have an implementation for every bundler. It'd be a small change to enable it in the case of Nollup (rixo@faca5e0), but I'm not sure it's the right separation of concerns that Sapper should have to know about every possible build system
Implementation notes
One thing that'd be a little tricky is that if it were a Rollup plugin we might need multiple plugins. E.g.
create_app
happens early in the build process right now andextract_css
happens later. I'm not sure if we need to maintain that ordering, but I do wonder ifextract_css
might live in a more generally-available plugin. Also,create_serviceworker_manifest
probably deserves its own plugin or we should use Google's existing Workbox plugin