deno bundleの代替コード
実装
$ deno run -A https://scrapbox.io/api/code/takker/deno_bundleの代替コード/build.ts
2024-02-14
12:34:15 依存関係表示プログラムは info.ts
に移した
12:31:36
deno-cliffyの
ansi
を使って、infoを再描画できるようにしてみようとしたのだが、うまく消えなかったので断念した
build.tsimport { build, stop } from "https://deno.land/x/esbuild@v0.20.0/mod.js";
import {
denoResolverPlugin,
denoLoaderPlugin
} from "https://deno.land/x/esbuild_deno_loader@0.9.0/mod.ts";
const result = await build({
plugins: [denoResolverPlugin(), denoLoaderPlugin()],
entryPoints: [Deno.args[0]],
bundle: true,
write: false,
format: "esm",
minify: true,
charset: "utf8",
});
console.log(result.outputFiles[0].text);
stop();
denoResolverPlugin()
を通した後は、 OnResolveArgs .importer
が消えてしまう
denoResolverPlugin()
の前にいれると、依存関係が保存された処理前の OnLoadArgs
と、処理後の OnLoadArgs
の両方を取得できる
info.tsimport { build, stop, Plugin } from "https://deno.land/x/esbuild@v0.20.0/mod.js";
import {
denoResolverPlugin,
denoLoaderPlugin
} from "https://deno.land/x/esbuild_deno_loader@0.9.0/mod.ts";
import { gray } from "https://deno.land/std@0.215.0/fmt/colors.ts";
import { toFileUrl } from "https://deno.land/std@0.213.0/path/mod.ts";
/** keyが親ファイルパス, valueがそのファイルでimportしたファイルのパスリスト */
const ancestors = new Map<string, string[]>;
let entryPoint = "";
function* makeTree(
parent: string,
// parentからの相対URLで表示したいときtrue
relative?: boolean,
viewedPath?: Set<string>,
): Generator<string> {
const childs = ancestors.get(parent);
if (!childs) return;
viewedPath ??= new Set<string>();
viewedPath.add(parent);
for (let i = 0; i < childs.length; i++) {
const child = childs[i];
const relativePath = decodeURIComponent(
relative ? makeRelative(new URL(parent), new URL(child)) : child,
);
const lastOne = i + 1 === childs.length;
const branch = lastOne ? "└─ " : "├─ ";
// 一度読み込んだものは灰色で表示する
if (viewedPath.has(child)) {
yield `${branch}${gray(relativePath)}`;
continue;
}
yield `${branch}${relativePath}`;
viewedPath.add(child);
const indent = lastOne ? " " : "│ ";
for (const line of makeTree(child, relative ?? false, viewedPath)) {
yield `${indent}${line}`;
}
}
}
const listPlugin: Plugin = {
name: "list-imports",
setup: ({ onResolve, resolve }) => {
onResolve({ filter: /.*/, }, (args) => {
/**
* The following codes come from https://github.com/lucacasonato/esbuild_deno_loader/blob/0.9.0/src/plugin_deno_resolver.ts
* Copyright (c) 2021 Luca Casonato. All rights reserved. MIT license.
*/
//
// The first pass resolver performs synchronous resolution. This
// includes relative to absolute specifier resolution and import map
// resolution.
// We have to first determine the referrer URL to use when resolving
// the specifier. This is either the importer URL, or the resolveDir
// URL if the importer is not specified (ie if the specifier is at the
// root).
let referrer: URL;
if (args.importer !== "") {
if (args.namespace === "") {
throw new Error("[assert] namespace is empty");
}
referrer = new URL(`${args.namespace}:${args.importer}`);
} else if (args.resolveDir !== "") {
referrer = new URL(`${toFileUrl(args.resolveDir).href}/`);
} else {
return undefined;
}
// We can then resolve the specifier relative to the referrer URL. If
// an import map is specified, we use that to resolve the specifier.
const resolved = new URL(args.path, referrer);
if (args.kind === "entry-point") {
entryPoint = resolved.href;
} else {
ancestors.set(
referrer.href,
[...(ancestors.get(referrer.href) ?? []), resolved.href]
);
}
return undefined;
});
},
};
await build({
plugins: [listPlugin, denoResolverPlugin(), denoLoaderPlugin()],
entryPoints: [Deno.args[0]],
bundle: true,
write: false,
format: "esm",
minify: true,
charset: "utf8",
});
stop();
console.log(entryPoint);
for (const line of makeTree(entryPoint)) {
console.log(line);
}
長すぎるコードを読み込むときに使う
$ deno run -r=https://scrapbox.io -A https://scrapbox.io/api/code/takker/deno_bundleの代替コード/json.ts
json.tsimport { build, stop } from "https://deno.land/x/esbuild@v0.20.0/mod.js";
import {
denoResolverPlugin,
denoLoaderPlugin
} from "https://deno.land/x/esbuild_deno_loader@0.9.0/mod.ts";
const result = await esbuild.build({
plugins: [denoResolverPlugin(), denoLoaderPlugin()],
entryPoints: [Deno.args[0]],
bundle: true,
write: false,
format: "esm",
minify: true,
charset: "utf8",
});
const pages = [{
title: Deno.args[1],
lines: [
Deno.args[1],
"",
"code:mod.js",
...result.outputFiles[0].text.split("\n").map((line) => ` ${line}`),
],
}];
console.log(JSON.stringify({pages}));
stop();