vite icon indicating copy to clipboard operation
vite copied to clipboard

Export `fileToUrl` function for plugins

Open Menci opened this issue 2 years ago • 9 comments

Clear and concise description of the problem

Vite's some internal plugins uses the internal helper function fileToUrl, which emits asset file to dev-server/bundle and return a URL for using in generated module code. It's also very useful for external plugins to emit asset files.

Suggested solution

Export fileToUrl function from Vite and document it in the docs.

Alternative

Plugin authors could copy the code from fileToUrl from their plugins. This is very inelegant.

Additional context

No response

Validations

Menci avatar Mar 03 '22 16:03 Menci

@Menci Can you show an example where this would be useful for external plugins? It would be helpful to justify exposing another API.

bluwy avatar Mar 04 '22 04:03 bluwy

yep, I want to see you example too. I'd like to share what I've met before

When you encounter picture resources in .markdown, you also can use the asset inside vite to judge whether the picture resources should become files.

for this example maybe we also can use import '1.img' to import assets. 😅 but we don't want to use script tag, it will need to fileToUrl api.

poyoho avatar Mar 04 '22 04:03 poyoho

I'm working on a plugin bringing WebAssembly ESM integration to Vite, which is equivalent to Webpack's asyncWebAssembly.

I need to emit the WASM file just like the internal wasm plugin but I have no way to do it. My workaround is calling the original plugin's load function, which is inelegant and won't work for other types of files (for those without a internal plugin in Vite that emits the file directly).

https://github.com/Menci/vite-plugin-wasm/blob/e501eb234ad22d81d9bc94cb20086b759b4b07df/src/index.ts#L50-L52

Menci avatar Mar 04 '22 09:03 Menci

Thanks for the explanation @Menci (and thanks for updating some old issues about your plugin!). I think it makes sense to export it looking at the plugin code. I'll bring the PR to the next team meeting for discussion.

PS: I wonder if the ESM integration could be first-class in Vite one day, that would be cool. PSS: I think you forgot to rename your plugin name

bluwy avatar Mar 05 '22 08:03 bluwy

I'm working on a plugin bringing WebAssembly ESM integration to Vite, which is equivalent to Webpack's asyncWebAssembly.

+1, having a similar case trying to add WASI support (via @wasmer/wasi) to the wasm loader. It needs to do some stuff before returning exports, so hacking around with the base loader is a no-go, and I'm only left with copy-pasting code from assets.js

reyafyi avatar Mar 08 '22 09:03 reyafyi

@bluwy 👀👀👀

poyoho avatar Apr 16 '22 04:04 poyoho

This seems to still be in the team discussion list. We had briefly talked about it but need Evan's input on how to expose this. Will give an update again when we circle back again!

bluwy avatar Apr 18 '22 02:04 bluwy

Related discussion from @sapphi-red https://github.com/vitejs/vite/discussions/7763 about the use case

patak-dev avatar Apr 18 '22 05:04 patak-dev

If it's in JS, I think import url from './something.js?url' could be used for now.

@Menci For example for your plugin, I guess this part https://github.com/Menci/vite-plugin-wasm/blob/d98e0384950b6aea3156031a17ae65d28bbc7abd/src/index.ts#L37-L57 could be like

`
import __wasmUrl from "${id}?url"
import __vite__initWasm from "${wasmHelper.id}"
${imports
  .map(
    ({ from, names }, i) =>
      `import { ${names.map((name, j) => `${name} as __vite__wasmImport_${i}_${j}`).join(", ")} } from ${JSON.stringify(
        from
      )};`
  )
  .join("\n")}
const __vite__wasmModule = await __vite__initWasm({ ${imports
        .map(
          ({ from, names }, i) =>
            `${JSON.stringify(from)}: { ${names.map((name, j) => `${name}: __vite__wasmImport_${i}_${j}`).join(", ")} }`
        )
        .join(", ")} }, __wasmUrl});
${exports
  .map(name => `export ${name === "default" ? "default" : `const ${name} =`} __vite__wasmModule.${name};`)
  .join("\n")}
`;

or

`
import __vite__initWasm from "${id}?init"
${imports
  .map(
    ({ from, names }, i) =>
      `import { ${names.map((name, j) => `${name} as __vite__wasmImport_${i}_${j}`).join(", ")} } from ${JSON.stringify(
        from
      )};`
  )
  .join("\n")}
const __vite__wasmModule = await __vite__initWasm({ ${imports
        .map(
          ({ from, names }, i) =>
            `${JSON.stringify(from)}: { ${names.map((name, j) => `${name}: __vite__wasmImport_${i}_${j}`).join(", ")} }`
        )
        .join(", ")} });
${exports
  .map(name => `export ${name === "default" ? "default" : `const ${name} =`} __vite__wasmModule.${name};`)
  .join("\n")}
`;

sapphi-red avatar Jul 23 '22 17:07 sapphi-red