-
Notifications
You must be signed in to change notification settings - Fork 7
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(vike-server): Add smart dependency handling for standalone builds #81
Conversation
* refactor: move middlewares to a dedicated folder * refactor: fix build * refactor: replace sirv by @universal-middleware/sirv * fix: sirv * refactor: small optimization regarding request * refactor: simplify renderPageHandler * chore: remove unused types * feat: remove edge support from main repo. Will be supported instead by specific vike-* packages. BREAKING CHANGE: remove edge support from vike-server. Will be moved to other vike-* repos * feat: +middleware support * refactor(test): move telefunc in +middleware * comment * refactor * refactor * chore: upgrade deps * chore: upgrade deps * feat: replace app.use() usage with apply(app) * chore * chore * chore: upgrade deps * chore: upgrade deps * chore: upgrade deps * chore: upgrade deps * chore: cleanup * chore: upgrade deps * refactor + cleanup
Introduces a new standaloneExternals plugin that intelligently manages external dependencies in standalone server builds: - Adds support for property in server config to specify dependencies that should not be bundled - Traces dependencies using Vercel's NFT to find all required files - Implements smart hoisting rules to minimize output size: - Single-version packages are hoisted to top-level node_modules - Multi-version packages maintain their original structure - Workspace packages are mapped to node_modules/<package-name> - Preserves relative import relationships when files are relocated - Configures Vite and esbuild externals automatically from server config Resolves dependency management issues in standalone builds by eliminating duplicate manual configuration and ensuring all required dependencies are correctly included in the build output.
It can go into a separate extension too :) But I'd like to know what you think about this. |
It even works when setting |
Tell me if I understand this correctly: In a package What would then be the difference with |
This plugin selectively copies only the exact files the app uses, creating a minimal production build. When @vercel/nft detects assets that bundlers miss (like files loaded via fs.readFile), it ensures only those specific required files get copied. In contrast, npm install --prod installs complete packages with all their files, regardless of whether your code uses them or not. For example, if your code only uses a single utility function from a large library, the plugin might copy just 2-3 required files, while npm install would bring in all entire packages with potentially hundreds/thousands of unnecessary files. This plugin only runs if standalone: enabled, when the user wants a build that is directly ready for deployment without any additional steps. |
It seems like you were already on your way to a Vite plugin doing the same thing. What are the differences? |
Yes I have an older Vite plugin, the one you linked. The differences between that and this pr are: Old version: The new vesion took inspiration from https://github.com/nitrojs/nitro/blob/v3/src/build/plugins/externals.ts, but added support for handling packages outside node_modules(externalized local packages) I can maintain the plugin separately, sure. |
Tried to simplify the plugin and make it as clear as I could while preserving its functionality. |
Also I think when a standalone build is enabled and completed by esbuild, all of its input files could be deleted from dist(esbuild.metafile.inputs), and a single .js file left in dist/server. This can save space and make it clearer which file to launch for users. If somone wants to have the non-standalone output, they can always just build it without standalone mode enabled. |
FYI: https://vike.dev/prerender#keepdistserver. Maybe a setting would also be a good approach here. Thinking out loud: maybe a self-contained package |
@nitedani I think you're right, keeping the files does not make much sense when generating a standalone build by default, but as @brillout said, I also think that a dedicated option to keep those files intact would help. Regarding this feature as a whole, the remaining next steps would be:
|
Introduces a new standaloneExternals plugin that intelligently manages external dependencies in standalone server builds:
external
property in server config to specify dependencies that should not be bundledPackages with a single version are directly copied to node_modules/
Packages with multiple versions are stored in node_modules/.vike/@ with the newest version linked to the top level
Workspace packages are mapped to node_modules/