honojs / vite-plugins

Vite Plugins for Hono
https://hono.dev
134 stars 35 forks source link

`c.env.ASSETS` is `undefined` in dev server #17

Closed yudai-nkt closed 1 year ago

yudai-nkt commented 1 year ago

I'm migrating one of my projects from Workers Site to Pages with Functions, and having trouble with env.ASSETS.fetch. With the following setup (I'll publish a reproduction repo later), GET / returns a 500 error saying TypeError: Cannot read properties of undefined (reading 'fetch') during dev server (i.e., wrangler pages dev -- vite).

// src/index.ts
import { Hono } from "hono";

const app = new Hono().get("/", async (c) => {
  const env = c.env as { ASSETS: { fetch: typeof fetch } };
  const asset = await env.ASSETS.fetch(
    new URL("/assets/static.json", c.req.url)
  ).then((r) => r.json());
  return c.json({ asset });
});

export default app;
// public/assets/static.json
{
  "foo": "Hello world",
  "bar": 42
}
// public/_routes.json
{
  "version": 1,
  "include": ["/*"],
  "exclude": ["/assets/*"]
}
// vite.config.ts
import { type UserConfig } from "vite";
import pages from "@hono/vite-cloudflare-pages";
import devServer, { defaultOptions } from "@hono/vite-dev-server";

export default {
  plugins: [
    pages(),
    devServer({
      exclude: [...defaultOptions.exclude, /^\/assets\/.+/],
    }),
  ],
} satisfies UserConfig;

After building with vite build, however, GET / returns the expected {"asset":{"foo":"Hello world","bar":42}} during preview server with wrangler pages dev dist. So how can I bind env.ASSETS.fetch to Hono's context in dev mode? If it's already possible, a small documentation would be much appreciated (I tried to find relevant options in the two plugins but wasn't successful unfortunately)

yudai-nkt commented 1 year ago

Repro is available at https://github.com/yudai-nkt/hono-vite-plugin-with-env-assets.

yusukebe commented 1 year ago

Hi @yudai-nkt,

Unfortunately, you can't use env.ASSETS.fetch with the dev-server in Vite. I thought it wouldn't be a problem because we have the /public directory to serve asset files.

I believe the reason you want to use env.ASSETS.fetch is because you want to retrieve the content from JSON or some files using c.env.ASSET.fetch. Is that correct? Indeed, though it's a rare need, it might arise. However, I think we can't accomplish this with env.ASSETS.fetch.

This is a limitation of Cloudflare Pages. Our Cloudflare team is also contemplating the fact that "Workers/Pages don't have a file system now".

I hope we find a good workaround, but I don't have one at the moment. Do you have any good ideas?

yudai-nkt commented 1 year ago

Yes, /pubic should be enough for most cases and I'm aware I'm in a rare situation. I want to use the static assets in a different endpoint, so I need to env.ASSET.fetch those assets.

I tried the global fetch, but it throws another error Error: Could not proxy request: TypeError: fetch failed. I'll keep investigating to see if there are any workaround.