Open riderx opened 10 months ago
Yep, Deno's npm:
specifiers are not supported, as they are not supported by deno bundle
- and we need to bundle into a single js for Cloudflare
As deno bundle
is now deprecated, are there plans to switch to an alternative bundler, eg deno_emit, or esbuild?
Yes, deno_emit
has never worked well, experimented in denoflare using --bundle backend=module
I imagine esbuild + esbuild_deno_loader will be the most full-featured solution.
I miss Deno.emit
, and soon deno bundle
: (
I have personally changed completely my stack. Now in deno I use import map so my import look like npm one. I did install only npm and deno compatible packages. And then used hono to have a server who work in both envs the same.
now the only difference is the root file who is different for cloudflare and deno.
That it, no more build step to transform anything.
i believe in the future with winterjs this will become more and more easy.
my code is open source so you see it here: https://github.com/Cap-go/capgo/blob/main/cloudflare_workers/index.ts
it’s deployed in supabase edge (deno) Cloudflare workers and Netlify (nodejs)
If it's any help I have a script that uses esbuild and esbuild-deno-loader (to build a service worker for the browser, but that's not so relevant), and it seems to work with both npm:
and the new jsr:
imports... https://github.com/jollytoad/home/blob/main/scripts/build.ts
(For context, I'm here because, I was curious to see if I could also deploy my site to Cloudflare too using denoflare, but after migrating to npm:
(from esm.sh) and jsr:
, it's seem not)
Do you think it'd be possible to have a bring-your-own-bundler feature in denoflare?
Denoflare supports Cloudflare wasm/text/binary imports with their non-standard syntax using some post-bundling transformations - these would be tricky to do in general, but sure an escape hatch where you could DIY would be interesting and allow for fast experimentation if those aren't used.
It would need to work with the cli, so maybe a pointer to a module that supports a simple bundle interface?
Is it possible to wrap some features with dynamic imports to build around this? Seems like the bundler sees node:
or npm:
anywhere in the code and panics prematurely. Now the code has to be patched to remove the references exclusively for this one use case unless I'm missing something?
I may have some time today to look into an esbuild-based bundler option. @Granitosaurus do you have a sample worker I could use as a validation test?
If it's any help I've just recently got my Deno Deploy site to build for Cloudflare Pages, I had to jump through a fair amount of hoops. It seems Cloudflare doesn't support import.meta.*, so I had to do some code transforms first and then bundle with esbuild. (esbuild doesn't have any option transpile import.meta.url/resolve either)
Transform stuff: https://github.com/jollytoad/home/blob/main/scripts/build_cloudflare.ts#L57 Bundle: https://github.com/jollytoad/home/blob/main/scripts/build_cloudflare.ts#L130
With this, I end up with a bundled _worker.js
along with a folder of assets for deploying to Cloudflare Pages.
hey @johnspurlock-skymethod thanks for the reply. Here's the minimal example that got me stumped:
// mod.ts
export class MyClass {
constructor() {
console.log("MyClass constructor");
}
async selector() {
// dynamically import npm: package, in real use it would throw an error if called through unsupported environment like cf
const cheerio = await import("npm:cheerio");
return cheerio.load("<h2 class='title'>Hello world</h2>")("h2").text();
}
}
and when serving through denoflare's index.ts
it immediately throws error that npm specifiers have not yet been implemented
:
// index.ts
import { MyClass } from "./mod.ts"
export default {
async fetch(request: Request, env: any) {
try {
// Nothing from the package is even used, just imported
// const foo = new MyClass();
return new Response("success")
} catch (e) {
return new Response(e.message)
}
},
}
I guess this is Typescript being overly safe here and prematurely breaking but maybe there's a way to tell it to shut up about it?
My goal is to get my package running on cf worker even if some methods that require npm:
dependencies are not available and the only way rn it seems is to build out a different version of the package with these methods replaced 🤔
@ Granitosaurus thanks - couple of notes on that sample.
await import("npm:cheerio" + "");
will prevent Deno from checking it.
This will still fail at runtime on cloudflare though (no npm:cheerio module
)
import cheerio from 'https://cdn.skypack.dev/cheerio@1.0.0-rc.12?dts';
export class MyClass {
constructor() {
console.log("MyClass constructor");
}
async selector() {
// works in local denoflare serve and when pushed to cf with denoflare push
return cheerio.load("<h2 class='title'>Hello world</h2>")("h2").text();
}
}
running on cloudflare here: https://cheerio.sw.workers.dev/
Ok introduced a proof of concept esbuild backend in https://github.com/skymethod/denoflare/commit/827d5b1faebf233f4edd434de7fec7d9f1086483
Install denoflare as of this commit or greater to try it out.
Can use it with a --bundle backend=esbuild
option to either denoflare serve
or denoflare push
.
Imports the esbuild stuff dynamically right now so doesn't bloat denoflare if never used.
Defaults to the native
loader (which requires --allow-run
), can use the portable
(wasm) loader with a --bundle loader=portable
option to either denoflare serve
or denoflare push
.
Since neither esbuild nor the esbuild deno loader does type checking, this backend doesn't do any type checking at all yet, I guess we'll need to shell out to deno check
to bring this to the same usefulness level as deno bundle
hey @johnspurlock-skymethod I've tested the new esbuild backend and it works great with my npm:cheerio
dependency:
import * as cheerio from 'npm:cheerio@1.0.0-rc.12'
Thanks for clarifying everything!
Great, glad to hear it
Now the esbuild backend is type-checking (via deno check
under the hood) by default as of https://github.com/skymethod/denoflare/commit/ea757ffb39ed87a282f22f7cdd88f5b17bc97b1d
Can control the check level using the same option as the other backends: --bundle check=(all|local|none)
Also added two other optional bundle options for specifying the versions of the esbuild module and esbuild-deno-loader used under the hood
--bundle loaderModule=(jsr-spec|url)
(defaults to ^0.10.3
)
This is the version of the esbuild-deno-loader to use, you can specify a version spec for the canonical module, or provide a full url to a fork etc
--bundle esbuildModule=(version|url)
(defaults to 0.23.0
)
This is the version of the esbuild module to use, you can specify a version for the deno/x repo, or provide a full url to a fork etc
If i change one import in my codebase to the new syntax for npm specifier in Deno. Like below: I get this error on the deploy step: it seems it's not supported