nksaraf / vinxi

The Full Stack JavaScript SDK
https://vinxi.vercel.app
MIT License
1.91k stars 77 forks source link

`buildStart` is called 3 times in a row #262

Closed BierDav closed 6 months ago

BierDav commented 6 months ago

I have made a custom plugin that compiles my openapi yamls to javascript files and it worked fine with vite until i switched to vinxi and vite 5.0. Know my plugin is executed 3 times in a row and parralell which doesn't make any sense:

export default function openApiPlugin(): Plugin {
    return {
        name: 'open-api-generate',
        async buildStart() {
            console.log("Generating")
            await main();
            console.log("Generating finished")
        },
        configureServer(server) {
            server.watcher.add(sourceDir)
            server.watcher.on('change', async (file) => {
                if (file.startsWith(sourceDir))
                    await main();
            })
        }
    }
}

This is roughly my code and when i start pnpm dev i get following in the console:

Generating
Generating
Generating
Generating finished
Generating finished
Generating finished

Am I doing something wrong or is this a bug?

Note: This only happens with pnpm dev. When using pnpm build everything works fine and buildStart is called only once.

nksaraf commented 6 months ago

No this is as expected. A SolidStart app is made of three vite subapps (a client app, a server app and server functions app). If you apply a vite plugin normally, it will be applied to all three subapps, thus will run thrice. You can use solid-start's vite option to only apply the plugin to one router, say the server.

eg.

import { defineConfig } from "@solidjs/start/config";
export default defineConfig({
  vite({ router }) {
    if (router === "server") {
    } else if (router === "client") {
    } else if (router === "server-function") {
    }
    return { plugins: [] };
  }
});
nksaraf commented 6 months ago

Wait why is buildStart even called during pnpm dev. That seems wrong.

BierDav commented 6 months ago

No this is as expected. A SolidStart app is made of three vite subapps (a client app, a server app and server functions app). If you apply a vite plugin normally, it will be applied to all three subapps, thus will run thrice.

That makes sense, I didn't know that, thanks

Wait why is buildStart even called during pnpm dev. That seems wrong.

What should I use instead? If buildStart is not the intended way to do so.

nksaraf commented 6 months ago

So you would do two things, one to configure the dev server (watcher), and for the build. You want to hook into the vinxi app hooks 'build:start' event. Right now the way to do this is like this.

const app = defineConfig({ ... });

// add a hook to the app before exporting it
app.hooks.hook('app:build:start', async () => {
    await main()
})

/**
 *
 * @returns {import('vinxi').PluginOption}
 */
function openAPIPlugin() {
  return {
    name: "fs-watcher",
    async configureServer(server) {
        // run it once at the beginning
        await main();
        server.watcher.add(sourceDir)
        server.watcher.on('change', async (file) => {
            if (file.startsWith(sourceDir))
                // run it again on change
                await main();
        })
    }
  };
}

export default app;

Please note this hooks API is experimental and likely to change soon:

probably to being able to add a hook via config directly (and simpler names like "build:start" instead of "app:build:start"