vitejs / vite

Next generation frontend tooling. It's fast!
http://vitejs.dev
MIT License
67.41k stars 6.07k forks source link

Return boundary object on HMR update hook #12097

Open alvarosabu opened 1 year ago

alvarosabu commented 1 year ago

Description

As the author of TresJS I wish I could differentiate when an HMR update hook (import.meta.hot.on('vite:beforeUpdate')) is triggered by a change on an <template> on a Vue SFC component and when is triggered from a <script setup /> block.

The reason is we need to dispose of 3D scene objects on HMR

if (import.meta.hot) {
    import.meta.hot.on('vite:beforeUpdate', context => {
      console.log('vite:beforeUpdate', context)
      scene.value.remove(instance)
    })

    import.meta.hot.on('vite:afterUpdate', context => {
      console.log('vite:afterUpdate', context)
      instance = createInstance(threeObj, attrs, slots)
      processProps(attrs, instance)

      if (instance.isObject3D) {
        scene?.value.add(instance)
      }
    })
  }

The problem is that this code works well when the change comes from the template, but if the change comes from the script tag the creation of 3D instances is loaded again, causing duplicate objects on the scene

I checked the value coming from both vite:beforeUpdate and vite:afterUpdate but I don't see any info that could help me differentiate between both

{
    "type": "update",
    "updates": [
        {
            "type": "js-update",
            "timestamp": 1676285908707,
            "path": "/src/components/TheEvents.vue",
            "explicitImportRequired": false,
            "acceptedPath": "/src/components/TheEvents.vue"
        }
    ]
}

Suggested solution

Would be possible if we modify the updateModules method on /packages/vite/src/node/server/hmr.ts#L156 to return the complete boundary object.

With that we could send the updateType from vite-plugin-vue/packages/plugin-vue/src/handleHotUpdate.ts#L170 by modifying the return statement to this

return [...affectedModules].filter(Boolean).map((m) => ({
    ...m,
    updateType,
  }));

I tested it locally and works, but I want to confirm if it's something you would consider before creating the PR in both places

Alternative

I can't think right now of an alternative that could solve the HMR issue.

Additional context

No response

Validations

sapphi-red commented 6 months ago

I think this should be handled in plugin-vue or vue. I guess it makes sense to let a custom renderer to hook into vue's HMR runtime.