UserScriptをbundleするDeno script
べつにコピーしてこなくても直接実行できたぽい
使い方
以下を実行する
shdeno run --allow-net=raw.githubusercontent.com,scrapbox.io --allow-read --allow-write --allow-run --allow-env --unstable https://scrapbox.io/api/code/yosider-scripts/UserScriptをbundleするDeno_script/build.ts filename.js --bundle --minify --outfile=filename.min.js --external=xxx --external=yyy --import-map=map.json
例
shdeno run --allow-net=raw.githubusercontent.com,registry.npmjs.org,scrapbox.io --allow-read --allow-write --allow-run --allow-env --unstable https://scrapbox.io/api/code/yosider-scripts/UserScriptをbundleするDeno_script/build.ts https://scrapbox.io/api/code/villagepump/yosider/script.js --bundle --minify --external=../preact@10.5.13/script.js --external=../preact@10.5.13/hooks.js --external=../htm@3.0.4/preact/script.js --external=../scrapbox-dom-accessor/script.js | xsel
code
bundle対象(entryFilePathが指すscrapbox上のscript.js)の中身を更新しても反映されない気がする
cacheが使われている?
~/.cache/deno/deps/https/scrapbox.io
を削除してみたりしたが変わらず
scrapboxのページ名を変えれば反映される
~/cache/deps/https/scrapbox.io
を削除する
~/.cache
ではないので注意
実行ファイルを更新したときは -r
をつけると更新を反映できる
build.tsimport { run } from './script.ts';
import { parse } from 'https://deno.land/std@0.200.0/flags/mod.ts';
const {_: [entryFilePath], importMap, external, ...rest} = parse(Deno.args);
if (typeof entryFilePath === 'number') throw Error('entryFilePath must be string');
let imports: {[key: string]: string} = {};
if (importMap) {
if (/^https?:\/\//.test(importMap)) {
const res = await fetch(importMap);
imports = await res.json();
} else {
imports = JSON.parse(await Deno.readTextFile(importMap));
}
}
await run(entryFilePath, imports, {external, ...rest});
update 'cache'
mod.tsimport { Plugin } from 'https://deno.land/x/esbuild@v0.19.2/mod.d.ts'
import * as Cache from 'https://deno.land/x/cache@0.2.13/mod.ts'
import { resolve } from 'https://deno.land/x/importmap@0.1.4/mod.ts'
import { join } from 'https://deno.land/std@0.200.0/path/mod.ts'
//prettier-ignore
type Loader = 'js' | 'jsx' | 'ts' | 'tsx' | 'css' | 'json' | 'text' | 'base64' | 'file' | 'dataurl' | 'binary' | 'default';
interface Config {
importmap: { imports: { [key: string]: string } }
directory: string
}
export function cache({ importmap = { imports: {} }, directory }: Config): Plugin {
Cache.configure({ directory })
return {
name: 'deno-cache',
setup(build) {
build.onResolve({ filter: /.*/ }, async (args) => {
if (build.initialOptions.external?.includes(args.path)) return {external: true};
const resolvedPath = resolve(args.path, importmap)
if (resolvedPath.startsWith('http')) {
return {
path: resolvedPath,
namespace: 'deno-cache',
}
}
if (args.namespace === 'deno-cache') {
return {
path: new URL(resolvedPath, args.importer).toString(),
namespace: 'deno-cache',
}
}
return { path: join(args.resolveDir, resolvedPath) }
})
build.onLoad({ filter: /.*/, namespace: 'deno-cache' }, async (args) => {
const file = await Cache.cache(args.path, undefined, 'deps')
const contents = await Deno.readTextFile(file.path)
const ext = file.meta.url.split('.').pop() as Loader
const loader = ext.match(/"j|tsx?$/) ? ext : 'js'
return { contents, loader }
})
},
}
}
script.tsimport { exists } from "https://deno.land/std@0.200.0/fs/mod.ts";
import { build, stop } from 'https://deno.land/x/esbuild@v0.19.2/mod.js';
import type { BuildOptions, BuildResult } from 'https://deno.land/x/esbuild@v0.19.2/mod.js';
// import { cache } from 'https://raw.githubusercontent.com/takker99/esbuild-plugin-cache/master/deno/mod.ts';
import { cache } from './mod.ts';
// 特定のpropertyを削るやつ
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export async function run(filename: string, imports: {[key: string]: string}, {external, ...rest }: Omit<BuildOptions, 'entryPoints' | 'platform' | 'plugins'>) {
let useTempFile = false;
let result: BuildResult | undefined = undefined;
try {
if (/^https?:\/\//.test(filename)) {
const tempname = `index-${Math.random()}.ts`;
await Deno.writeTextFile(tempname, `import '${filename}';export * from '${filename}';`);
filename = tempname;
useTempFile = true;
}
const options: BuildOptions = {
entryPoints: [filename],
platform: 'neutral',
plugins: [cache({directory: './cache', importmap: {imports}})],
external: Array.isArray(external) ? external : (external ? [external] : []),
...rest
};
result = await build(options);
stop();
} catch(e) {
throw e;
}finally {
//後始末
if (useTempFile) await Deno.remove(filename);
if (await exists('./cache')) await Deno.remove('./cache', { recursive: true });
}
return result;
}
const {code} =
をコメントアウト
externalを指定しなかったせい?
未検証
消し忘れとのこと
生成したコードの書き込み先( --outfile
)を指定しない場合のみ code
が戻り値に生える
txterror: TS2339 [ERROR]: Property 'code' does not exist on type 'BuildResult'.
const {code} =
~~~~
at https://scrapbox.io/api/code/yosider-scripts/UserScript%E3%82%92bundle%E3%81%99%E3%82%8BDeno_script/build.ts:24:8