Coder Social home page Coder Social logo

esbuild_deno_loader's Introduction

esbuild-deno-loader

Deno module resolution for esbuild.

  • Support for file:, https:, and data: specifiers
  • Support for npm: specifiers
  • Support for jsr: specifiers
  • Support for import maps (including embedded into deno.json)
  • Native loader using Deno's global cache directory
  • Portable loader that words in environments with limited permissions

Example

This example bundles an entrypoint into a single ESM output.

import * as esbuild from "npm:[email protected]";
// Import the WASM build on platforms where running subprocesses is not
// permitted, such as Deno Deploy, or when running without `--allow-run`.
// import * as esbuild from "https://deno.land/x/[email protected]/wasm.js";

import { denoPlugins } from "jsr:@luca/esbuild-deno-loader@^0.10.3";

const result = await esbuild.build({
  plugins: [...denoPlugins()],
  entryPoints: ["https://deno.land/[email protected]/bytes/mod.ts"],
  outfile: "./dist/bytes.esm.js",
  bundle: true,
  format: "esm",
});

console.log(result.outputFiles);

esbuild.stop();

Limitations

  • The "portable" loader does not use the Deno module cache, so all remote specifiers are downloaded on every run.
  • When using the "portable" loader, all npm: dependencies must be pre-downloaded into a local node_modules/ directory.
  • When using the "portable" loader with jsr: specifiers, a lockfile must be present and passed to the loader (either using configPath or lockPath).
  • npm: specifiers are not supported on WASM esbuild builds due to FS access limitations (see evanw/esbuild#2968).

Documentation

The Deno integration for Deno consists of two separate plugins (that are however most commonly used together):

  1. The resolver, which resolves specifiers within a file relative to the file itself (absolutization), taking into account import maps.
  2. The loader, which takes a fully resolved specifier, and attempts to load it. If the loader encounters redirects, these are processed until a final module is found.

Most commonly these two plugins are used together, chained directly after each other using the denoPlugins() function. This function returns an array of esbuild.Plugin instances, which can be spread directly into the plugins array of the esbuild build options.

In depth documentation for each of the plugins, and the denoPlugins() function can be found in the generated docs.

Using with other plugins

For some use-cases these plugins should be manually instantiated. For example if you want to add your own loader plugins that handles specific file extensions or URL schemes, you should insert these plugins between the Deno resolver, and Deno loader.

In most cases, the denoResolverPlugin should be the first plugin in the plugin array.

The resolver performs initial resolution on the path. This includes making relative specifiers absolute and processing import maps. It will then send the fully resolved specifiers back into esbuild's resolver stack to be processed by other plugins. In the second path, the representation of the module is a fully qualified URL. The namespace of the second resolve pass is the scheme of the URL. The path is the remainder of the URL. The second resolve pass does not have a resolveDir property, as the URL is fully qualified already.

The denoLoaderPlugin registers resolvers that are hit in the secondary resolve pass for the schemes http, https, data, and file.

The output of the second resolve pass is then passed to the loader stack. The loader stack is responsible for loading the module. Just like in the resolver stack, the namespace of the loader stack is the scheme of the URL, and the path is the remainder of the URL.

The denoLoaderPlugin registers loaders that are hit in the secondary resolve pass for the schemes http, https, data, and file.

The examples directory contains an example for how to integrate with custom plugins. The examples/custom_scheme_plugin.ts example shows how to add a plugin that handles a custom scheme.

Permissions

This plugins requires the following permissions:

  • --allow-read if you need to resolve local files.
  • --allow-net if you need to resolve remote files.

If the program is run with --allow-run, the plugin will use the deno binary to resolve remote files. This allows the plugin to re-use the Deno module cache.

esbuild_deno_loader's People

Contributors

0xxff avatar aninternettroll avatar blackaslight avatar deer avatar johnspurlock avatar jsejcksn avatar leodog896 avatar lucacasonato avatar marvinhagemeister avatar nayeemrmn avatar ngasull avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

esbuild_deno_loader's Issues

Doesn't work with `node:` specifiers

Ideally, node: specifiers should probably be allowed to pass through untouched and not be resolved when bundling since they're handled by deno during runtime.

npm specifiers with subdirectories fail to create destination directory

The gist of the issue is this:

X [ERROR] The system cannot find the path specified. (os error 3): rename 'C:\...\Temp\9ead501e' -> '...\deno_esbuild\@tanstack\[email protected]\node_modules\@tanstack\table-core' [plugin deno-loader]

deno-loader is trying to rename directory without creating the destination first.

If I manually make this destination directory:

C:\Users\jarip\AppData\Local\deno\deno_esbuild\@tanstack\[email protected]\node_modules\@tanstack\table-core

Then it resumes.

More error details

C:\Source\Deno\denotest>deno run -A bundle.ts
X [ERROR] The system cannot find the path specified. (os error 3): rename 'C:\Users\jarip\AppData\Local\Temp\9ead501e' -> 'C:\Users\jarip\AppData\Local\deno\deno_esbuild\@tanstack\[email protected]\node_modules\@tanstack\table-core' [plugin deno-loader]

    ../../../Users/jarip/AppData/Local/deno/deno_esbuild/@tanstack/[email protected][email protected]/node_modules/@tanstack/solid-table/build/lib/index.mjs:11:28:
      11 │ import { createTable } from '@tanstack/table-core';
         ╵                             ~~~~~~~~~~~~~~~~~~~~~~

error: Uncaught Error: Build failed with 1 error:
../../../Users/jarip/AppData/Local/deno/deno_esbuild/@tanstack/[email protected][email protected]/node_modules/@tanstack/solid-table/build/lib/index.mjs:11:28: ERROR: [plugin: deno-loader] The system cannot find the path specified. (os error 3): rename 'C:\Users\jarip\AppData\Local\Temp\9ead501e' -> 'C:\Users\jarip\AppData\Local\deno\deno_esbuild\@tanstack\[email protected]\node_modules\@tanstack\table-core'
    at failureErrorWithLog (file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:1636:15)
    at file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:1048:25
    at runOnEndCallbacks (file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:1471:45)
    at buildResponseToResult (file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:1046:7)
    at file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:1075:16
    at responseCallbacks.<computed> (file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:697:9)
    at handleIncomingPacket (file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:752:9)
    at Readable.readFromStdout (file:///C:/Users/jarip/AppData/Local/deno/npm/registry.npmjs.org/esbuild/0.17.10/lib/main.js:673:7)
    at Readable.emit (ext:deno_node/_stream.mjs:1852:9)
    at addChunk (ext:deno_node/_stream.mjs:2874:16)

Reproduce

bundle.ts

import * as esbuild from "npm:esbuild";
import { denoPlugins } from "https://deno.land/x/[email protected]/mod.ts";

await esbuild.build({
    plugins: [...denoPlugins({
        loader: "native"
    })],
    entryPoints: ["test.ts"],
    outfile: "test.js",
    bundle: true,
    format: "esm",
});

test.ts

import {
    flexRender
} from "npm:@tanstack/solid-table";

export function test() {
    flexRender(null, {});
}

Then run deno run -A bundle.ts

Adding a custom file extension

Hi, I'm trying to add a custom file extension to esbuild but get this:

✘ [ERROR] [plugin deno] Expected a JavaScript or TypeScript module, but identified a Unknown module. Importing these types of modules is currently not supported.

What could we do to support other plugins, or is the support already there?

The plugin looks like this:

  name: 'script',
  setup(build) {
    // Resolve ".script"
    build.onResolve({ filter: /\.script$/ }, ({ path, resolveDir }) => {
      // Ignore unresolvable paths
      if (resolveDir === '') return;

      return { path, namespace };
    });

    build.onLoad({ filter: /.*/, namespace }, async ({ path }) => ({
      contents: "contents"
    }));
  },
}```

Support for import maps

I've was going to use an import_map.json to reference imports in my typescript files using lume.

This gave me an error: [plugin lumeLoader] Must be an absolute path.

I then tried to use esbuild-plugin-import-map
however the error message remained the same.
I'm not sure why this fails.

It would be great to have some kind of support for import maps!

For now I will resort to using a deps.ts file that im- and exports dependencies (e.g. export * as some_dependency from 'foobar';)

Basic code I used:

import * as importMap from 'npm:esbuild-plugin-import-map';
import esbuild from 'lume/plugins/esbuild.ts';
import lume from 'lume/mod.ts';

const site = lume();

importMap.load({
  'imports': {
    'some_dependency: 'foobar',
  },
});

site.use(
  esbuild({
    options: {
      plugins: [importMap.plugin()],
    },
  }),
);

export default site;

Doesn't work with `npm:` specifiers

✘ [ERROR] [plugin deno] Failed to call 'deno info' on 'file:///.../.../index.js'

This could potentially be solved with an unstable flag. I will open a PR when my last one is merged. Please take a look.

How can I make a library's dependencies resolve in a local project's `import_map.json`?

I'm not sure if it's right to question here.

The situation is that I imported "react" in the deno.land/x/wrp, and I imported that library along with import_map.json in the fresh project.

Then the following error occurred:

Server listening on http://localhost:8000
Download https://deno.land/x/[email protected]/react/react
✘ [ERROR] [plugin deno] The module was missing and could not be loaded.

    deno:https://deno.land/x/[email protected]/react/useWrpClientImpl.ts:2:36:
      2 │ import { useEffect, useState } from "react";
        ╵                                     ~~~~~~~

How to reproduce the error:

git clone [email protected]:pbkit/pbkit.dev.git
cd pbkit.dev
git checkout wrp
deno task dev
open http://localhost:8000/wrp-example-host

Error with the latest version of esbuild

I'd like to update esbuild to the last version (v0.14.48) but I have this error due typing incompatibilities between v0.14.39 (the version imported by deno loader) and v0.14.48.

error: TS2322 [ERROR]: Type 'import("https://deno.land/x/[email protected]/mod.d.ts").Plugin' is not assignable to type 'import("https://deno.land/x/[email protected]/mod.d.ts").Plugin'.
  Types of property 'setup' are incompatible.
    Type '(build: import("https://deno.land/x/[email protected]/mod.d.ts").PluginBuild) => void | Promise<void>' is not assignable to type '(build: import("https://deno.land/x/[email protected]/mod.d.ts").PluginBuild) => void | Promise<void>'.
      Types of parameters 'build' and 'build' are incompatible.
...

I propose to release the 0.5.1 version with updated dependencies.

importmap support local path

seems this plugin does not support importmap like

{
"import" : {
  "~": "./src"
}
}

but the import_map of deno support it

Module parse failure make the file unwatchable

Steps to reproduce

  1. Prepare the following files.
// a.ts
import "./b.ts";
// b.ts
export {};
  1. Run esbuild a.ts in watch mode with esbuild_deno_loader.
  2. Append ,, to b.ts and save.
  3. Remove ,, from b.ts and save.

Expected behavior

Error is recovered and it should be built.

Actual behavior

Some error like the following and nothing happens.

[ERROR] The module's source code could not be parsed: Unexpected token `,`. Expected identifier, string literal, numeric literal or [ for the computed key at

If we modify a.ts, it works fine again.

Additional context

https://github.com/jeiea/esbuild_deno_loader this works as expected, but it feels like monkey patching.

I think it should fail on load phase, not resolve phase.

Bug: Failing to treeshake dead imports of sub files that have node type imports in them

Esbuild seems to be failing to exclude dead imports of sub files believed to be because they have a node type import. I am not sure if this bug is caused by this plugin or esbuild itself.

Reproduction

deno run -A bundle.ts

main.ts

import { random } from './lib.ts'

console.log('Hello World')
console.log(random())

lib.ts

import { Iter } from 'https://deno.land/x/[email protected]/mod.ts'
import { Peer } from 'https://esm.sh/[email protected]?bundle-deps'

export function createPeer() {
	return new Peer()
}

export function createIter() {
	return new Iter((function* () {
		let i = 0
		while (true)
			yield i++
	})())
}

export function random() {
	return Math.random()
}

bundle.ts

// @deno-types='https://deno.land/x/[email protected]/mod.d.ts'
import { build, stop } from 'https://deno.land/x/[email protected]/mod.js'
import { denoPlugins } from 'https://deno.land/x/[email protected]/mod.ts'

await esbuild('./main.ts', './main.js')

stop()

async function esbuild(inPath: string, outPath: string) {
	{
		const { errors, warnings } = await build({
			plugins: denoPlugins(),
			entryPoints: [ inPath ],
			outfile: outPath,
			format: 'esm',
			bundle: true,
			treeShaking: true,
		})
		errors.forEach(x => console.error(x))
		warnings.forEach(x => console.warn(x))
	}
}

main.js expected output

The actual output includes the entire contents of the Peer import, but not the IterStar import

// lib.ts
function random() {
  return Math.random();
}

// main.ts
console.log("Hello World");
console.log(random());

[feature request] Add support for imports in Deno config

Thank you for writing this great plugin! This is a feature request.

Deno v1.30 recently added support to for inlining import maps into the deno.json. This is a feature request to add deno.json support. The current implementation errors out when a Deno config is a passed as an import map: an invalid top-level key was present in the import map.

Example deno.json with an import map inlined:

{
  "compilerOptions": {
    "exactOptionalPropertyTypes": true,
    "noImplicitOverride": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "useUnknownInCatchVariables": true
  },
  "fmt": {
    "files": { "exclude": ["dist"] },
    "options": { "semiColons": false, "singleQuote": true }
  },
  "imports": {
    "@/ooz": "./mod.ts",
    "dejs/": "https://deno.land/x/[email protected]/",
    "esbuild": "https://deno.land/x/[email protected]/mod.js",
    "esbuild_deno_loader": "https://deno.land/x/[email protected]/mod.ts",
    "std/": "https://deno.land/[email protected]/"
  },
  "lint": {
    "files": { "exclude": ["dist"] },
    "rules": {
      "exclude": ["no-empty-interface", "no-inferrable-types", "no-namespace"]
    }
  },
  "lock": false,
  "test": { "files": { "exclude": ["dist"] } }
}

References

NPM specifier libs not working

Hey 👋

Tried bundling one of my aws lambda projects and I'm getting errors when trying to do it:

my deps.ts

....
export { SSMClient, GetParameterCommand } from "npm:@aws-sdk/client-ssm"
....

my bundle.ts

import * as esbuild from "https://deno.land/x/[email protected]/mod.js";

import { denoPlugins } from "https://raw.githubusercontent.com/lucacasonato/esbuild_deno_loader/main/mod.ts";

const result = await esbuild.build({
  plugins: [...denoPlugins()],
  entryPoints: [`${source}/handler.ts`],
  outfile: `${dist_folder}/handler-bundle.js`,
  bundle: true,
  format: "esm",
});

This resunts in over 30+ errors:

✘ [ERROR] NPM package not found. [plugin deno-loader]

    ../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/webCryptoSha256.js:4:21:
      4 │ var util_1 = require("@aws-crypto/util");
        ╵                      ~~~~~~~~~~~~~~~~~~

✘ [ERROR] NPM package not found. [plugin deno-loader]

    ../../.cache/deno/deno_esbuild/@smithy/[email protected]/node_modules/@smithy/util-retry/dist-es/DefaultRateLimiter.js:1:34:
      1 │ import { isThrottlingError } from "@smithy/service-error-classification";
        ╵                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

✘ [ERROR] NPM package not found. [plugin deno-loader]

    ../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/webCryptoSha256.js:6:35:
      6 │ var util_locate_window_1 = require("@aws-sdk/util-locate-window");
        ╵                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

✘ [ERROR] NPM package not found. [plugin deno-loader]

    ../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/ie11Sha256.js:6:34:
      6 │ var util_utf8_browser_1 = require("@aws-sdk/util-utf8-browser");

................
................
error: Uncaught (in promise) Error: Build failed with 30 errors:
../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/crossPlatformSha256.js:7:36: ERROR: [plugin: deno-loader] NPM package not found.
../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/crossPlatformSha256.js:8:31: ERROR: [plugin: deno-loader] NPM package not found.
../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/crossPlatformSha256.js:9:35: ERROR: [plugin: deno-loader] NPM package not found.
../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/crossPlatformSha256.js:10:21: ERROR: [plugin: deno-loader] NPM package not found.
../../.cache/deno/deno_esbuild/@aws-crypto/[email protected]/node_modules/@aws-crypto/sha256-browser/build/ie11Sha256.js:6:34: ERROR: [plugin: deno-loader] NPM package not found.
...
  let error = new Error(text);

Any ideas how I can sort this out?

cannot resolve module specifier starts with special character

I tried to run Tauri with Deno Fresh. So, I used deno_esbuild for compile to deno-fresh entrypoint file. And I used esbuild_deno_loader for module resolution. But, I failed.

{
  "lock": false,
  "tasks": {
    "start": "deno run -A --watch=static/,routes/ dev.ts",
    "build": "deno run -A build.ts",
    "update": "deno run -A -r https://fresh.deno.dev/update .",
    "cache": "deno cache --reload --lock=deno.lock --lock-write main.ts"
  },
  "imports": {
    "$fresh/": "https://deno.land/x/[email protected]/",
    "preact": "https://esm.sh/[email protected]",
    "preact/": "https://esm.sh/[email protected]/",
    "preact-render-to-string": "https://esm.sh/*[email protected]",
    "@preact/signals": "https://esm.sh/*@preact/[email protected]",
    "@preact/signals-core": "https://esm.sh/*@preact/[email protected]",
    "$std/": "https://deno.land/[email protected]/",
    "esbuild": "https://deno.land/x/[email protected]/mod.js",
    "esbuild-deno-loader": "https://deno.land/x/[email protected]/mod.ts"
  },
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "preact"
  }
}
import * as esbuild from "esbuild";
import { denoPlugins } from "esbuild-deno-loader";
import { posix } from "$std/path/mod.ts";

const options: esbuild.BuildOptions = {
  entryPoints: [posix.resolve("main.ts")],
  bundle: true,
  format: "esm",
  outdir: posix.resolve("build"),
  minify: true,
  sourcemap: "external",
  plugins: [
    ...denoPlugins(),
  ],
};

await esbuild.build(options);

esbuild.stop();

all codes is here:
https://github.com/babie/tauri-with-deno-fresh/tree/with-special-character

Expect

No errors.

Actual

$ deno task build
Task build deno run -A build.ts
✘ [ERROR] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/$std/dotenv/load.ts". [plugin deno-loader]

    main.ts:7:7:
      7 │ import "$std/dotenv/load.ts";
        ╵        ~~~~~~~~~~~~~~~~~~~~~

✘ [ERROR] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/$fresh/server.ts". [plugin deno-loader]

    main.ts:9:22:
      9 │ import { start } from "$fresh/server.ts";
        ╵                       ~~~~~~~~~~~~~~~~~~

✘ [ERROR] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/routes/$fresh/runtime.ts". [plugin deno-loader]

    routes/index.tsx:1:21:
      1 │ import { Head } from "$fresh/runtime.ts";
        ╵                      ~~~~~~~~~~~~~~~~~~~

✘ [ERROR] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/components/$fresh/runtime.ts". [plugin deno-loader]

    components/Button.tsx:2:27:
      2 │ import { IS_BROWSER } from "$fresh/runtime.ts";
        ╵                            ~~~~~~~~~~~~~~~~~~~

✘ [ERROR] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/routes/@preact/signals". [plugin deno-loader]

    routes/index.tsx:2:26:
      2 │ import { useSignal } from "@preact/signals";
        ╵                           ~~~~~~~~~~~~~~~~~

error: Uncaught (in promise) Error: Build failed with 5 errors:
components/Button.tsx:2:27: ERROR: [plugin: deno-loader] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/components/$fresh/runtime.ts".
main.ts:7:7: ERROR: [plugin: deno-loader] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/$std/dotenv/load.ts".
main.ts:9:22: ERROR: [plugin: deno-loader] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/$fresh/server.ts".
routes/index.tsx:1:21: ERROR: [plugin: deno-loader] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/routes/$fresh/runtime.ts".
routes/index.tsx:2:26: ERROR: [plugin: deno-loader] Module not found "file:///Users/babie/src/github.com/babie/tauri-deno-fresh/routes/@preact/signals".
  let error = new Error(`${text}${summary}`);
              ^
    at failureErrorWithLog (https://deno.land/x/[email protected]/mod.js:1615:15)
    at https://deno.land/x/[email protected]/mod.js:1027:25
    at runOnEndCallbacks (https://deno.land/x/[email protected]/mod.js:1450:45)
    at buildResponseToResult (https://deno.land/x/[email protected]/mod.js:1025:7)
    at https://deno.land/x/[email protected]/mod.js:1054:16
    at responseCallbacks.<computed> (https://deno.land/x/[email protected]/mod.js:676:9)
    at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:731:9)
    at readFromStdout (https://deno.land/x/[email protected]/mod.js:652:7)
    at https://deno.land/x/[email protected]/mod.js:1901:11
    at eventLoopTick (ext:core/01_core.js:183:11)

I guess that importmap module cannot resolve specifiers starts with $ or @. I will send an issue to importmap repo and connect here later.

Error when importing JSR packages with jsr specifiers: "Importing a JSR package via an HTTPS URL is not implemented."

Description of the problem:

I'm encountering an error when importing JSR packages using jsr specifiers in my Deno project. The error message states:

"Importing a JSR package via an HTTPS URL is not implemented. Use a jsr: specifier instead for the time being."

However, I'm already using jsr specifiers everywhere.

Steps to reproduce:

Create a Deno project with a deno.json file that includes JSR dependencies using jsr specifiers.
Attempt to import the JSR packages in your code using esbuild_deno_loader, those JSR packages must have also other JSR packages as dependencies.

Expected behavior:

The JSR packages should import successfully.

Actual behavior:

The error message mentioned above is displayed.

Environment:

Deno version: 1.41
esbuild_deno_loader version: 0.9
Relevant package versions (e.g., @bureaudouble/bureau):
@bureaudouble/bureau: 0.0.4
@bureaudouble/islet: 0.0.7

Additional context:

It appears that the issue might be originating within esbuild_deno_loader itself.

Request:

Kindly investigate this issue and provide guidance on how to resolve it.

Thank you for your attention to this matter.

Sincerely,

typecheck fails when used with esbuild 0.15.3

error: TS2769 [ERROR]: No overload matches this call.
  The last overload gave the following error.
    Type 'import("https://deno.land/x/[email protected]/mod.d.ts").Plugin' is not assignable to type 'import("https://deno.land/x/[email protected]/mod.d.ts").Plugin'.
      Types of property 'setup' are incompatible.
        Type '(build: import("https://deno.land/x/[email protected]/mod.d.ts").PluginBuild) => void | Promise<void>' is not assignable to type '(build: import("https://deno.land/x/[email protected]/mod.d.ts").PluginBuild) => void | Promise<void>'.
          Types of parameters 'build' and 'build' are incompatible.
            Type 'import("https://deno.land/x/[email protected]/mod.d.ts").PluginBuild' is not assignable to type 'import("https://deno.land/x/[email protected]/mod.d.ts").PluginBuild'.
              The types of 'initialOptions.stdin' are incompatible between these types.
                Type 'import("https://deno.land/x/[email protected]/mod.d.ts").StdinOptions | undefined' is not assignable to type 'import("https://deno.land/x/[email protected]/mod.d.ts").StdinOptions | undefined'.
                  Type 'import("https://deno.land/x/[email protected]/mod.d.ts").StdinOptions' is not assignable to type 'import("https://deno.land/x/[email protected]/mod.d.ts").StdinOptions'.
                    Types of property 'contents' are incompatible.
                      Type 'string | Uint8Array' is not assignable to type 'string'.
                        Type 'Uint8Array' is not assignable to type 'string'.
    plugins: [denoPlugin({ importMapURL })],

Version conflicts

Hi, I see this error in VSCode, however it runs fine anyways:

No overload matches this call.
  Overload 1 of 2, '(options: BuildOptions): Promise<BuildResult<BuildOptions>>', gave the following error.
    Type 'import("https://deno.land/x/[email protected]/mod").Plugin' is not assignable to type 'import("https://deno.land/x/[email protected]/mod").Plugin'.
      Types of property 'setup' are incompatible.
        Type '(build: import("https://deno.land/x/[email protected]/mod").PluginBuild) => void | Promise<void>' is not assignable to type '(build: import("https://deno.land/x/[email protected]/mod").PluginBuild) => void | Promise<void>'.
          Types of parameters 'build' and 'build' are incompatible.
            Type 'import("https://deno.land/x/[email protected]/mod").PluginBuild' is not assignable to type 'import("https://deno.land/x/[email protected]/mod").PluginBuild'.
              The types of 'initialOptions.loader' are incompatible between these types.
                Type '{ [ext: string]: import("https://deno.land/x/[email protected]/mod").Loader; } | undefined' is not assignable to type '{ [ext: string]: import("https://deno.land/x/[email protected]/mod").Loader; } | undefined'.
                  Type '{ [ext: string]: import("https://deno.land/x/[email protected]/mod").Loader; }' is not assignable to type '{ [ext: string]: import("https://deno.land/x/[email protected]/mod").Loader; }'.
                    'string' index signatures are incompatible.
                      Type 'import("https://deno.land/x/[email protected]/mod").Loader' is not assignable to type 'import("https://deno.land/x/[email protected]/mod").Loader'.
                        Type '"empty"' is not assignable to type 'Loader'.  Overload 2 of 2, '(options: BuildOptions): Promise<BuildResult<BuildOptions>>', gave the following error.
    Type 'import("https://deno.land/x/[email protected]/mod").Plugin' is not assignable to type 'import("https://deno.land/x/[email protected]/mod").Plugin'.

Document minimum deno version this works with

Doesn't seem like it works with 1.23.1, but does with 1.37.1. With 1.23.1, the error I see trying to use this module is:

error: Uncaught SyntaxError: Export 'DenoLoaderPluginOptions' is not defined in module
export { DEFAULT_LOADER, denoLoaderPlugin, DenoLoaderPluginOptions };
                                           ^
    at <anonymous> (https://deno.land/x/[email protected]/mod.ts:23:44)

Maybe because DenoLoaderPluginOptions is imported as a type? Not sure.

Remove warning message

Hi.
I want to use this loader in the esbuild plugin for Lume. The plugin detects the importMap value of the deno.json file automatically here: https://github.com/lumeland/lume/blob/76072b52df9e463d1ce2ce49c73da7e54f1dfbf1/plugins/esbuild.ts#L21

On run esbuild, I get the following warning in the console:

Warning the configuration file "file:///Users/oscarotero/testing/deno.json" contains an entry for "importMap" that is being ignored.

I think this error is because the loader runs internally deno with Deno.run and this deno.json file is detected automatically by deno, but the import map file was passed with the --import-map option.

If the import file is not passed (because should be detected by the deno.json file) the build fails with errors like:

✘ [ERROR] [plugin deno] The module was missing and could not be loaded.

    deno:file:///Users/oscarotero/testing/main.jsx:1:18:
      1 │ import React from "react";

Deno v1.22 introduced the --no-config flag, so I think it should be passed here: https://github.com/lucacasonato/esbuild_deno_loader/blob/main/src/deno.ts#L45 to avoid unexpected errors.

Conflicts with other loaders

Because of the automatically registered "file" specifier, this conflicts with any defined loaders that also use file.

For example following esbuild options:

{
    plugins: [...denoPlugins()],
    entryPoints: entryPoints,
    ...
    loader: {
      ".graphql": "file",
    },
  }

If i now import a graphql file like this:

import query from "./query.graphql";

The deno-loader plugin throws the following error:

 The module's source code could not be parsed: Expected ',', got ':'
 ~ [plugin deno-loader]

The plugin should not handle all file namespaces as TypeScript/JavaScript files.

error: [plugin: deno] Unreachable

Given a file module.ts

import { assetsBaseUrl } from "ggbot2-assets";
console.log(assetsBaseUrl);

And a file build.ts

import * as esbuild from "esbuild";
import { denoPlugin } from "esbuild_deno_loader";

await esbuild.build({
  plugins: [denoPlugin({ importMapFile: "./import_map.json" })],
  entryPoints: ["./module.ts"],
  outfile: "./module.js",
  bundle: true,
  minify: true,
  format: "esm",
});
esbuild.stop();

Where import_map.json is the following

{
  "imports": {
    "esbuild": "https://deno.land/x/[email protected]/mod.js",
    "esbuild_deno_loader": "https://deno.land/x/[email protected]/mod.ts",
    "ggbot2-assets": "https://github.com/ggbot2/assets/raw/main/index.ts"
  }
}

Running the module works, try it with

deno run --unstable --importmap=import_map.json module.ts

But the build raises the following issue

 > deno:file:///Users/gcasati/github.com/ggbot2/test/module.ts:1:30: error: [plugin: deno] Unreachable.
    1 │ import { assetsBaseUrl } from "ggbot2-assets";
      ╵                               ~~~~~~~~~~~~~~~

error: Uncaught (in promise) Error: Build failed with 1 error:
deno:file:///Users/gcasati/github.com/ggbot2/test/module.ts:1:30: error: [plugin: deno] Unreachable.
  let error = new Error(`${text}${summary}`);
              ^
    at failureErrorWithLog (https://deno.land/x/[email protected]/mod.js:1436:15)
    at https://deno.land/x/[email protected]/mod.js:1094:28
    at runOnEndCallbacks (https://deno.land/x/[email protected]/mod.js:882:63)
    at buildResponseToResult (https://deno.land/x/[email protected]/mod.js:1092:7)
    at https://deno.land/x/[email protected]/mod.js:1201:14
    at https://deno.land/x/[email protected]/mod.js:570:9
    at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:667:9)
    at readFromStdout (https://deno.land/x/[email protected]/mod.js:537:7)
    at https://deno.land/x/[email protected]/mod.js:1706:11

To run build launch command

deno run --unstable --importmap=import_map.json --allow-env --allow-read --allow-net --allow-run --allow-write ./build.ts

loaders no longer work

When configuring esbuild with loaders, e.g.

loader: {
    ".css": "text",
},

I get an error when I import a .css file, e.g.

import cssText from "./main.css";

Error:

error: Uncaught (in promise) Error: Build failed with 1 error:
deno:file:///.../main.ts:20:20: ERROR: [plugin: deno] Expected a JavaScript or TypeScript module, but identified a Unknown module. Importing these types of modules is currently not supported.

I am able to work around this by patching the onResolve and onLoad a bit, but I'm not sure what would be the clean way to do this. What I have now is in my fork of this repo in the mod.ts (note the "NOT FOR CSS" markers):

build.onResolve(
        { filter: /.*/ },
        function onResolve(
          args: esbuild.OnResolveArgs
        ): esbuild.OnResolveResult | null | undefined {
          const resolveDir = args.resolveDir
            ? `${toFileUrl(args.resolveDir).href}/`
            : "";
          const referrer = args.importer || resolveDir;
          let resolved: URL;
          if (importMap !== null) {
            const res = resolveModuleSpecifier(
              args.path,
              importMap,
              new URL(referrer) || undefined
            );
            resolved = new URL(res);
          } else {
            resolved = new URL(args.path, referrer);
          }
          // NOT FOR CSS
          if (resolved.href.endsWith(".css")) {
            return {
              path: resolved.href.substring("file://".length),
            };
          }
          return { path: resolved.href, namespace: "deno" };
        }
      );

      build.onLoad(
        { filter: /.*/ },
        function onLoad(
          args: esbuild.OnLoadArgs
        ): Promise<esbuild.OnLoadResult | null> {
          // NOT FOR CSS
          if (args.path.endsWith(".css")) {
            return Promise.resolve(null);
          }
          const url = new URL(args.path);
          switch (loader) {
            case "native":
              return nativeLoad(infoCache, url, options);
            case "portable":
              return portableLoad(url, options);
          }
        }
      );

[ERROR] Directory not empty (os error 39) on build in docker

When running

deno run -A --no-check --unstable main.js

in a fresh project in a Docker environment, it fails with this:

#0 19.00 ✘ [ERROR] Directory not empty (os error 39): rename '/tmp/d2d1db33' -> '/root/.cache/deno/deno_esbuild/[email protected]/node_modules/clsx' [plugin deno-loader]
#0 19.00 
#0 19.00     islands/piece-display.jsx:10:17:
#0 19.00       10 │ import clsx from "clsx";
#0 19.00          ╵                  ~~~~~~
#0 19.00 
#0 19.05 ✘ [ERROR] Directory not empty (os error 39): rename '/tmp/911cbde1' -> '/root/.cache/deno/deno_esbuild/[email protected]/node_modules/clsx' [plugin deno-loader]
#0 19.05 
#0 19.05     components/input/button.jsx:1:17:
#0 19.05       1 │ import clsx from "clsx";
#0 19.05         ╵                  ~~~~~~
#0 19.05 
#0 19.29 error: Uncaught (in promise) Error: Build failed with 2 errors:
#0 19.29 components/input/button.jsx:1:17: ERROR: [plugin: deno-loader] Directory not empty (os error 39): rename '/tmp/911cbde1' -> '/root/.cache/deno/deno_esbuild/[email protected]/node_modules/clsx'
#0 19.29 islands/piece-display.jsx:10:17: ERROR: [plugin: deno-loader] Directory not empty (os error 39): rename '/tmp/d2d1db33' -> '/root/.cache/deno/deno_esbuild/[email protected]/node_modules/clsx'
#0 19.29   let error = new Error(`${text}${summary}`);
#0 19.29               ^
#0 19.29     at failureErrorWithLog (https://deno.land/x/[email protected]/mod.js:1615:15)
#0 19.29     at https://deno.land/x/[email protected]/mod.js:1027:25
#0 19.29     at runOnEndCallbacks (https://deno.land/x/[email protected]/mod.js:1450:45)
#0 19.29     at buildResponseToResult (https://deno.land/x/[email protected]/mod.js:1025:7)
#0 19.29     at https://deno.land/x/[email protected]/mod.js:1054:16
#0 19.29     at responseCallbacks.<computed> (https://deno.land/x/[email protected]/mod.js:676:9)
#0 19.29     at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:731:9)
#0 19.29     at readFromStdout (https://deno.land/x/[email protected]/mod.js:652:7)
#0 19.29     at https://deno.land/x/[email protected]/mod.js:1901:11
#0 19.29     at eventLoopTick (ext:core/01_core.js:183:11)
------
Error: failed to fetch an image or build from source: error building: failed to solve: executor failed running [/bin/sh -c deno task build]: exit code: 1

To reproduce, check out this repository: https://github.com/pumpncode/open-match

It uses fly.io as deployment platform and you might need an account there to exactly reproduce this, but maybe just deploying the Dockerfile locally works as well. Below are the steps for fly.io:

  1. create an .env file in the repository root and add PORT=8000 to it
  2. if you're not logged in fly yet deno task authenticate
  3. deno task create-app
  4. fly secrets set PORT=8000
  5. deno task scale
  6. deno task deploy

This may be related to #82 and may be fixed by #83, however I never rename the DENO_DIR in my case, in case this a requirement for this issue to occur.

Running deno task build locally works just fine for me.

Cache imports

Using denoPlugins with esbuild.server every reload of the page triggers a download of the imports.

Is there a way to cache the modules? I tried with https://github.com/dalcib/esbuild-plugin-cache but doesn't seem to work with the current version of esbuild.

Here is my bundle.ts file:

import * as esbuild from "https://deno.land/x/[email protected]/mod.js";
import { denoPlugins } from "https://deno.land/x/[email protected]/mod.ts";

const ctx = await esbuild.context({
  entryPoints: ["./www/index.tsx"],
  outfile: "./www/dist/main.js",
  bundle: true,
  format: "esm",
  target: "es2020",
  platform: "browser",
  plugins: [
    {
      name: "json",
      setup: (build) =>
        build.onLoad({ filter: /\.json$/ }, () => ({ loader: "json" })),
    },
    ...denoPlugins(),
  ],
  publicPath: "./www/public",
});

await ctx.watch();

await ctx.serve({
  servedir: "./www",
  port: 3000,
});

[bug] JSON imports broken

Thanks for the cool tool! This is a small bug report.

When I try to import any JSON such as the following:

import gamepadMapJSON from './src/input/gamepad/gamepad-map.json' assert {
  type: 'json',
}

I get an error:

✘ [ERROR] The file "src/input/gamepad/gamepad-map.json" was loaded with the "js" loader

    mod.ts:48:27:
      48 │ import gamepadMapJSON from './src/input/gamepad/gamepad-map.json' assert {
         ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  This import assertion requires the loader to be "json" instead:

    mod.ts:49:2:
      49 │   type: 'json',
         ╵   ~~~~~~~~~~~~

If I omit the assertion, Deno complains The module is a JSON module and not being imported with an import assertion. Consider adding assert { type: "json" } to the import statement.deno(no-assert-type) (and I can't seem to ignore that).

I think I should just be able to add a loader to esbuild:

  loader: {
    '.json': 'json',
  },

But that seemed to have no effect. I tried to track it down and I think esbuild_deno_loader is maybe somehow intercepting the JSON import? I'm working around this with the following JSON plugin:

    {
      name: 'json',
      setup: (build) =>
        build.onLoad({ filter: /\.json$/ }, () => ({ loader: 'json' })),
    },

In case it's helpful, the whole script looks like this:

const options: esbuild.BuildOptions = {
  sourcemap: 'linked',
  bundle: true,
  entryPoints: [input],
  format: 'esm',
  logLevel: `warning`,
  outfile: output,
  treeShaking: true,
  minify: true,
  plugins: [
    // Hack around JSON loader overrides in esbuild_deno_loader that flag type
    // assertions.
    {
      name: 'json',
      setup: (build) =>
        build.onLoad({ filter: /\.json$/ }, () => ({ loader: 'json' })),
    },
    denoPlugin({
      ...(importMap != null && { importMapURL: new URL(importMap) }),
    }) as unknown as esbuild.Plugin,
  ],
}

await esbuild.build(options)
esbuild.stop()

Using with Deno Deploy

I wanted to learn how to setup esbuild within Deno Deploy. I have tried the example as stated in the README but I keep getting the following errors

ReferenceError: Worker is not defined
    at startRunningService (https://deno.land/x/[email protected]/wasm.js:1777:5)
    at ensureServiceIsRunning (https://deno.land/x/[email protected]/wasm.js:1758:31)
    at Module.build (https://deno.land/x/[email protected]/wasm.js:1734:26)
    at file:///src/main.ts:8:30

I have tried using the v0.19.2 version of the wasm esbuild (which looks to give me a deno-ts error saying the versions are not compatible) as well as v0.17.19 not working.

Would like to know what I ought to do to resolve
link to repo here
link to deployed app here

imports map not working

I don't think the resolver handles import maps correctly.

deno.json

{
  "imports": {
    "path": "https://deno.land/[email protected]/path/mod.ts"
  }
}

mod.ts

import { join } from "path";

console.log(join("foo", "bar"));

build.ts

import * as esbuild from "https://deno.land/x/[email protected]/mod.js";
import { denoPlugins } from "https://deno.land/x/[email protected]/mod.ts";

await esbuild.build({
  plugins: [...denoPlugins()],
  entryPoints: ["./mod.ts"],
  bundle: true,
  outdir: "./build",
});

when running deno run -A build.ts, I got

✘ [ERROR] Module not found "file:///home/swwind/Repositories/deno_esbuild_test/path". [plugin deno-loader]

    mod.ts:1:21:
      1 │ import { join } from "path";
        ╵                      ~~~~~~

error: Uncaught (in promise) Error: Build failed with 1 error:
mod.ts:1:21: ERROR: [plugin: deno-loader] Module not found "file:///home/swwind/Repositories/deno_esbuild_test/path".
  let error = new Error(`${text}${summary}`);
              ^
    at failureErrorWithLog (https://deno.land/x/[email protected]/mod.js:1612:15)
    at https://deno.land/x/[email protected]/mod.js:1024:25
    at runOnEndCallbacks (https://deno.land/x/[email protected]/mod.js:1447:45)
    at buildResponseToResult (https://deno.land/x/[email protected]/mod.js:1022:7)
    at https://deno.land/x/[email protected]/mod.js:1051:16
    at responseCallbacks.<computed> (https://deno.land/x/[email protected]/mod.js:673:9)
    at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:728:9)
    at readFromStdout (https://deno.land/x/[email protected]/mod.js:649:7)
    at https://deno.land/x/[email protected]/mod.js:1898:11
    at eventLoopTick (ext:core/01_core.js:183:11)

while deno run mod.ts just works.

Relative path are not loaded

It seems that on every relative path, I get the following error:

✘ [ERROR] Could not resolve "/home/carere/Projects/Ashiso/deno_zentai/apps/karada/src/components/organisms/Graph/controls/ContractSelector/ContractPreview/index.tsx" [plugin deno-loader]

    apps/karada/src/components/organisms/Graph/controls/ContractSelector/index.tsx:19:32:
      19 │ import { ContractPreview } from "./ContractPreview/index.tsx";
         ╵                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  The plugin "deno-loader" didn't set a resolve directory, so esbuild did not search for
  "/home/carere/Projects/Ashiso/deno_zentai/apps/karada/src/components/organisms/Graph/controls/ContractSelector/ContractPreview/index.tsx"
  on the file system.

I'm not well-versed into esbuild, and I don't know how to fix this issue.
Maybe someone got a clue ??

"external" config option in esbuild broken

When I configure external to be excluded from the bundle in my esbuilder config, they seem to be ignored when enabling the esbuild_deno_loader plugin. What I've done my local fork is add this:

if (build.initialOptions.external) {
  for (const external of build.initialOptions.external) {
    if (resolved.href.startsWith(external)) {
      return { path: resolved.href, external: true };
    }
  }
}

Above this line: https://github.com/lucacasonato/esbuild_deno_loader/blob/main/mod.ts#L77

This works, but isn't great, because external supports wildcards and what not. According to the esbuild docs this shouldn't be necessary, but I'm not familiar enough of how this all interacts to figure out why externals just seem to break without the lines above.

deno.json import maps

re recent update, deno.json becomes an import map. However, it seems like deno.json currently fails "Import map diagnostics" when being used as an importMapURL, since it has additional keys:

Import map diagnostics:
  - Invalid top-level key "compilerOptions". Only "imports" and "scopes" can be present.
  - Invalid top-level key "tasks". Only "imports" and "scopes" can be present.
  - Invalid top-level key "lint". Only "imports" and "scopes" can be present.
  - Invalid top-level key "fmt". Only "imports" and "scopes" can be present.

Should we maybe just validate import and scope keys?

Deno Lock

If lock isn't a string, the plugin throws. So the plugin doesn't work for projects that disable lock files. Is this intended behaviour?

[ERROR] File name too long

When attempting to build a package with many dependencies, the following error occurs:

error: Uncaught (in promise) Error: Build failed with 1 error:
error: File name too long (os error 63): mkdir ~
...

Reproduction:

import * as esbuild from "https://deno.land/x/[email protected]/mod.js";
import { denoPlugins } from "https://deno.land/x/[email protected]/mod.ts";

const result = await esbuild.build({
  plugins: [
    ...denoPlugins(),
  ],
  entryPoints: ["npm:[email protected]"],
  outfile: "./dist/bytes.esm.js",
  bundle: true,
  format: "esm",
});

console.log(result.outputFiles);

esbuild.stop();

This seems to be caused by the npmPackageId exceeding the OS limit.

How about using a hash value instead?

[plugin deno-loader] Module not found - preact/hook

ERROR:

✘ [ERROR] Module not found "file:///Users/pro/ken/preact/hooks". [plugin deno-loader]

    preact.tsx:2:25:
      2 │ import { useState } from "preact/hooks";
        ╵                          ~~~~~~~~~~~~~~

error: Uncaught (in promise) Error: Build failed with 1 error:
preact.tsx:2:25: ERROR: [plugin: deno-loader] Module not found "file:///Users/pro/ken/preact/hooks".
  let error = new Error(`${text}${summary}`);
              ^
    at failureErrorWithLog (https://deno.land/x/[email protected]/mod.js:1612:15)
    at https://deno.land/x/[email protected]/mod.js:1024:25
    at runOnEndCallbacks (https://deno.land/x/[email protected]/mod.js:1447:45)
    at buildResponseToResult (https://deno.land/x/[email protected]/mod.js:1022:7)
    at https://deno.land/x/[email protected]/mod.js:1051:16
    at responseCallbacks.<computed> (https://deno.land/x/[email protected]/mod.js:673:9)
    at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:728:9)
    at readFromStdout (https://deno.land/x/[email protected]/mod.js:649:7)
    at https://deno.land/x/[email protected]/mod.js:1898:11
    at eventLoopTick (ext:core/01_core.js:183:11)

preact.tsx

import { h } from "preact";
import { useState } from "preact/hooks";

export default function UUID(props: { data: string }) {
  const [data, setD] = useState({
    uuid: "e90d45df-4132-41ad-aec8-e0e19f7647a9",
  });

  const handleClick = async () => {
    const res = await fetch("/api");
    setD(await res.json());
  };

  return (
    <div>
      <h1>Hello {props.data}</h1>
      <button onClick={handleClick}>
        Click me to get the fresh UUID from API: {data.uuid}
      </button>
    </div>
  );
}

Import map:

{
  "imports": {
    "react": "https://esm.sh/[email protected]/compat",
    "preact": "https://esm.sh/[email protected]",
    "preact/": "https://esm.sh/[email protected]/"
  }
}

build.ts

import * as esbuild from "https://deno.land/x/[email protected]/mod.js";
// Import the WASM build on platforms where running subprocesses is not
// permitted, such as Deno Deploy, or when running without `--allow-run`.
// import * as esbuild from "https://deno.land/x/[email protected]/wasm.js";

import { denoPlugins } from "https://deno.land/x/[email protected]/mod.ts";

const result = await esbuild.build({
  plugins: [...denoPlugins()],
  entryPoints: ["preact.tsx"],
  outfile: "./dist/preact.js",
  bundle: true,
  format: "esm",
});

console.log(result.outputFiles);

esbuild.stop();

Doesn't work when using esbuild's `stdin`

Windows 11, Deno 1.24.0, https://deno.land/x/[email protected], https://deno.land/x/[email protected]

// greetings.ts
export function sayWelcome(name: string) {
    return `Welcome ${name}!`
}

// welcome.ts 
import { sayWelcome } from './greetings.ts'

console.log(sayWelcome('Luca'))

But welcome.ts is passed to esbuild by stdin with these settings:

esbuild.build({
    // ...

    stdin: {
        contents: await Deno.readTextFile('./welcome.ts'),
        resolveDir: Deno.cwd(),
        sourcefile: 'welcome.ts',
        loader: 'ts',
    }

    // ...
})
X [ERROR] [plugin deno] Invalid URL

    welcome.ts:1:27:
      1 │ import { sayWelcome } from './greetings.ts'
        ╵                            ~~~~~~~~~~~~~~~~

error: Uncaught (in promise) Error: Build failed with 1 error:
welcome.ts:1:27: ERROR: [plugin: deno] Invalid URL
    {
      detail: TypeError: Invalid URL
        at Object.opSync (deno:core/01_core.js:170:12)
        at opUrlParse (deno:ext/url/00_url.js:49:27)
        at new URL (deno:ext/url/00_url.js:323:20)
        at onResolve (https://deno.land/x/[email protected]/mod.ts:68:22)
        at callback (https://deno.land/x/[email protected]/mod.js:904:34)
        at handleRequest (https://deno.land/x/[email protected]/mod.js:684:36)
        at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:739:7)
        at readFromStdout (https://deno.land/x/[email protected]/mod.js:615:7)
        at https://deno.land/x/[email protected]/mod.js:1867:11,
      id: "",
      location: {
        column: 27,
        file: "welcome.ts",
        length: 16,
        line: 1,
        lineText: "import { sayWelcome } from './greetings.ts'",
        namespace: "",
        suggestion: ""
      },
      notes: [],
      pluginName: "deno",
      text: "Invalid URL"
    }
  let error = new Error(`${text}${summary}`);
              ^
    at failureErrorWithLog (https://deno.land/x/[email protected]/mod.js:1588:15)
    at https://deno.land/x/[email protected]/mod.js:1234:28
    at runOnEndCallbacks (https://deno.land/x/[email protected]/mod.js:1017:63)
    at buildResponseToResult (https://deno.land/x/[email protected]/mod.js:1232:7)
    at https://deno.land/x/[email protected]/mod.js:1341:14
    at https://deno.land/x/[email protected]/mod.js:649:9
    at handleIncomingPacket (https://deno.land/x/[email protected]/mod.js:746:9)
    at readFromStdout (https://deno.land/x/[email protected]/mod.js:615:7)
    at https://deno.land/x/[email protected]/mod.js:1867:11

npm deps, with dependencies on node libraries are not handled properly

I use EasyMde which depends on typo-js. when run locally typo-js normally falls back to node apis and runs var fs = require("fs"); this trips up esbuild_deno_loader which complains it should be namespaced and fails. namespacing this validly complains that i should target nodejs and not web, I know that this won't be executed and normally is treeshaken out but the plugin doesn't seem to be context aware. Would it be possible to force the loader to ignore unresolvable deps?

readme example doesn't work, also undefined `Deno` objects appear in output

the example in the readme is broken (.. instead of ... and denoPlugins isn't in the imported target)

I've got it to work with small tweaks

import * as esbuild from "https://deno.land/x/[email protected]/mod.js";

import { NodeModulesPolyfillPlugin } from "npm:@esbuild-plugins/node-modules-polyfill";
import { denoPlugin } from "https://deno.land/x/[email protected]/mod.ts";

// Import the WASM build on platforms where running subprocesses is not
// permitted, such as Deno Deploy, or when running without `--allow-run`.
// import * as esbuild from "https://deno.land/x/[email protected]/wasm.js";

const result = await esbuild.build({
  plugins: [
    NodeModulesPolyfillPlugin({ polyfills: { crypto: true } }),
    denoPlugin(),
  ],
  entryPoints: ["../portal/client/src/index.ts"],
  outfile: "./out.js",
  bundle: true,
  format: "esm",
});
console.log(result);
esbuild.stop();

but now I'm getting a result which has many Deno object references, and these are undefined in a browser environment.

Am I missing something obvious?

Invalid cross-device link when shipping npm specified modules to browser

Bundling in Fresh with npm specifiers has this issue when /tmp and home are on two different filesystems:

      detail: Error: Invalid cross-device link (os error 18): link '/var/home/ewired/.cache/deno/npm/registry.npmjs.org/preact/10.15.1/LICENSE' -> '/tmp/68aa0db9/LICENSE'
    at async Object.link (ext:deno_fs/30_fs.js:401:3)
    at async linkRecursive (https://deno.land/x/[email protected]/src/loader_native.ts:165:5)
    at async linkRecursive (https://deno.land/x/[email protected]/src/loader_native.ts:162:7)
    at async NativeLoader.#nodeModulesDirForPackageInner (https://deno.land/x/[email protected]/src/loader_native.ts:126:5)
    at async NativeLoader.nodeModulesDirForPackage (https://deno.land/x/[email protected]/src/loader_native.ts:80:17)
    at async onResolve (https://deno.land/x/[email protected]/src/plugin_deno_loader.ts:261:28)
    at async requestCallbacks.on-resolve (https://deno.land/x/[email protected]/mod.js:1336:22)
    at async handleRequest (https://deno.land/x/[email protected]/mod.js:699:13) {
        code: "EXDEV"

Option to filter out protocols

I'd like the option of, after resolving import_map links, not bundling external dependencies (http). Would it make sense to add an option for this (AFAIK the externals options of esbuild doesn't cover this)?

I could create a PR if needed. The idea would be that you could have a new option where you specify protocols that are external. For example

esbuild.build({
  // ...
  plugins: [denoPlugin({ importMapURL, externals: ['https:']})]
}):

When is the new version going to come out?

For me to use this deno plugin, I am also forced to use the same version of esbuild that it uses. Latest release version being 0.6.0 and 0.15.10. Esbuild is currently at 0.17.15. So I'm really just wondering when you plan to release the next version of the plugin so I can use the latest version of esbuild as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.