From 5d9499fe76cbfe6a7e398b5b47a95d7a229a094e Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:28:14 +0530 Subject: [PATCH 1/9] (feat): deep support for `server.baseURL` API from nitro in dev & prod, fixes [Bug?]: Router "base" property is flaky solidjs/solid-start#1158 #55 --- examples/solid/ssr/basic/app/app.tsx | 2 +- packages/vinxi/lib/app.js | 4 +- packages/vinxi/lib/dev-server.js | 9 ++-- .../vinxi/lib/manifest/dev-server-manifest.js | 12 +++-- .../lib/manifest/prod-server-manifest.js | 50 ++++++++++++------- packages/vinxi/lib/nitro-dev.js | 5 +- packages/vinxi/lib/plugins/manifest.js | 7 +++ 7 files changed, 59 insertions(+), 30 deletions(-) diff --git a/examples/solid/ssr/basic/app/app.tsx b/examples/solid/ssr/basic/app/app.tsx index 9739c0b6..5f9a8f11 100644 --- a/examples/solid/ssr/basic/app/app.tsx +++ b/examples/solid/ssr/basic/app/app.tsx @@ -6,7 +6,7 @@ export default function App({ assets, scripts }) { return ( - + {assets} diff --git a/packages/vinxi/lib/app.js b/packages/vinxi/lib/app.js index 4293cfa9..8dbc28e7 100644 --- a/packages/vinxi/lib/app.js +++ b/packages/vinxi/lib/app.js @@ -12,7 +12,9 @@ import { resolveRouterConfig, routerSchema } from "./router-modes.js"; routers?: import("./router-modes.js").RouterSchemaInput[]; name?: string; - server?: import('nitropack').NitroConfig; + server?: import('nitropack').NitroConfig & { + baseURL?: string; + }; root?: string }} AppOptions */ diff --git a/packages/vinxi/lib/dev-server.js b/packages/vinxi/lib/dev-server.js index 9fa99fe1..b66d3abe 100644 --- a/packages/vinxi/lib/dev-server.js +++ b/packages/vinxi/lib/dev-server.js @@ -3,7 +3,7 @@ import { inspect } from "@vinxi/devtools"; import { fileURLToPath } from "node:url"; import { consola, withLogger } from "./logger.js"; -import { normalize } from "./path.js"; +import { join, normalize } from "./path.js"; export * from "./router-dev-plugins.js"; @@ -57,9 +57,12 @@ export async function createViteHandler(router, app, serveConfig) { ...(((await router.plugins?.(router)) ?? []).filter(Boolean) || []), ].filter(Boolean); + let base = join(app.config.server.baseURL ?? "/", router.base); + + console.log(base); const viteDevServer = await createViteDevServer({ configFile: false, - base: router.base, + base, plugins, optimizeDeps: { force: serveConfig.force, @@ -122,7 +125,7 @@ export async function createDevServer( publicAssets: [ ...app.config.routers .map((router) => { - return router.internals.mode.dev.publicAssets?.(router, app.config); + return router.internals.mode.dev.publicAssets?.(router, app); }) .filter( /** diff --git a/packages/vinxi/lib/manifest/dev-server-manifest.js b/packages/vinxi/lib/manifest/dev-server-manifest.js index 145a9c4a..28d5e844 100644 --- a/packages/vinxi/lib/manifest/dev-server-manifest.js +++ b/packages/vinxi/lib/manifest/dev-server-manifest.js @@ -16,6 +16,8 @@ export function createDevManifest(app) { let router = app.getRouter(bundlerName); + let base = join(app.config.server.baseURL ?? "", router.base); + if (router.mode === "static") { return { json() { @@ -27,7 +29,7 @@ export function createDevManifest(app) { routes() { return []; }, - base: router.base, + base, target: "static", mode: router.mode, handler: undefined, @@ -64,7 +66,7 @@ export function createDevManifest(app) { return {}; }, handler: router.handler, - base: router.base, + base, target: router.target, mode: router.mode, chunks: new Proxy( @@ -83,7 +85,7 @@ export function createDevManifest(app) { if (router.target === "browser") { return { output: { - path: join(router.base, "@fs", absolutePath), + path: join(base, "@fs", absolutePath), }, }; } else { @@ -234,7 +236,7 @@ export function createDevManifest(app) { attrs: { key: "vite-client", type: "module", - src: join(router.base, "@vite", "client"), + src: join(base, "@vite", "client"), }, }, ] @@ -242,7 +244,7 @@ export function createDevManifest(app) { ].filter(Boolean); }, output: { - path: join(router.base, "@fs", absolutePath), + path: join(base, "@fs", absolutePath), }, }; } else { diff --git a/packages/vinxi/lib/manifest/prod-server-manifest.js b/packages/vinxi/lib/manifest/prod-server-manifest.js index 8719450b..e24a5c1b 100644 --- a/packages/vinxi/lib/manifest/prod-server-manifest.js +++ b/packages/vinxi/lib/manifest/prod-server-manifest.js @@ -1,3 +1,4 @@ +import { joinURL } from "ufo"; import invariant from "vinxi/lib/invariant"; import { handlerModule, join, virtualId } from "vinxi/lib/path"; @@ -7,21 +8,19 @@ import findAssetsInViteManifest from "./vite-manifest.js"; /** @typedef {import("../app.js").App & { config: { buildManifest: { [key:string]: any } }}} ProdApp */ -function createHtmlTagsForAssets(router, assets) { - return assets.filter( - (asset) => - asset.endsWith(".css") || asset.endsWith(".js"), - ) - .map((asset) => ({ - tag: "link", - attrs: { - href: join(router.base, asset), - key: join(router.base, asset), - ...(asset.endsWith(".css") - ? { rel: "stylesheet", precendence: "high" } - : { rel: "modulepreload" }), - }, - })); +function createHtmlTagsForAssets(router, app, assets) { + return assets + .filter((asset) => asset.endsWith(".css") || asset.endsWith(".js")) + .map((asset) => ({ + tag: "link", + attrs: { + href: joinURL(app.config.server.baseURL ?? "", router.base, asset), + key: join(app.config.server.baseURL ?? "", router.base, asset), + ...(asset.endsWith(".css") + ? { rel: "stylesheet", precendence: "high" } + : { rel: "modulepreload" }), + }, + })); } /** @@ -121,7 +120,11 @@ export function createProdManifest(app) { : input; return { assets() { - return createHtmlTagsForAssets(router, findAssetsInViteManifest(bundlerManifest, id)); + return createHtmlTagsForAssets( + router, + app, + findAssetsInViteManifest(bundlerManifest, id), + ); }, output: { path: join( @@ -139,17 +142,26 @@ export function createProdManifest(app) { return { import() { return import( - /* @vite-ignore */ join( + /* @vite-ignore */ joinURL( + app.config.server.baseURL ?? "", router.base, bundlerManifest[id].file, ) ); }, assets() { - return createHtmlTagsForAssets(router, findAssetsInViteManifest(bundlerManifest, id)); + return createHtmlTagsForAssets( + router, + app, + findAssetsInViteManifest(bundlerManifest, id), + ); }, output: { - path: join(router.base, bundlerManifest[id].file), + path: joinURL( + app.config.server.baseURL ?? "", + router.base, + bundlerManifest[id].file, + ), }, }; } diff --git a/packages/vinxi/lib/nitro-dev.js b/packages/vinxi/lib/nitro-dev.js index a817dbe5..5980d657 100644 --- a/packages/vinxi/lib/nitro-dev.js +++ b/packages/vinxi/lib/nitro-dev.js @@ -168,7 +168,10 @@ export function createDevServer(nitro) { // Dev-only handlers for (const handler of nitro.options.devHandlers) { - app.use(handler.route || "/", handler.handler); + app.use( + joinURL(nitro.options.runtimeConfig.app.baseURL, handler.route ?? "/"), + handler.handler, + ); } // User defined dev proxy diff --git a/packages/vinxi/lib/plugins/manifest.js b/packages/vinxi/lib/plugins/manifest.js index 271fcda1..143e2cac 100644 --- a/packages/vinxi/lib/plugins/manifest.js +++ b/packages/vinxi/lib/plugins/manifest.js @@ -29,6 +29,9 @@ export function manifest() { "import.meta.env.ROUTER_NAME": JSON.stringify(router.name), "import.meta.env.ROUTER_HANDLER": JSON.stringify(router.handler), "import.meta.env.CWD": JSON.stringify(router.root), + "import.meta.env.APP_BASE_URL": JSON.stringify( + app.config.server.baseURL ?? "", + ), "import.meta.env.ROUTERS": JSON.stringify( app.config.routers.map((router) => router.name), ), @@ -67,10 +70,13 @@ export function manifest() { export function injectVinxiClient() { /** @type {import('../router-mode.js').Router} */ let router; + /** @type {import('../app.js').App} */ + let app; return { name: "vinxi:inject-client-runtime", configResolved(config) { router = config.router; + app = config.app; }, apply: "serve", transformIndexHtml(html) { @@ -80,6 +86,7 @@ export function injectVinxiClient() { attrs: { type: "module", src: join( + app.config.server.baseURL ?? "", router.base, "@fs", `${fileURLToPath( From 5fe413122d76523659fc188e8a202958da8e6f7b Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:28:43 +0530 Subject: [PATCH 2/9] Create shy-comics-crash.md --- .changeset/shy-comics-crash.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/shy-comics-crash.md diff --git a/.changeset/shy-comics-crash.md b/.changeset/shy-comics-crash.md new file mode 100644 index 00000000..c899e16d --- /dev/null +++ b/.changeset/shy-comics-crash.md @@ -0,0 +1,6 @@ +--- +"vinxi": patch +"solid-ssr-basic": patch +--- + +(feat): deep support for `server.baseURL` API from nitro in dev & prod, From 633b15b2297eadcc068811bee560924bc95c134c Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:30:23 +0530 Subject: [PATCH 3/9] change APP_BASE_URL to SERVER_BASE_URL (to match the config name) --- packages/vinxi/lib/plugins/manifest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vinxi/lib/plugins/manifest.js b/packages/vinxi/lib/plugins/manifest.js index 143e2cac..68aba71c 100644 --- a/packages/vinxi/lib/plugins/manifest.js +++ b/packages/vinxi/lib/plugins/manifest.js @@ -29,7 +29,7 @@ export function manifest() { "import.meta.env.ROUTER_NAME": JSON.stringify(router.name), "import.meta.env.ROUTER_HANDLER": JSON.stringify(router.handler), "import.meta.env.CWD": JSON.stringify(router.root), - "import.meta.env.APP_BASE_URL": JSON.stringify( + "import.meta.env.SERVER_BASE_URL": JSON.stringify( app.config.server.baseURL ?? "", ), "import.meta.env.ROUTERS": JSON.stringify( From f643e117a9c82bc41fc7ec32350ab06435b966c8 Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:30:38 +0530 Subject: [PATCH 4/9] fix server-functions runtime to account for this --- packages/vinxi-server-functions/client-runtime.js | 10 ++++++++-- packages/vinxi-server-functions/server-runtime.js | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/vinxi-server-functions/client-runtime.js b/packages/vinxi-server-functions/client-runtime.js index 82ab62eb..97d3c555 100644 --- a/packages/vinxi-server-functions/client-runtime.js +++ b/packages/vinxi-server-functions/client-runtime.js @@ -15,13 +15,19 @@ export function createServerReference(fn, id, name) { return new Proxy(fn, { get(target, prop, receiver) { if (prop === "url") { - return "/_server" + `id=${id}&name=${name}`; + return ( + import.meta.env.SERVER_BASE_URL + "/_server" + `id=${id}&name=${name}` + ); } return Reflect.get(target, prop, receiver); }, apply(target, thisArg, args) { - return fetchServerAction("/_server", `${id}#${name}`, args); + return fetchServerAction( + `${import.meta.env.SERVER_BASE_URL}/_server`, + `${id}#${name}`, + args, + ); }, }); } diff --git a/packages/vinxi-server-functions/server-runtime.js b/packages/vinxi-server-functions/server-runtime.js index bc0953cd..60538b7f 100644 --- a/packages/vinxi-server-functions/server-runtime.js +++ b/packages/vinxi-server-functions/server-runtime.js @@ -2,7 +2,9 @@ export function createServerReference(fn, id, name) { return new Proxy(fn, { get(target, prop, receiver) { if (prop === "url") { - return "/_server" + `id=${id}&name=${name}`; + return ( + import.meta.env.SERVER_BASE_URL + "/_server" + `id=${id}&name=${name}` + ); } return Reflect.get(target, prop, receiver); From 2100a98bf2dca4415eca9d9877e4e389ef75c5b5 Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:30:50 +0530 Subject: [PATCH 5/9] fix example --- examples/solid/ssr/basic/app/app.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/solid/ssr/basic/app/app.tsx b/examples/solid/ssr/basic/app/app.tsx index 5f9a8f11..3067a79c 100644 --- a/examples/solid/ssr/basic/app/app.tsx +++ b/examples/solid/ssr/basic/app/app.tsx @@ -6,7 +6,10 @@ export default function App({ assets, scripts }) { return ( - + {assets} From 2045edd2c1c0dade31ba41adc05225e974b8fc23 Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:31:24 +0530 Subject: [PATCH 6/9] fix rsc example base url --- examples/react/rsc/spa/app/client.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/react/rsc/spa/app/client.tsx b/examples/react/rsc/spa/app/client.tsx index ba2063da..9d5990a2 100644 --- a/examples/react/rsc/spa/app/client.tsx +++ b/examples/react/rsc/spa/app/client.tsx @@ -11,7 +11,11 @@ import { ServerComponent } from "./server-component"; document.addEventListener("click", async (e) => { console.log(sayHello, "hello"); - const result = await fetchServerAction("/_server", sayHello["$$id"], []); + const result = await fetchServerAction( + import.meta.env.SERVER_BASE_URL + "/_server", + sayHello["$$id"], + [], + ); console.log(result); // sayHello(); }); From c5a94cfad4f292feb0b976fd6d722b204fe7acfa Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:31:54 +0530 Subject: [PATCH 7/9] Create early-pumas-pump.md --- .changeset/early-pumas-pump.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/early-pumas-pump.md diff --git a/.changeset/early-pumas-pump.md b/.changeset/early-pumas-pump.md new file mode 100644 index 00000000..7f90064b --- /dev/null +++ b/.changeset/early-pumas-pump.md @@ -0,0 +1,7 @@ +--- +"@vinxi/server-functions": patch +"vinxi": patch +"solid-ssr-basic": patch +--- + +(feat): deep support for `server.baseURL` API from nitro in dev & prod, From 099f76e1b8f12a559875eb31cac50c8e7d1b7c57 Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:32:30 +0530 Subject: [PATCH 8/9] remove duplicate changeset --- .changeset/shy-comics-crash.md | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .changeset/shy-comics-crash.md diff --git a/.changeset/shy-comics-crash.md b/.changeset/shy-comics-crash.md deleted file mode 100644 index c899e16d..00000000 --- a/.changeset/shy-comics-crash.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"vinxi": patch -"solid-ssr-basic": patch ---- - -(feat): deep support for `server.baseURL` API from nitro in dev & prod, From 1cf96cd8ffc59955a7d0ea9a745e6d003c047505 Mon Sep 17 00:00:00 2001 From: Nikhil Saraf Date: Thu, 28 Dec 2023 02:56:04 +0530 Subject: [PATCH 9/9] fix types to only expose options that will work properly right now --- packages/vinxi/lib/app.js | 6 ++---- packages/vinxi/lib/build.js | 1 + packages/vinxi/lib/plugins/config.js | 2 +- packages/vinxi/lib/vite-dev.d.ts | 25 ++++++++++++++++++++++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/vinxi/lib/app.js b/packages/vinxi/lib/app.js index 8dbc28e7..92d8cecc 100644 --- a/packages/vinxi/lib/app.js +++ b/packages/vinxi/lib/app.js @@ -12,9 +12,7 @@ import { resolveRouterConfig, routerSchema } from "./router-modes.js"; routers?: import("./router-modes.js").RouterSchemaInput[]; name?: string; - server?: import('nitropack').NitroConfig & { - baseURL?: string; - }; + server?: Omit; root?: string }} AppOptions */ @@ -22,7 +20,7 @@ import { resolveRouterConfig, routerSchema } from "./router-modes.js"; config: { name: string; devtools: boolean; - server: import("nitropack").NitroConfig; + server: Omit; routers: import("./router-mode.js").Router[]; root: string; }; diff --git a/packages/vinxi/lib/build.js b/packages/vinxi/lib/build.js index 1a7cdb78..c2722c4a 100644 --- a/packages/vinxi/lib/build.js +++ b/packages/vinxi/lib/build.js @@ -83,6 +83,7 @@ export async function createBuild(app, buildConfig) { "node-fetch-native/polyfill": require.resolve( "node-fetch-native/polyfill", ), + ...(app.config.server.alias ?? {}), // "unstorage/drivers/fs-lite": require.resolve("unstorage/drivers/fs-lite"), // "unstorage/drivers/fs": require.resolve("unstorage/drivers/fs"), // defu: require.resolve("defu"), diff --git a/packages/vinxi/lib/plugins/config.js b/packages/vinxi/lib/plugins/config.js index b9cc8935..93e6af2c 100644 --- a/packages/vinxi/lib/plugins/config.js +++ b/packages/vinxi/lib/plugins/config.js @@ -1,7 +1,7 @@ /** * * @param {string} tag - * @param {Omit} conf + * @param {import('../vite-dev.d.ts').CustomizableConfig} conf * @returns {import('../vite-dev.d.ts').Plugin} */ export function config(tag, conf) { diff --git a/packages/vinxi/lib/vite-dev.d.ts b/packages/vinxi/lib/vite-dev.d.ts index 97097684..a27f1bca 100644 --- a/packages/vinxi/lib/vite-dev.d.ts +++ b/packages/vinxi/lib/vite-dev.d.ts @@ -1,8 +1,8 @@ import { Plugin as VitePlugin, ResolvedConfig as _ResolvedConfig } from "vite"; import { App } from "./app.js"; -import { Router } from "./router-mode.js"; import { DevConfig } from "./dev-server.js"; +import { Router } from "./router-mode.js"; declare module "vite" { interface UserConfig { @@ -28,4 +28,27 @@ export type ViteConfig = _ResolvedConfig & { router: Router; app: App }; export type Plugin = VitePlugin; +export type CustomizableConfig = Omit< + import("vite").InlineConfig, + | "appType" + | "app" + | "router" + | "base" + | "root" + | "publicDir" + | "mode" + | "server" + | "preview" + | "clearScreen" + | "configFile" + | "envFile" +> & { + build?: Omit< + import("vite").InlineConfig["build"], + "outDir" | "ssr" | "ssrManifest" | "rollupOptions" + > & { + rollupOptions?: Omit; + }; +}; + export type { ConfigEnv as ConfigEnv } from "vite";