#Project structure for manually bootstrapping Vite+React?

1 messages · Page 1 of 1 (latest)

fallen vapor
#

Im currently using vite as just a bundler
the script runs on a page I don't control / don't want to alter
so to show a ui i have to open a new tab like this

const w = window.open("", "_blank")
w.document.body.innerHTML = "a vanilla.js ui"

now suppose i want to make this new page a vite+react app
I could set up an entirely new project and import the ui bundle somehow

import my_ui from "gui/dist/index.html?raw"
const w = window.open("", "_blank")
w.document.body.parentElement.outerHTML = my_ui

but since I dont even have a backend, getting the scripts / assets inlined into the ui bundle seems tricky
https://github.com/richardtallent/vite-plugin-singlefile?tab=readme-ov-file#caveats

and im guessing the devex wont be pleasant either, probably breaking hot reload

So I guess my question is if there's any alternative to setting up a separate vite project

fallen vapor
#

got it working with a second vite config but shared package.json / tsconfig.json / etc

// userscript.ts

// @ts-ignore
import uiBundle from "@/../dist/ui/src/lib/.../main.html?raw"

export function launchUi() {
    const w = (unsafeWindow ?? window).open("", "_blank")
    if (!w) {
        alert(
            "Unable to open new tab. Please enable pop-ups for this site."
        )
        return
    }

    w.document.write(uiBundle)

    // write() doesn't run the <script> tags for some reason
    for (const scriptEl of w.document.querySelectorAll(
        "script"
    )) {
        w.eval(scriptEl.textContent)
    }
}
``` ```html
<!-- main.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <link rel="icon" type="image/svg+xml" href="/vite.svg" />
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0"
        />
        <title>Vite + React + TS</title>
    </head>
    <body>
        <div id="root"></div>
        <script type="module" src="./main.tsx"></script>
    </body>
</html>
``` ```tsx
// main.tsx
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import Test from "./test"

createRoot(document.getElementById("root")!).render(
    <StrictMode>
        <Test></Test>
    </StrictMode>
)
``` ```ts
// vite.config.ts
import { defineConfig } from "vite"
import monkey from "vite-plugin-monkey"

export default defineConfig((config) => {
    return {
        plugins: [
            monkey(),
        ],
        build: {
            outDir: "dist/userscript/",
        },
    }
})
#
// vite.config.ui.ts
export default defineConfig((config) => {
    return {
        plugins: [react(), viteSingleFile()],
        build: {
            outDir: "dist/ui",
            rollupOptions: {
                input: {
                    app: "./src/lib/.../main.html",
                },
            },
        },
    }
})
``` ```json
// replacing vite build --watch in package.json
{
    "scripts": {
        "dev": "npm-watch",
        "dev-userscript": "vite build --mode development --config vite.config.ts",
        "dev-ui": "vite build --mode development --config vite.config.ui.ts",
        "serve": "python3 -m http.server --directory dist/userscript 5648",
    },
    "type": "module",
    "watch": {
        "dev-userscript": {
            "patterns": [
                "src",
                "dist/ui"
            ],
            "extensions": "html,css,js,ts,tsx",
            "verbose": true
        },
        "dev-ui": {
            "patterns": [
                "src"
            ],
            "extensions": "html,css,js,ts,tsx",
            "verbose": true
        }
    }
}
#

kinda slow without --watch and some external react components arent mounting for some reason