Skip to content

Instantly share code, notes, and snippets.

@adamziel
Created June 23, 2025 22:28
Show Gist options
  • Select an option

  • Save adamziel/624cc21a5e8575c1dce14c760c97ee31 to your computer and use it in GitHub Desktop.

Select an option

Save adamziel/624cc21a5e8575c1dce14c760c97ee31 to your computer and use it in GitHub Desktop.
esbuild support for ?url
// build.mjs
import esbuild from 'esbuild'
import importUrlPlugin from './import-url-plugin.ts'; // the plugin shown earlier
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
outdir: 'build',
format: 'esm',
platform: 'browser', // change to 'node' if you bundle for Node
publicPath: '/assets/', // base path your server uses to serve static files
plugins: [importUrlPlugin()]
})
this is a file
import fs from 'fs';
import path from 'path';
import { createHash } from 'crypto';
import type { Plugin } from 'esbuild';
function importUrlPlugin(): Plugin {
return {
name: 'import-url',
setup(build) {
const root = build.initialOptions.absWorkingDir ?? process.cwd();
build.onResolve({ filter: /\?url$/ }, async args => {
const spec = args.path.replace(/\?url$/, '');
const resolved = await build.resolve(spec, {
resolveDir: args.resolveDir,
kind: args.kind,
importer: args.importer
});
if (resolved.errors.length) return { errors: resolved.errors };
const abs = resolved.path;
const rel = path
.relative(root, abs)
.split(path.sep)
.join('/'); // posix-style for consistency
return {
namespace: 'url-import',
path: rel, // what shows up after “url-import:”
pluginData: { abs } // keep real location for onLoad
};
});
build.onLoad({ filter: /.*/, namespace: 'url-import' }, async args => {
const absPath: string =
(args.pluginData as { abs: string }).abs ?? path.join(root, args.path);
const buf = await fs.promises.readFile(absPath);
const hash = createHash('sha1').update(buf).digest('hex').slice(0, 8);
const ext = path.extname(absPath);
const base = path.basename(absPath, ext);
const fileName = `${base}-${hash}${ext}`;
const outDir =
build.initialOptions.outdir ??
path.dirname(build.initialOptions.outfile ?? 'dist');
await fs.promises.mkdir(outDir, { recursive: true });
await fs.promises.writeFile(path.join(outDir, fileName), buf);
return {
contents: `export default new URL(${JSON.stringify(
fileName
)}, import.meta.url).href;`,
loader: 'js'
};
});
}
};
}
export default importUrlPlugin;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// url-import:src/icudata.dat
var icudata_exports = {};
__export(icudata_exports, {
default: () => icudata_default
});
var icudata_default;
var init_icudata = __esm({
"url-import:src/icudata.dat"() {
icudata_default = new URL("icudata-1c8c6df5.dat", import.meta.url).href;
}
});
// src/index.ts
var imageUrl = (await Promise.resolve().then(() => (init_icudata(), icudata_exports))).default;
export {
imageUrl
};
// @ts-ignore
const imageUrl = (await import('./icudata.dat?url')).default;
export { imageUrl };
{
"name": "tmp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "node build.mjs"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment