vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
68.15k stars 6.15k forks source link

Using Vite's programmatic API to inject HTML modifications #17675

Closed conspireagency closed 3 months ago

conspireagency commented 3 months ago

My situation is that I'm creating React widgets that I'm injecting on an external site (Shopify in this instance). In order to develop these things I need to run the widgets locally and tunnel them on a Shopify hosted storefront so I can easily interact with things like their AJAX cart API etc.

SO... I went to the Shopify theme, added a root entry div, and added a script tag tunneled to my local main.tsx. Basically what you see in index.html out of the box for Vite, but using an ngrok tunnel.

I was running into the "vite-plugin-react can't detect preamble. Something is wrong." error and saw this other thread. Below code works, but would like to better understand what's going on here and if there's a better way using Vite configuration options so I don't need to add the first script tag (guy in that thread was serving HTML via PHP, & I'm not).

Thank you so much

<script type="module">
import RefreshRuntime from "https://example.ngrok.app/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
<div id="app"></div>
<script type="module" src="https://example.ngrok.app/src/upsell-widgets/main.tsx"></script>

COMMENT FROM ORIGINAL THREAD:

Ah, so you are serving the HTML over your PHP server. Unfortunately because of this, Vite plugins (in this case @vitejs/plugin-react-refresh) won't be able to inject its HTML modifications.

Since you are not using Node.js, you can't leverage Vite's programmatic API to inject those HTML modifications, so in this case you'll have to do it manually inject this code into your HTML:

<script type="module">
import RefreshRuntime from "/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>

This isn't a bug per-se, but we probably want to consider how to improve that.

Originally posted by @yyx990803 in https://github.com/vitejs/vite/issues/1984#issuecomment-778289660

hi-ogawa commented 3 months ago

Can you check this? https://github.com/vitejs/vite-plugin-react/issues/336#issuecomment-2164859744 It's possible that two <script /> are executed in a random order and main.tsx is executed before window.__vite_plugin_react_preamble_installed__ = true reaches. One common workaround is to move main.tsx to the first <script> as dynamic import.

hi-ogawa commented 3 months ago

Oh, sorry I misunderstood the issue since you are saying the code is working. Please ignore my previous comment.

conspireagency commented 3 months ago

@hi-ogawa yeah, just trying to understand why I have to add that extra "@react-refresh" script tag and what @yyx990803 was saying about Vite's programmatic API