Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cloudflare pages adapter, alternate implementation #795

Merged
merged 3 commits into from
Jul 25, 2024

Conversation

rmarscher
Copy link
Contributor

@rmarscher rmarscher commented Jul 17, 2024

Here is an alternate attempt at Cloudflare Pages support. Related to #793.

  • In output-cloudflare.ts, it moves the outDir to a subdir named worker.js (a directory, not a file). It creates a dist/worker.js/index.js file to load the dist/worker.js/serve.js file.
  • It creates a _routes.json file in the root if one doesn't already exist from the publicDir and writes the publicDir entries to it.
  • It moves the publicDir to the root of the outDir.
  • It outputs an updated wrangler.toml if one doesn't exist with basic settings
  • It uses env.ASSETS.fetch to load a custom 404.html file.

Reference:

A waku plugin can be used to make wrangler dev server bindings available.

This could be bundled into waku or an external plugin... but it would want the developer to supply the wrangler version as a peer dependency. Cloudflare is constantly publishing wrangler and miniflare versions with new features. I published an example in a gist: https://gist.github.com/rmarscher/9bb6ed54dc9535f4b81bed147204c7e9

I published examples/10_fs-router to https://c03fa4b1.waku-test.pages.dev/

Thanks for waku! I'm looking forward to trying it on my cloudflare pages projects!

Copy link

vercel bot commented Jul 17, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
waku ✅ Ready (Inspect) Visit Preview Jul 25, 2024 2:24pm

Copy link

codesandbox-ci bot commented Jul 17, 2024

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@jkhaui
Copy link

jkhaui commented Jul 17, 2024

Maybe we just go with this PR - especially if it doesn't require setting the base path in waku config (I also just want to use Waku with pages asap haha)

Looks like significant effort has gone into getting a dev environment set up, look forward to trying it!

@rmarscher
Copy link
Contributor Author

rmarscher commented Jul 17, 2024

It seems like it would be helpful to add some docs about setting up wrangler dev server middleware and deploying to cloudflare. Maybe at the docs/builder/cloudflare.mdx location? Or maybe we should also add a new example with a cloudflare pages project that has an environment variable binding?

I used this to verify it works. In wrangler.toml:

[vars]
TEST_VAR = "Hello"

In a page component:

import { getEnv } from "waku"

const TestBindings = () => (
  <div>
    <p>TEST_VAR = {getEnv("TEST_VAR")}</p>
  </div>
)

export default TestBindings

Outputs TEST_VAR = Hello when I use waku dev

@rmarscher
Copy link
Contributor Author

rmarscher commented Jul 18, 2024

I can't get a build to work while my waku dev server middleware is in place without marking wrangler and miniflare as external in a custom vite.config.ts:

  ssr: {
    external: ["wrangler", "miniflare"],
  },

Everything works now for dev, build and deploy. I thought the dynamic import would get it to not be included when building, but it doesn't seem to be the case with the current build system.

@rmarscher
Copy link
Contributor Author

rmarscher commented Jul 18, 2024

We might want to document that dependencies with wasm files probably need to be added to optimizeDeps.exclude in a custom vite.config.ts. That will be a common pitfall.

@jkhaui
Copy link

jkhaui commented Jul 19, 2024

Everything works now for dev, build and deploy. I thought the dynamic import would get it to not be included when building, but it doesn't seem to be the case with the current build system.

Are you familiar with Vite and its bundling quirks? I've been trying to migrate an Astro React app to Waku and by far the biggest challenge I'm facing is lots of packages that work fine in Astro get tripped up with Waku's Vite setup.
I just can't work out why module resolution is behaving so differently despite the resolved Vite config for both projects looking fairly similar. E.g. wrangler never needs to be externalised when used in Astro via the CF adapter

(I realise this is getting way off-topic; just wanted to provide tangible examples of challenges with Vite. I might start a discussion on this.)

Here's another example: I want to use the lib @react-navigation/native so I can create my own mobile-centric router. The lib exports both ESM and CJS builds. In Astro, Vite automatically detects that there's something funky with the ESM build and defaults to using the CJS build (wrapped in an ESM loader). This works fine.
Waku, however, will try to load the ESM build and fails because some files use import paths without file extensions. The package version is also locked to be the same across both Astro & Waku projects

Would be great to hear if you've any insights regarding Waku's Vite internals

@rmarscher
Copy link
Contributor Author

rmarscher commented Jul 20, 2024

I reworked my dev server plugin to be in an external file and adjusted the dynamic importing in the waku.config.ts. That got it working without needing to externalize those packages in vite. I moved it to a gist rather than being pasted in the description of this issue. https://gist.github.com/rmarscher/9bb6ed54dc9535f4b81bed147204c7e9

I think the transition from CommonJS to ESM -- and different module resolution rules between versions of javascript, node and typescript -- has been one of the most painful things for the javascript ecosystem. It sounds like we need a separate issue or discussion to work out the problem building that package and others like it.

@rmarscher
Copy link
Contributor Author

