feat: expose module identifier - #32
Conversation
chenjiahan
left a comment
There was a problem hiding this comment.
Thanks for working on this! The module identifier option looks good to me.
I noticed two issues with the server HMR changes:
- SSR builds import
ssrRender, but the generated template update callback still callsapi.rerender(id, render). I reproduced aReferenceError: render is not definedwhen applying a template update. - The imported-type watch hook only invalidates
clientCache, while server builds useserverCache. Changes to imported prop types can therefore leave the server using stale compiled results.
Would you be open to moving the server HMR changes into a separate PR? That would let us review the update behavior and add tests for actual SSR template and type updates independently.
67afd6a to
7e715e0
Compare
Add an opt-in `exposeModuleIdentifier` option that attaches a stable `__moduleIdentifier` to each component, so an SSR runtime can map the components it rendered back to their chunks.
7e715e0 to
85696c6
Compare
@chenjiahan Oh, I didn't notice that! Of course - I've removed the HMR code. I'll investigate both issues and bring them back in a separate PR. |
`hotReload: true` now opts a server build into hot reload as well, so a dev server that renders on the server can hot swap modules instead of restarting the whole process. Server builds stay opt-in: without the flag nothing changes, and `hotReload: false` still wins. Addresses both issues raised in the review of #32: - A server build imports `ssrRender`, but the generated template update callback called `api.rerender(id, render)`, which threw `ReferenceError: render is not defined`. `api.rerender` cannot handle `ssrRender` either - it assigns whatever it is given to `render` and re-renders the mounted instances, which a server build does not have. The new function is written back to the component definition instead, which is the object parent modules hold on to. - The imported-type watch hook only invalidated `clientCache`, so a server build kept rendering with the stale compiled script after an imported prop type changed. Both caches are invalidated now. Tests drive a real watching server build: they render through `vue/server-renderer`, edit a template or an imported type, apply the hot update the way a dev server would, and render again.
An opt-in option for SSR setups. It is a no-op unless you pass it, so nothing changes for existing users.
exposeModuleIdentifierAttaches a stable identifier to each component, so an SSR runtime can map the components it rendered back to their chunks and preload the right CSS/JS.
v15 did this itself via
componentNormalizer.js#L56-L57. It was dropped in v16 and never replaced (vue-loader#1887, open since 2021, confirmed as "planned but not yet implemented"). Two PRs tried to restore it and are still unmerged: #2079 and #2083.Both register into
ssrContext._registeredComponentswith a fixed hash. This PR only exposes the value instead, because consumers disagree on both parts:_registeredComponentswithssrContext.modules.vue-server-rendererbyhash-sumof the request, #2083 by sha256, and it flags the clash itself.The name
__moduleIdentifiermatches v15 and Nuxt's mixin, so existing consumer code works unchanged. The value goes throughpropsToAttachlike__file, and the|<hash>suffix from inline match resources is stripped so it lines up withModule.identifier().Registering into
ssrContexton top of this is a few lines consumer-side. Happy to move it into the loader instead if you prefer.