Skip to content

Instantly share code, notes, and snippets.

@composite
Created January 8, 2026 11:45
Show Gist options
  • Select an option

  • Save composite/2d9a408ad6bafe10cd73601c4411573a to your computer and use it in GitHub Desktop.

Select an option

Save composite/2d9a408ad6bafe10cd73601c4411573a to your computer and use it in GitHub Desktop.
node.js `Worker` with `.ts` in dev, real life usage with Bree, `?modulePath` plugin for Vite and howto... you can make all for one!
import { parentPort } from 'node:worker_threads';
const heavyTask = (): string => {
return "Task Completed in TypeScript! and it also works after built Javascript!";
};
parentPort?.postMessage(heavyTask());
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import Bree from 'bree';
import devplugin from './devplugin';
import childpath from './bree.child?modulePath';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const DEV = import.meta.env.DEV;
Bree.extend(devplugin);
const bree = new Bree({
jobs: [
{
name: 'child-worker',
path: childpath,
cron: '*/15 * * * *',
},
],
});
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { Worker } from 'node:worker_threads';
import type { PluginFunc } from 'bree';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const devplugin: PluginFunc = (opts, Bree: any) => {
if (import.meta.env.DEV) {
const init = Bree.prototype.init;
Bree.prototype.init = async function () {
if (!this.config.acceptedExtensions.includes('.ts'))
this.config.acceptedExtensions.push('.ts');
return init.call(this);
};
const createWorker = Bree.prototype.createWorker;
Bree.prototype.createWorker = function (filename, options) {
if (filename.endsWith('.ts')) {
console.log('Delegating worker with filename "' + filename + '"');
options.workerData.JOB__PATH = filename;
return new Worker(resolve(__dirname, 'devworker.mjs'), options);
}
return createWorker(filename, options);
};
}
};
export default devplugin;
import { workerData } from 'node:worker_threads';
import { createServer } from 'vite';
import { ViteNodeRunner } from 'vite-node/client';
import { ViteNodeServer } from 'vite-node/server';
import { installSourcemapsSupport } from 'vite-node/source-map';
// create vite server
const server = await createServer({
optimizeDeps: {
// It's recommended to disable deps optimization
noDiscovery: true,
include: undefined,
},
});
// create vite-node server
const node = new ViteNodeServer(server);
// fixes stacktraces in Errors
installSourcemapsSupport({
getSourceMap: (source) => node.getSourceMap(source),
});
// create vite-node runner
const runner = new ViteNodeRunner({
root: server.config.root,
base: server.config.base,
// when having the server and runner in a different context,
// you will need to handle the communication between them
// and pass to this function
fetchModule(id) {
return node.fetchModule(id);
},
resolveId(id, importer) {
return node.resolveId(id, importer);
},
});
// execute the file
await runner.executeFile(workerData.JOB__PATH);
// close the vite server
await server.close();
/// <reference types="vite/client" />
declare module '*?modulePath' {
const src: string;
export default src;
}
import MagicString from 'magic-string';
import { URL, URLSearchParams } from 'node:url';
import path from 'node:path';
import fs from 'node:fs/promises';
import { createHash } from 'node:crypto';
import type { Plugin, InlineConfig, Rolldown } from 'vite';
import { build as viteBuild, mergeConfig } from 'vite';
function toRelativePath(filename: string, importer: string): string {
const relPath = path.posix.relative(path.dirname(importer), filename);
return relPath.startsWith('.') ? relPath : `./${relPath}`;
}
function parseRequest(id: string): Record<string, string> | null {
try {
const { search } = new URL(id, 'file:');
if (!search) {
return null;
}
return Object.fromEntries(new URLSearchParams(search));
} catch {
return null;
}
}
function getHash(text: string): string {
return createHash('sha256').update(text).digest('hex').substring(0, 8);
}
const queryRE = /\?.*$/s;
const hashRE = /#.*$/s;
const cleanUrl = (url: string): string =>
url.replace(hashRE, '').replace(queryRE, '');
const modulePathRE = /__VITE_MODULE_PATH__([\w$]+)__/g;
// ESM shim for __dirname
const CJSShim = `
import __cjs_url__ from 'node:url';
import __cjs_path__ from 'node:path';
const __filename = __cjs_url__.fileURLToPath(import.meta.url);
const __dirname = __cjs_path__.dirname(__filename);
`;
interface ModulePathPluginOptions {
/**
* Vite configuration to use for bundling modules
*/
bundleConfig?: InlineConfig;
}
interface EmittedChunk {
fileName: string;
code: string;
referenceId: string;
}
/**
* Resolve `?modulePath` import and return the module bundle path.
*/
export default function modulePathPlugin(
options: ModulePathPluginOptions = {}
): Plugin {
let sourcemap = false;
let viteConfig: InlineConfig;
let rootDir: string;
let outDir: string;
let isDev = false;
const assetCache = new Map<string, string>(); // original path -> hashed fileName
const chunksToWrite = new Map<string, EmittedChunk>(); // fileName -> chunk data
const chunkShims = new Set<string>();
const fileNameMap = new Map<string, string>(); // original fileName -> hashed fileName
return {
name: 'vite:module-path',
enforce: 'pre',
configResolved(config) {
isDev = config.command === 'serve';
sourcemap = !!config.build.sourcemap;
rootDir = config.root;
outDir = path.resolve(rootDir, config.build.outDir);
if (!isDev) {
viteConfig = {
root: config.root,
mode: config.mode,
configFile: false,
logLevel: 'warn',
...options.bundleConfig,
build: {
...options.bundleConfig?.build,
write: false,
lib: undefined,
rollupOptions: {
...options.bundleConfig?.build?.rollupOptions,
output: {
format: 'es',
entryFileNames: '[name].js',
chunkFileNames: '[name]-[hash].js',
assetFileNames: '[name]-[hash][extname]',
...(options.bundleConfig?.build?.rollupOptions?.output as any),
},
},
},
};
console.log(`[module-path] Output directory: ${outDir}`);
}
},
buildStart() {
if (!isDev) {
assetCache.clear();
chunksToWrite.clear();
chunkShims.clear();
fileNameMap.clear();
}
},
async resolveId(id, importer) {
const query = parseRequest(id);
if (query && typeof query.modulePath === 'string') {
// dev 모드에서는 절대 경로로 변환
if (isDev) {
const cleanPath = cleanUrl(id);
// 절대 경로가 아니면 importer 기준으로 resolve
let resolvedPath: string;
if (path.isAbsolute(cleanPath)) {
resolvedPath = cleanPath;
} else if (importer) {
resolvedPath = path.resolve(path.dirname(importer), cleanPath);
} else {
resolvedPath = path.resolve(rootDir, cleanPath);
}
console.log(`[module-path] Resolved: ${id} -> ${resolvedPath}`);
// 절대 경로에 플래그 추가
return resolvedPath + '?__modulePath__=true';
}
}
return null;
},
async load(id) {
const query = parseRequest(id);
// Dev 모드: 파일을 실행하지 않고 경로만 반환
if (isDev && query && query.__modulePath__ === 'true') {
const cleanPath = cleanUrl(id);
console.log(
`[module-path] Dev mode: returning file path for ${cleanPath}`
);
// 절대 경로를 그대로 반환 (dev 모드에서는 소스 파일 직접 사용)
return `export default ${JSON.stringify(cleanPath)}`;
}
// Build 모드: 번들링 수행
if (!isDev && query && typeof query.modulePath === 'string') {
const cleanPath = cleanUrl(id);
// 이미 처리된 파일인지 확인
if (assetCache.has(cleanPath)) {
const hashedFileName = assetCache.get(cleanPath)!;
const referenceId = chunksToWrite.get(hashedFileName)?.referenceId;
if (referenceId) {
console.log(
`[module-path] Reusing cached bundle: ${cleanPath} -> ${hashedFileName}`
);
const refId = `__VITE_MODULE_PATH__${referenceId}__`;
return `
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
export default join(__dirname, ${refId})`;
}
}
console.log(`[module-path] Bundling module: ${cleanPath}`);
try {
const { outputChunks } = await bundleModule(cleanPath, viteConfig);
if (outputChunks.length === 0) {
throw new Error(`No output chunks generated for: ${cleanPath}`);
}
console.log(
`[module-path] Generated ${outputChunks.length} chunk(s)`
);
// 메인 청크에 대해 고유한 파일명 생성
const mainChunk = outputChunks[0];
const mainChunkHash = getHash(cleanPath + mainChunk.code);
const ext = path.extname(mainChunk.fileName);
const baseName = path.basename(mainChunk.fileName, ext);
const hashedMainFileName = `${baseName}-${mainChunkHash}${ext}`;
// 파일명 매핑 저장
fileNameMap.set(mainChunk.fileName, hashedMainFileName);
console.log(
`[module-path] Main chunk: ${mainChunk.fileName} -> ${hashedMainFileName}`
);
let mainReferenceId: string | undefined;
// 모든 청크를 저장
for (const chunk of outputChunks) {
const originalFileName = chunk.fileName;
const isMainChunk = chunk === mainChunk;
// 메인 청크는 이미 해시된 이름 사용, 나머지는 원본 이름 또는 이미 해시된 이름 사용
const fileName = isMainChunk
? hashedMainFileName
: fileNameMap.get(originalFileName) || originalFileName;
// 동일한 파일이 이미 처리되었는지 확인
if (chunksToWrite.has(fileName)) {
console.log(`[module-path] Skipping duplicate: ${fileName}`);
if (isMainChunk) {
mainReferenceId = chunksToWrite.get(fileName)!.referenceId;
}
continue;
}
// 청크의 import 경로를 수정 (다른 청크를 참조하는 경우)
let code =
chunk.type === 'chunk' ? chunk.code : (chunk.source as string);
if (chunk.type === 'chunk') {
// import 문에서 다른 청크를 참조하는 경우 해시된 이름으로 변경
for (const [original, hashed] of fileNameMap) {
if (original !== hashed) {
const importRegex = new RegExp(
`(from\\s+['"]\\.\\/)(${original.replace('.', '\\.')})(['"])`,
'g'
);
code = code.replace(importRegex, `$1${hashed}$3`);
}
}
}
// emitFile로 참조 ID 생성
const referenceId = this.emitFile({
type: 'asset',
fileName: fileName,
source: code,
});
if (isMainChunk) {
mainReferenceId = referenceId;
assetCache.set(cleanPath, fileName);
}
// 나중에 직접 쓰기 위해 저장
chunksToWrite.set(fileName, {
fileName,
code,
referenceId,
});
if (chunk.type === 'chunk') {
chunkShims.add(fileName);
}
console.log(`[module-path] Processed: ${fileName}`);
}
if (!mainReferenceId) {
throw new Error('Failed to process main chunk');
}
const refId = `__VITE_MODULE_PATH__${mainReferenceId}__`;
return `
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
export default join(__dirname, ${refId})`;
} catch (error) {
console.error(`[module-path] Bundle error:`, error);
throw error;
}
}
},
renderChunk(code, chunk) {
if (isDev) return null;
let modified = false;
let s: MagicString | undefined;
if (code.match(modulePathRE)) {
s = new MagicString(code);
let match: RegExpExecArray | null;
modulePathRE.lastIndex = 0;
while ((match = modulePathRE.exec(code))) {
const [full, hash] = match;
const filename = this.getFileName(hash);
const outputFilepath = toRelativePath(filename, chunk.fileName);
const replacement = JSON.stringify(outputFilepath);
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true,
});
modified = true;
}
}
if (chunkShims.has(chunk.fileName) && !code.includes('const __dirname')) {
s = s || new MagicString(code);
const importMatches = Array.from(
code.matchAll(/import\s+.*?from\s+['"][^'"]+['"]\s*;?/g)
);
const lastImport = importMatches[importMatches.length - 1];
const insertPos = lastImport
? lastImport.index! + lastImport[0].length
: 0;
s.appendRight(insertPos, CJSShim);
modified = true;
}
if (modified && s) {
return {
code: s.toString(),
map: sourcemap ? s.generateMap({ hires: 'boundary' }) : null,
};
}
return null;
},
async writeBundle(options, bundle) {
if (isDev) return;
console.log(
`[module-path] Writing ${chunksToWrite.size} additional chunk(s)`
);
for (const [fileName, chunkData] of chunksToWrite) {
const outputPath = path.resolve(outDir, fileName);
try {
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, chunkData.code, 'utf-8');
console.log(`[module-path] Written: ${fileName}`);
} catch (error) {
console.error(`[module-path] Failed to write ${fileName}:`, error);
throw error;
}
}
console.log(`[module-path] All chunks written successfully`);
},
};
}
async function bundleModule(
input: string,
baseConfig: InlineConfig
): Promise<{ outputChunks: any[] }> {
const entryName = path.basename(input, path.extname(input));
const buildConfig = mergeConfig(baseConfig, {
build: {
write: false,
emptyOutDir: false,
rollupOptions: {
input: {
[entryName]: input,
},
preserveEntrySignatures: 'strict',
},
},
}) as InlineConfig;
try {
const bundles = (await viteBuild(buildConfig)) as Rolldown.RolldownOutput;
if (!bundles || !bundles.output) {
throw new Error('No output from vite build');
}
const outputChunks = bundles.output;
return { outputChunks };
} catch (error) {
console.error('[module-path] Bundle error:', error);
throw error;
}
}
export default defineConfig(({ mode, command }) => {
return {
plugins: [
modulePathPlugin({
bundleConfig: {
build: {
target: 'node20',
minify: false,
ssr: true, // SSR mode should be enabled!
rollupOptions: {
external: [/* CommonJS, native related dependencies here. */],
},
},
ssr: {
external: [/* CommonJS, native related dependencies here. */],
}
},
}),
// ... other plugins ...
],
build: {
target: 'esnext',
copyPublicDir: false,
rollupOptions: {
output: {
format: 'es',
}
},
},
resolve,
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment