adoublef
adoublef10mo ago

Deploy says Worker not defined for ESBuild (wasm.js)

@Deno AI Helper I am having trouble understanding how to get the esbuilder to work on Deno Deploy, using write: false here is what my conifg looks like currently
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
// @ts-ignore been updated to v0.19.2
plugins: [...denoPlugins()],
});

console.log(result.outputFiles)
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
// @ts-ignore been updated to v0.19.2
plugins: [...denoPlugins()],
});

console.log(result.outputFiles)
The error seems to suggest that the Worker is not defined even though I am using the wasm version of esbuild@v0.19.2
8 Replies
Deno AI Helper
Deno AI Helper10mo ago
Based on the documentation, Deno supports the Web Worker API, which allows you to run code on multiple threads. Each instance of Worker is run on a separate thread, dedicated only to that worker. However, there are some important points to note: 1. Deno supports only module type workers. Therefore, it's essential to pass the type: "module" option when creating a new worker. 2. Workers currently do not work in compiled executables. 3. Use of relative module specifiers in the main worker are only supported with --location <href> passed on the CLI. This is not recommended for portability. You can instead use the URL constructor and import.meta.url to easily create a specifier for some nearby script. Here is an example of how to correctly create a worker in Deno:
new Worker(new URL("./worker.js", import.meta.url).href, { type: "module" });
new Worker(new URL("./worker.js", import.meta.url).href, { type: "module" });
If you're trying to use the Worker in your code and it's not defined, it might be because you're not creating it correctly or not passing the correct options when creating it. As for the write: false option in your esbuild configuration, it's not clear how this is related to the Worker issue. The write: false option tells esbuild to not write the output files to disk, but instead return them in the result object. This should not affect the availability of the Worker API. If you're still having issues, could you provide more details about where and how you're using the Worker in your code? That would help in providing a more accurate solution. 🦕
adoublef
adoublef10mo ago
@Deno AI Helper can you give an example of how to use the worker along with esbuild?
Deno AI Helper
Deno AI Helper10mo ago
Sure, here's an example of how you might use a worker with esbuild in Deno. First, let's create a worker file named worker.ts:
// worker.ts
self.onmessage = async (e) => {
const { code } = e.data;
const result = await someTransformFunction(code); // Replace this with actual transformation logic
self.postMessage(result);
};
// worker.ts
self.onmessage = async (e) => {
const { code } = e.data;
const result = await someTransformFunction(code); // Replace this with actual transformation logic
self.postMessage(result);
};
Then, in your main file, you can create a new worker and use it to transform your code:
// main.ts
import * as esbuild from "https://deno.land/x/esbuild_wasm/mod.ts";

const worker = new Worker(new URL("./worker.ts", import.meta.url).href, { type: "module" });

worker.onmessage = (e) => {
console.log("Transformed code:", e.data);
};

const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
});

worker.postMessage({ code: result.outputFiles[0].text });
// main.ts
import * as esbuild from "https://deno.land/x/esbuild_wasm/mod.ts";

const worker = new Worker(new URL("./worker.ts", import.meta.url).href, { type: "module" });

worker.onmessage = (e) => {
console.log("Transformed code:", e.data);
};

const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
});

worker.postMessage({ code: result.outputFiles[0].text });
In this example, someTransformFunction in worker.ts should be replaced with the actual transformation logic you want to apply to your code. The transformed code is then logged in the main thread. Please note that this is a simplified example and might need to be adjusted based on your actual use case. Also, remember that the permissions of the worker are inherited from the main thread, so if you need to use any Deno APIs inside the worker, you need to ensure the main thread has the necessary permissions.
adoublef
adoublef10mo ago
@Deno AI Helper if i just want to build the bundle so that i can serve it as a response body, what config would you recomment
Deno AI Helper
Deno AI Helper10mo ago
If you want to build a bundle to serve as a response body, you can use the esbuild.build function with the write: false option. This will return the output files in the result object instead of writing them to disk. Here's an example configuration:
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
plugins: [...denoPlugins()],
});
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
plugins: [...denoPlugins()],
});
In this configuration: - entryPoints is the entry point of your application. - platform is set to "browser" to indicate that the output should be able to run in a browser. - target specifies the minimum versions of Chrome, Firefox, and Safari that the output should be compatible with. - format is set to "esm" to output ES modules. - bundle is set to true to bundle all dependencies into a single file. - minify is set to true to minify the output. - absWorkingDir is set to the current working directory. - outdir is set to the current directory, but this is ignored because write is set to false. - write is set to false to return the output files in the result object instead of writing them to disk. - metafile is set to false because we don't need a metafile in this case. - plugins is set to the Deno plugins. After running this build, you can access the output files with result.outputFiles. Each output file is an object with path and contents properties. The contents property is a Uint8Array of the file contents. You can convert this to a string with new TextDecoder().decode(file.contents) to get the file contents as a string, which you can then serve
adoublef
adoublef10mo ago
@Deno AI Helper is there something wrong with my script as it is still returning the error
import * as esbuild from "https://deno.land/x/esbuild@v0.19.2/wasm.js";
import { denoPlugins } from "https://deno.land/x/esbuild_deno_loader@0.8.1/mod.ts";
import { Hono } from "https://deno.land/x/hono@v3.6.0-rc.1/mod.ts";

// Learn more at https://deno.land/manual/examples/module_metadata#concepts
if (import.meta.main) {
try {
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
// @ts-ignore been updated to v0.19.2
plugins: [...denoPlugins()],
});

console.log(result.outputFiles);

const app = new Hono();

app.get("/", c => c.text(`Add 2 + 3 = ${add(2, 3)}`));

await Deno.serve(app.fetch).finished;
} catch (error) {
console.error(error.message);
} finally {
esbuild.stop();
}
}
import * as esbuild from "https://deno.land/x/esbuild@v0.19.2/wasm.js";
import { denoPlugins } from "https://deno.land/x/esbuild_deno_loader@0.8.1/mod.ts";
import { Hono } from "https://deno.land/x/hono@v3.6.0-rc.1/mod.ts";

// Learn more at https://deno.land/manual/examples/module_metadata#concepts
if (import.meta.main) {
try {
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outdir: ".",
write: false,
metafile: false,
// @ts-ignore been updated to v0.19.2
plugins: [...denoPlugins()],
});

console.log(result.outputFiles);

const app = new Hono();

app.get("/", c => c.text(`Add 2 + 3 = ${add(2, 3)}`));

await Deno.serve(app.fetch).finished;
} catch (error) {
console.error(error.message);
} finally {
esbuild.stop();
}
}
Deno AI Helper
Deno AI Helper10mo ago
Based on the provided script, it seems like you're trying to use esbuild to bundle a TypeScript file and then serve it using Hono. However, the error message you're seeing suggests that there's an issue with the Worker API. The Worker API is used by esbuild to run tasks in parallel. However, Deno Deploy does not currently support the Worker API, which is likely why you're seeing this error. One possible solution to this issue is to run the esbuild bundling step before deploying your code. This way, you can bundle your code into a single JavaScript file, which can then be deployed without needing to run esbuild in the cloud. Here's an example of how you might do this: 1. First, run esbuild locally to bundle your code:
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outfile: "./bundle.js",
metafile: false,
plugins: [...denoPlugins()],
});
const result = await esbuild.build({
entryPoints: ["./hello_world.ts"],
platform: "browser",
target: ["chrome99", "firefox99", "safari15"],
format: "esm",
bundle: true,
minify: true,
absWorkingDir: Deno.cwd(),
outfile: "./bundle.js",
metafile: false,
plugins: [...denoPlugins()],
});
This will create a bundle.js file in your project directory. 2. Then, modify your server code to serve the bundled file:
import { Hono } from "https://deno.land/x/hono@v3.6.0-rc.1/mod.ts";

const app = new Hono();

app.get("/", c => c.text(`Add 2 + 3 = ${add(2, 3)}`));

await Deno.serve(app.fetch).finished;
import { Hono } from "https://deno.land/x/hono@v3.6.0-rc.1/mod.ts";

const app = new Hono();

app.get("/", c => c.text(`Add 2 + 3 = ${add(2, 3)}`));

await Deno.serve(app.fetch).finished;
3. Finally, deploy your server code and the bundle.js file to Deno Deploy. Please note that this is a workaround and might not be suitable for all use cases. If you need to use esbuild in the cloud, you might need to wait until Deno Deploy supports the Worker API.