Re: nodejs_compat. I have compatibility_flags = [ "nodejs_als" ] in my wrangler.toml. When I build the project and then run wrangler pages dev on the built dist folder, it gives a warning:

▲ [WARNING] The package "node:async_hooks" wasn't found on the file system but is built into node.

  Your Worker may throw errors at runtime unless you enable the "nodejs_compat" compatibility flag.
  Refer to https://developers.cloudflare.com/workers/runtime-apis/nodejs/ for more details. Imported
  from:
   - .wrangler/tmp/pages-4rx3No/waku-server.js
   - .wrangler/tmp/pages-4rx3No/rsdw-server.js

I found there's an open bug about fixing that warning - cloudflare/workers-sdk#6011

Comment on lines 68 to 73
// if (opts.serve === 'cloudflare') {
// viteConfig.build.rollupOptions.external.push(
// 'hono/cloudflare-workers',
// '__STATIC_CONTENT_MANIFEST',
// );
// }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simply remove it instead of commenting out. (or maybe it's WIP)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dai-shi Thank you. I forgot to remove the commented code once I confirmed it was no longer needed. I added another commit to this PR to remove it.

@@ -59,18 +59,18 @@ export function rscServePlugin(opts: {
opts.distPublic,
),
};
if (opts.serve === 'cloudflare' || opts.serve === 'partykit') {
if (opts.serve === 'partykit') {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@threepointone you might be interested in this PR, as you followed the previous cloudflare impl?

@threepointone
Copy link
Contributor

I'll have a look this week!

Copy link
Owner

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good to me.

We would like to have reviews from @jkhaui and @threepointone .

@jkhaui
Copy link

jkhaui commented Jul 24, 2024

The code looks good to me.

We would like to have reviews from @jkhaui and @threepointone .

At a glance, it looks good - I can see similar patterns used in Hono's Vite CFP plugin which gives confidence this is the right way!

I'll give it a proper review later today

@dai-shi dai-shi mentioned this pull request Jul 25, 2024
76 tasks
Copy link

@jkhaui jkhaui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice stuff! All looks to be working as expected, I just needed to create a wrangler.toml file in one of the example projects before deploying
image

Dev environment also looks good!

@@ -59,18 +59,18 @@ export function rscServePlugin(opts: {
opts.distPublic,
),
};
if (opts.serve === 'cloudflare' || opts.serve === 'partykit') {
if (opts.serve === 'partykit') {
viteConfig.build ||= {};
viteConfig.build.rollupOptions ||= {};
viteConfig.build.rollupOptions.external ||= [];
if (Array.isArray(viteConfig.build.rollupOptions.external)) {
viteConfig.build.rollupOptions.external.push('hono');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't hono still need to be externalised here for the CFP build? 🤔

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us know if we need it and we can have a follow-up PR.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fine without (didn't experience any build or dev issues without it)

Copy link
Contributor

@threepointone threepointone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks fine! Thank you

Copy link
Owner

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, guys. Let's merge.

Also, if there's room for improvement for partykit, feel free to send a PR.

@@ -59,18 +59,18 @@ export function rscServePlugin(opts: {
opts.distPublic,
),
};
if (opts.serve === 'cloudflare' || opts.serve === 'partykit') {
if (opts.serve === 'partykit') {
viteConfig.build ||= {};
viteConfig.build.rollupOptions ||= {};
viteConfig.build.rollupOptions.external ||= [];
if (Array.isArray(viteConfig.build.rollupOptions.external)) {
viteConfig.build.rollupOptions.external.push('hono');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us know if we need it and we can have a follow-up PR.

@dai-shi dai-shi merged commit 5fb414b into dai-shi:main Jul 25, 2024
28 checks passed
@Leechael
Copy link

Note to anyone attempting to deploy to Cloudflare Pages, use the command wrangler pages deploy.

npx wrangler pages deploy

Although it is not mentioned in the PR and document, it does work.

@dai-shi
Copy link
Owner

dai-shi commented Jul 27, 2024

Can anyone update README?

@jkhaui
Copy link

jkhaui commented Jul 28, 2024

Can anyone update README?

Sure. Shall I open a PR?

@dai-shi
Copy link
Owner

dai-shi commented Jul 28, 2024

Yes.

@geelen
Copy link

geelen commented Aug 7, 2024

Just playing with Waku today, was initially quite surprised it wasn't defaulting to Cloudflare Pages. Then, I found this PR, upgraded Waku to 0.21.0-beta.3 and reran pnpm build --with-cloudflare and then pnpm wrangler pages deploy and boom, that worked!

So thanks for shipping this, Pages gives a much better experience at the moment 🙏

@dai-shi
Copy link
Owner

dai-shi commented Aug 28, 2024

Can anyone update README?

Sure. Shall I open a PR?

@jkhaui I forgot about this. Waiting for your PR.

@dai-shi
Copy link
Owner

dai-shi commented Sep 9, 2024

78a5503 is this correct and enough?

@dai-shi
Copy link
Owner

dai-shi commented Sep 9, 2024

Can anyone help #869?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants