vite-plugin-vue icon indicating copy to clipboard operation
vite-plugin-vue copied to clipboard

Allow configuring how the hmr Id is generated in @vitejs/plugin-vue

Open PPetau opened this issue 3 years ago • 4 comments

Description

I was trying to import a Vue component from another instance of vite.

The problem lies here: https://github.com/vitejs/vite/blob/c78e4099e502876a2ab23fd8163455d8172ff5b7/packages/plugin-vue/src/utils/descriptorCache.ts#L30 Due to how the id on the descriptor is generated it is impossible to me to change how the css-Scope/__hmrId ... will be generated resulting in a broken hmr runtime and conflicting css.

Using the isProduction flag is not viable because it disables the hmr runtime on vue components.

Suggested solution

Could we introduce another flag or an option to specify how this Id would generate?

There could be an Option that works like isProduction to include the source when creating the id hash

Alternative

No response

Additional context

Repro in StackBlitz: https://stackblitz.com/edit/vitejs-vite-kr3fdz?file=vite-1/index.html

If we then edit the vite-1/src/App.vue the other app gets broken because their internal _hmrId is the same.

Validations

PPetau avatar Jul 27 '22 12:07 PPetau

This feels like a very niche usecase which many plugins won't support, so it's not only a problem with plugin-vue. What is your usecase needing to accessing Vue components from a different server?

bluwy avatar Jul 28 '22 08:07 bluwy

I am trying to create some kind of micro-frontend where I am importing other Vue apps from different packages within a workspace. I would like to have multiple vite instances serving the different projects so that the main application can dynamically import these and still utilize the hot reload functionality. Because how the projects are structured, the logic determining how the _hmrId is generated, results in the same id for every component that have the same root-relative path (ex. src/App.vue => "7a7a37b1").

I have written one workaround that tries to rewrite the generated id after the plugin transformed the SFC, but was unable to catch every place where the generated id is used.

PPetau avatar Jul 28 '22 12:07 PPetau

@PPetau could you share your workaround? I have a similar usecase: I have a production app that is extendable with plugins. While the user develops a new plugin I want HMR. I can consume the plugin component in my app directly from the plugin's vite dev server, but the ids won't match so only global styles and scripts are working right now.

arnoson avatar Sep 11 '22 11:09 arnoson

Hi @arnoson, this is the snipped that runs in the transform hook and replaces the generated hmrIds (only of the .vue files).

const hmrUniqueIdentifier = "your_custom_id_namespace";

if (/\.vue/.test(id)) {
  if (code.includes("_sfc_main.__hmrId")) {
    const magicString = new MagicString(code);
    const hmrId = code.match(
      /_sfc_main\.__hmrId\s*\=\s*["'](.+)["']/m
    )?.[1];
    if (hmrId) {
      magicString.replace(
        new RegExp(hmrId, "g"),
        hmrId + hmrUniqueIdentifier
      );
    return {
      code: magicString.toString(),
      map: magicString.generateMap()
    };
  }
}

PPetau avatar Sep 12 '22 06:09 PPetau