Skip to main content
Deno 2 is finally here 🎉️
Learn more

esbuild Cache Plugin for Deno

esbuild Cache Plugin for Deno is an esbuild plugin to resolve remote (HTTP/HTTPS) and even npm modules using Deno’s cache.

Features

  • Resolves http/https imports to Deno’s cache.
  • Resolves npm module imports to Deno’s cache.
    • Of course resolving imports and requires in the npm module.
    • Supports polyfill for npm modules.
  • Resolves importmaps.
  • Customizing loader of remote files.

Usage

Minimum Example

import { esbuild } from 'https://deno.land/x/esbuild';
import esbuildCachePlugin from 'https://deno.land/x/esbuild_plugin_cache_deno';
import lockMap from './lock.json' assert { type: 'json' };

// To use deno.lock file, you should parse the file manually
// const lockMap = JSON.parse(Deno.readTextFileSync('./deno.lock'));

const config: esbuild.BuildOptions = {
  entryPoints: [ 'src/main.ts' ],
  bundle: true,
  outdir: './dist',
  platform: 'browser',
  plugins: [
    esbuildCachePlugin({
      lockMap,
      denoCacheDirectory: '/home/[user]/.cache/deno'
    }),
  ],
};

await esbuild.build(config);

await esbuild.stop();

And don’t forget to cache src/main.ts with Deno:

$deno cache --lock=./test/lock.json --lock-write ./src/main.ts
# or to use deno.lock:
# $deno cache ./src/main.ts

The you can use remote imports like:

// src/main.ts
import * as react from "https://esm.sh/react";

console.log(react.version);

Getting Deno’s Cache Path

There’s a utility function to get DENO_PATH from output of deno info command and you can use the pass as denoCacheDirectory.

const denoPath = await esbuildCachePlugin.util.getDenoDir();

Alternatively, you can pass them from CLI argument using shell scripts.

Using npm Modules

You can use npm modules just like using them in Deno:

// src/main.ts
import * as preact from "npm:preact";
import * as preact from "npm:/preact/hooks";

You can replace or remove some modules like Node.js’s core modules using import-maps and custom loader (details are in the next section).

esbuildCachePlugin({
  lockMap,
  denoCacheDirectory: '/home/[user]/.cache/deno',
  importmap: {
    imports: {
      // replace "http" module to polyfill
      "node:http": "/src/polyfill/http.ts",
    },
  },
  loaderRules: [
    // remote "util" module
    { test: /^node:util/, loader: 'empty' },
  ],
}),

Using Import Maps

You can pass import maps with importmap option.

esbuildCachePlugin({
  lockMap,
  denoCacheDirectory: '/home/[user]/.cache/deno',
  importmap: {
    imports: {
      react: "https://esm.sh/react",
    },
  },
}),

Then you can use the module specifier like:

// src/main.ts
import * as react from "react";

console.log(react.version);

Of cause you can use your import maps you’re using for the intellisense:

import importmap from './import_map.json' assert type { type: 'json' };

// ...

esbuildCachePlugin({
  lockMap,
  denoCacheDirectory: '/home/[user]/.cache/deno',
  importmap,
}),

Also you can disguise import map’s path for import maps not located in the CWD:

import importmap from './src/import_map.json' assert type { type: 'json' };

// ...

esbuildCachePlugin({
  lockMap,
  denoCacheDirectory: '/home/[user]/.cache/deno',
  importmap,
  importmapBasePath: 'src/',
}),

Customizing loaders

You can specify loaders for files with loaderRules option. The plugin uses default loader as the esbuild, you may not need to use this option.

esbuildCachePlugin({
  lockMap,
  denoCacheDirectory: '/home/[user]/.cache/deno',
  loaderRules: [
    { test: /\.css$/, loader: 'css' },
  ],
}),

npm Module Support

Reference: Modules: Packages | Node.js v20.2.0 Documentation

Specification Support
Main entry point
Subpath exports Partial
Subpath imports -
Conditional exports
Nested conditions
Resolving user conditions -
Package self-referencing

Subpath exports support

Reference: Package exports | webpack

Specification Support
"." property
Normal property
Property ending with /
Property ending with * -
Alternatives -
Abbreviation only path
Abbreviation only conditions
Conditional syntax
Nested conditional syntax
Conditions order -
"default" condition
Path order -
Error when not mapped -
Error when mixind conditions and paths