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

deno-esbuild: Deno Deploy support #2336

Closed
ayoreis opened this issue Jun 21, 2022 · 6 comments
Closed

deno-esbuild: Deno Deploy support #2336

ayoreis opened this issue Jun 21, 2022 · 6 comments

Comments

@ayoreis
Copy link

ayoreis commented Jun 21, 2022

Deno Deploy is an edge runtime by Deno. And it would be awesome to use esbuild with it, but when I try to run this code:

import * as esbuild from "https://deno.land/x/esbuild@v0.14.45/mod.js";
const ts = 'let test: boolean = true'
const result = await esbuild.transform(ts, { loader: 'ts' })
console.log('result:', result)
esbuild.stop()

It gives me this error:

Error: Failed to find cache directory
    at getCachePath (https://deno.land/x/esbuild@v0.14.45/mod.js:1759:11)
    at installFromNPM (https://deno.land/x/esbuild@v0.14.45/mod.js:1713:35)
    at install (https://deno.land/x/esbuild@v0.14.45/mod.js:1802:18)
    at https://deno.land/x/esbuild@v0.14.45/mod.js:1813:29
    at ensureServiceIsRunning (https://deno.land/x/esbuild@v0.14.45/mod.js:1941:7)
    at Module.transform (https://deno.land/x/esbuild@v0.14.45/mod.js:1679:37)
    at file:///src/main.tsx:8:30

I don't get the error right now, but I can try to find the problem and then propose a fix.

@evanw
Copy link
Owner

evanw commented Jun 21, 2022

You can read the source code here:

esbuild/lib/deno/mod.ts

Lines 83 to 117 in 20f4b45

function getCachePath(name: string): { finalPath: string, finalDir: string } {
let baseDir: string | undefined
switch (Deno.build.os) {
case 'darwin':
baseDir = Deno.env.get('HOME')
if (baseDir) baseDir += '/Library/Caches'
break
case 'windows':
baseDir = Deno.env.get('LOCALAPPDATA')
if (!baseDir) {
baseDir = Deno.env.get('USERPROFILE')
if (baseDir) baseDir += '/AppData/Local'
}
if (baseDir) baseDir += '/Cache'
break
case 'linux':
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
const xdg = Deno.env.get('XDG_CACHE_HOME')
if (xdg && xdg[0] === '/') baseDir = xdg
break
}
if (!baseDir) {
baseDir = Deno.env.get('HOME')
if (baseDir) baseDir += '/.cache'
}
if (!baseDir) throw new Error('Failed to find cache directory')
const finalDir = baseDir + `/esbuild/bin`
const finalPath = finalDir + `/${name}@${version}`
return { finalPath, finalDir }
}

This will fail on Linux if certain environment variables aren't set. I don't use Deno and know nothing about it so I can't help you, sorry.

@ayoreis
Copy link
Author

ayoreis commented Jun 27, 2022

Thanks for your reply @evanw ❤️. I'll look into this soon.

@evanw
Copy link
Owner

evanw commented Jun 30, 2022

BTW if you are ok with using WebAssembly instead of native, then you can try that when the next version of esbuild is released soon. See #2323 which was just fixed.

@evanw
Copy link
Owner

evanw commented Jul 6, 2022

Marking as unactionable until more information is provided.

@ayoreis
Copy link
Author

ayoreis commented Jul 6, 2022

Update: Deno Deploy does not support Deno.writeFile nor Deno.run (at least yet). That's what's causing the errors, the best option right now is using WebAssembly as you sugested, though its not enough for my use case where I need building.

So my proposal is that we make build available in the WebAssembly version and get files with fetch(new URL('./path/to.file')).text() / the user being required to write a plugin that would resolve all the files by itself.

This would allow building in Deno Deploy 🦕, and in the browser 🌐! You mentioned in #2323 that to get this working it would require additional work, so I am not expecting this to happen and just proposing it. Maybe I could even learn Go and do it myself.

And maybe esbuild switching automatically to WebAssembly in Deno Deploy, but I don't think that's necessary since you can just check for the existence of Deno.run and fallback to WebAssembly.

What do you think? Do I write a new issue for this?

@evanw
Copy link
Owner

evanw commented Jul 10, 2022

I'm confused. The build API already works. Here's an example:

import * as esbuild from 'https://deno.land/x/esbuild@v0.14.48/wasm.js'
const result = await esbuild.build({
  stdin: {
    contents: `
      import x from 'fib(10)'
      console.log('fib(10) is', x)
    `,
  },
  bundle: true,
  plugins: [{
    name: 'some-plugin',
    setup(build) {
      build.onResolve({ filter: /^fib\((\d+)\)/ }, args => {
        return { path: args.path, namespace: 'fib' }
      })
      build.onLoad({ filter: /^fib\((\d+)\)/, namespace: 'fib' }, args => {
        let match = /^fib\((\d+)\)/.exec(args.path), n = +match[1]
        let contents = n < 2 ? `export default ${n}` : `
          import n1 from 'fib(${n - 1}) ${args.path}'
          import n2 from 'fib(${n - 2}) ${args.path}'
          export default n1 + n2`
        return { contents }
      })
    },
  }],
})
eval(result.outputFiles[0].text)
Deno.exit(0)

That should print this:

fib(10) is 55

You'll need to use an esbuild plugin to avoid the file system if Deno Deploy doesn't have a file system, but there should be nothing preventing you from using esbuild in that case. I'm not planning on testing esbuild with Deno Deploy myself because it's a closed service so it'll be up to you to figure out how to write the plugin you need for this. I'm closing this issue since esbuild's current WebAssembly implementation should be sufficient for this.

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

No branches or pull requests

2 participants