NAPI / JavaScript API
@zntc/core 는 ZNTC 엔진을 Node.js / Bun 에서 in-process 호출하는 NAPI 바인딩입니다. CLI 와 동일한 옵션을 프로그래머블하게 사용할 수 있습니다.
TypeDoc 자동 생성 레퍼런스: 모든 export 의 상세 type 시그니처는 사이드바의 API Reference 그룹 참고. 이 페이지는 사용자 친화적 요약입니다.
아키텍처
섹션 제목: “아키텍처”@zntc/core 는 JS 표면 (사용자 API + plugin dispatcher) + NAPI bridge + Zig native engine 3 layer 구조입니다.
| Layer | 책임 |
|---|---|
JS (packages/core/index.ts) | 사용자 API surface, 옵션 정규화, plugin lifecycle 호출 |
| Plugin Dispatcher | hook 등록 / 매 모듈마다 NAPI threadsafe-fn 통해 JS callback 호출 |
NAPI bridge (packages/core/src/napi_entry.zig → zntc.node) | JS↔Zig boundary. JSON payload 변환, plugin dispatch |
Zig engine (src/) | Scanner → Parser → Semantic → Transformer → Codegen 단일 흐름 + Bundler → Linker → Tree-shaker → Emitter 번들 흐름 |
JS plugin 의 onResolve / onLoad 등은 native bundler 가 모듈을 만나는 시점마다 NAPI threadsafe function 으로 JS dispatcher 를 깨워 호출 — Zig worker 가 응답을 기다리는 sync 모델 (Promise 결과까지 wait).
설치 + 초기화
섹션 제목: “설치 + 초기화”bun add @zntc/coreimport { init, close, transpile, build, watch } from "@zntc/core";
init(); // NAPI addon 로드 (한 번만)// ... 사용 ...close(); // 종료 시 cleanuptranspile(source, options)
섹션 제목: “transpile(source, options)”단일 파일 트랜스파일. 번들링 없이 TypeScript / JSX / Flow / 데코레이터 변환만.
import { transpile } from "@zntc/core";
const r = transpile("const x: number = 42;", { target: "es2020", jsx: "automatic", sourcemap: true,});
console.log(r.code); // "const x = 42;"console.log(r.map); // 소스맵 JSON핵심 옵션 (전체: Transpile 옵션):
target—es5/es2015–es2025/esnextjsx—classic/automatic/automatic-devflow— Flow 타입 스트리핑experimentalDecorators/emitDecoratorMetadataminifyWhitespace/minifyIdentifiers/minifySyntaxdefine—{ key: value }정적 치환sourcemap/sourcemapDebugIdstsconfigPath/tsconfigRawcache—TsconfigCache인스턴스 (autodiscover walk 캐시 재사용)
tokenize(source, options)
섹션 제목: “tokenize(source, options)”단일 파일을 lexer 로 토큰화. 파싱 없이 토큰 배열 반환.
import { tokenize } from "@zntc/core";
const tokens = tokenize("const x = 1;", { filename: "input.ts" });console.log(tokens[0]); // { kind, text, start, end, line, column, hasNewlineBefore }TokenizeToken 필드: kind / text / start / end / line / column / hasNewlineBefore.
TokenizeOptions: { filename?: string }.
TsconfigCache
섹션 제목: “TsconfigCache”tsconfig autodiscover walk 결과를 in-process 재사용하는 캐시. 다수 파일을 반복 transpile 하는
Vite / Rollup 플러그인 작성자에게 권장 — 파일당 5–10 fs syscall 절약. tsconfigPath / tsconfigRaw
명시 시 캐시는 무시됨.
import { TsconfigCache, transpile } from "@zntc/core";
using cache = new TsconfigCache(); // Symbol.dispose 자동 clearfor (const file of files) { transpile(read(file), { filename: file, cache });}console.log(cache.size); // 캐시된 entry 수cache.clear(); // 명시 비우기 (재사용 가능)configureProfile(profile, level?) / profileReport(format?)
섹션 제목: “configureProfile(profile, level?) / profileReport(format?)”Profile category 활성화 + 결과 출력. CLI --profile / --profile-level 의 NAPI 대응.
import { configureProfile, profileReport, transpile } from "@zntc/core";
configureProfile(["parse", "transform"], "summary");transpile(source, {});console.log(profileReport("table")); // "table" | "tree" | "json" | "csv"level: "summary" | "detailed" | "per-module" | "per-pass".
build(options) / buildSync(options)
섹션 제목: “build(options) / buildSync(options)”번들링. esbuild / Rollup / rolldown 호환 옵션.
import { build } from "@zntc/core";
const result = await build({ entryPoints: ["src/index.ts"], outdir: "dist", bundle: true, splitting: true, format: "esm", platform: "browser", minify: true, sourcemap: true, outputExports: "named", // CJS/UMD entry export 형식 inlineDynamicImports: false, // dynamic import 인라인 여부 (#2185) manualChunks: (id, meta) => { // record form 또는 함수형 if (id.includes("node_modules")) return "vendor"; return null; },});
console.log(`Built ${result.outputFiles.length} files`);buildSync() 는 동기 버전 — JS 플러그인 미지원 (스레드 모델 한계). 단순 단일 파일 빌드에 적합.
Array 형태 alias 도 미지원 (host RegExp 위임 — build() 사용).
번들 전용 옵션:
entryPoints— 진입점 배열outdir/outfilesplitting— code splittingpreserveModules/preserveModulesRootinlineDynamicImportsexternal—string[]또는 RegExpalias— 두 형태 (아래 참고)loader— 확장자별 로더 (아래 참고)manualChunks— 함수형 또는 record form (#2186)outputExports—"auto" | "named" | "default" | "none".default모드에 named 가 섞이면 warning + 빈 출력.banner/footer/intro/outroentryNames/chunkNames/assetNamesmetafile/analyzesourcemap/sourcemapMode("linked" | "external" | "inline")emitDiskSourcemap—false면.map디스크 쓰기 생략 →WatchHandle.getBundleSourceMap()lazy servelogLevel(silent | error | warning | info | debug | verbose) — throw 안 함,result.errors길이로 실패 판정logOverride/logLimitbrowserslist—string | string[]. 지정 시target보다 우선server—DevServerOptions(zntc dev/--serve기본값. CLI flag 가 우선)
alias 형태
섹션 제목: “alias 형태”// (1) Object — esbuild 형태. exact + prefix 매칭build({ alias: { react: "preact/compat" } });// "react" / "react/hooks" → "preact/compat" / "preact/compat/hooks"
// (2) Array — Vite 형태. RegExp find 지원, build() 만 가능build({ alias: [{ find: /^@\/(.*)$/, replacement: "./src/$1" }] });loader vocabulary
섹션 제목: “loader vocabulary”값으로 받는 로더: js | jsx | ts | tsx | json | css | file | dataurl | base64 | text | binary | copy | empty.
build({ loader: { ".png": "file", ".svg": "text", ".wasm": "binary" } });server (DevServerOptions)
섹션 제목: “server (DevServerOptions)”| 필드 | 의미 |
|---|---|
port | 리스닝 포트. CLI --port 가 override |
host | 호스트. true 면 0.0.0.0 (Vite 호환) |
strictPort | port 충돌 시 다음 port 시도 대신 종료 |
open | 시작 후 브라우저 자동 열기 |
React Native 관련 옵션
섹션 제목: “React Native 관련 옵션”platform: "react-native" 시 자동 활성화되는 항목 포함 — Hermes 호환 매트릭스 강제로 target /
browserslist 는 무시됨.
assetRegistry— Metro AssetRegistry 모듈 경로 (또는false로 비활성)silentConsoleErrorPatterns— 매칭되는console.error호출 silent swallow (RegExp source 배열)entryErrorGuard— entry trigger 호출을try/catch + ErrorUtils.reportFatalError로 wrap. RN 자동 활성strictExecutionOrder— 함수 선언 호이스팅 방지 (rolldown 동등). RN 자동 활성workletPluginVersion—react-native-worklets패키지 버전 문자열workletTransform— Reanimated worklet 변환. RN 자동 활성codegenTransform—*NativeComponent의codegenNativeComponentinline view config 치환. RN 자동 활성configurableExports—Object.defineProperty에configurable: true(RN/Hermes 호환)reactRefresh— React Fast Refresh 활성화devMode— 모듈을__zntc_register()팩토리 + HMR 런타임 주입rootDir— dev mode 모듈 ID 기준 경로collectModuleCodes— dev mode per-module code 수집 (HMR rebuild 용)moduleSpecifierMap—import { x } from 'lodash'→import x from 'lodash/x'등 cherry-pick 분해 매핑globals— Rollupoutput.globals. IIFE/UMD external → 글로벌 변수 매핑intro/outro— Rollupoutput.intro/outro. 포맷 wrapper 내부 코드 앞/뒤 삽입blockList— 해석 차단 패턴 (RegExp | string배열, MetroblockList호환)fallback— 일반 해석 실패 시에만 적용 ({ crypto: "crypto-browserify", fs: false })watchFolders— 그래프 밖 디렉토리 감시 추가 (Metro 호환)watchInclude/watchExclude—watchFoldersglob 화이트/블랙리스트
runtimePolyfills / runtimeTarget / coreJs
섹션 제목: “runtimePolyfills / runtimeTarget / coreJs”core-js 기반 런타임 API 폴리필 자동 주입. 값 형태:
runtimePolyfills: "off" | "auto" | "usage" | "entry" | RuntimePolyfillOptionsRuntimePolyfillOptions 필드: mode (auto | usage | entry) / provider ("core-js") /
targets (browserslist 쿼리) / coreJs (버전 문자열) / include[] / exclude[] / proposals (boolean).
coreJs top-level 옵션은 runtimePolyfills.coreJs 와 동일 역할.
compiler 네임스페이스
섹션 제목: “compiler 네임스페이스”라이브러리별 1st-party transform 설정 (@next/swc 호환 surface). babel-plugin-styled-components /
@emotion/babel-plugin 과 동일한 결과를 plugin 등록 없이 옵션만 켜서 얻습니다.
build({ compiler: { styledComponents: { displayName: true, ssr: true, minify: true }, emotion: { autoLabel: "dev-only", labelFormat: "[local]" }, },});StyledComponentsOptions: displayName / ssr / cssProp / fileName / meaninglessFileNames /
transpileTemplateLiterals / pure / minify / topLevelImportPaths / namespace / meta.
EmotionOptions: autoLabel ("always" | "dev-only" | "never" | boolean) / labelFormat / importMap /
sourceMap. (jsxImportSource 는 BuildOptions 의 동명 옵션으로 별도 지정.)
watch(options)
섹션 제목: “watch(options)”증분 빌드 watch 모드. 파일 변경 시 자동 rebuild.
onReady / onRebuild는 Promise를 반환할 수 있습니다. 플러그인 lifecycle은 초기 build와
매 rebuild마다 buildStart → buildEnd → onReady/onRebuild → closeBundle 순서로 호출됩니다.
import { watch } from "@zntc/core";
const handle = watch({ entryPoints: ["src/index.ts"], outdir: "dist", bundle: true, onReady: () => console.log("first build ready"), onRebuild: (event) => { console.log("rebuild", event.changed); // 변경된 파일 경로 배열 console.log("emit", event.phaseDurations?.emit); },});
handle.stop();WatchRebuildEvent 필드
섹션 제목: “WatchRebuildEvent 필드”success: boolean/error?: string— rebuild 결과changed?: string[]— 변경 감지된 파일 경로graphChanged?: boolean— module graph 위상 변경 여부updates?: Array<{ id, code, map? }>— HMR 모듈 단위 코드 (dev mode)bytes?: number/reparsedModules?: numberphaseDurations?: { ... }— 단계별 ms
phaseDurations 의 기본 phase: detect / graph / link / shake / emit / delta / total.
Sub-phase (profile: ["..."] 또는 ZNTC_PROFILE env 활성 시): scan / parse / resolve /
semantic / transform / codegen / metadata / graphBuild / graphWorker / graphDiscover /
graphFinalize / emitPolyfill / emitRefresh / emitOutput / emitMetafile / emitCss /
emitPrelude / emitModulePass / emitConcat / emitSourcemapFinalize.
2026-04-22 이전의
phaseDurations.parse/semantic은 사실graph/link+shake를 담은 레거시 이름이었으며 제거됨. 현재parse는 진짜 parser 시간만.
WatchHandle lazy sourcemap
섹션 제목: “WatchHandle lazy sourcemap”const handle = watch({ ..., sourcemap: true, emitDiskSourcemap: false });
// dev server 가 /bundle.js.map 요청 받을 때const bundleMap = handle.getBundleSourceMap(); // string | null
// dev server 가 /hmr-map/:moduleId 요청 받을 때const moduleMap = handle.getHmrSourceMap(absoluteModulePath); // string | nullVLQ encode + sourcesContent 첨부를 emit 단계 밖으로 빼서 HMR latency 절감. sourcemap 비활성 / 초기
빌드 전 / stop() 이후엔 null.
vitePlugin(rollupPlugin)
섹션 제목: “vitePlugin(rollupPlugin)”Rollup plugin 을 ZNTC 의 ZntcPlugin 으로 변환하는 어댑터. Vite plugin 도 Rollup 호환이라 그대로 사용 가능.
import { build, vitePlugin } from "@zntc/core";import someRollupPlugin from "rollup-plugin-something";
await build({ entryPoints: ["src/index.ts"], plugins: [vitePlugin(someRollupPlugin())],});지원 hook: resolveId / load / transform / renderChunk / generateBundle / buildStart / buildEnd / closeBundle (#2156).
watch()에서도 lifecycle hook이 초기 build와 매 rebuild마다 forward됩니다.
ZNTC plugin 직접 작성
섹션 제목: “ZNTC plugin 직접 작성”Rollup-style hook 인터페이스. 자세한 내용은 Plugins 가이드 참고.
import type { ZntcPlugin } from "@zntc/core";
const myPlugin: ZntcPlugin = { name: "my-plugin", setup(build) { build.onResolve({ filter: /^@my\// }, (args) => ({ path: resolve(__dirname, args.path), // disabled: true, // 빈 모듈로 대체 (Metro/webpack fallback escape) })); build.onLoad({ filter: /\.md$/ }, (args) => ({ contents: readFileSync(args.path, "utf-8"), loader: "text", // (#2157) loader override })); build.onTransform({ filter: /\.ts$/ }, (args) => ({ code: args.code.replace(/__VERSION__/g, '"1.0.0"'), })); build.onBuildStart(() => console.log("started")); // (#2156) build.onBuildEnd((err) => err && console.error(err)); // (#2156) build.onCloseBundle(() => console.log("done")); // (#2156)
// require.context 매칭 결과를 host runtime 의 RegExp 로 채움 build.onResolveContext({ filter: /./ }, (args) => { const re = new RegExp(args.filter ?? ".*", args.flags ?? ""); return { context: scanDir(args.dir, args.recursive, re) }; });
// 함수 단위 AST visit — directive strip / trailing code 주입 build.onAstFunction({ filter: /\.tsx?$/ }, (info) => { if (info.directives.includes("worklet")) return { stripDirective: "worklet" }; }); },};onResolve 추가 반환 필드
섹션 제목: “onResolve 추가 반환 필드”path— 해석된 절대 경로external— import 문 보존 (런타임 해석)disabled— 빈 모듈 (module.exports = {}) 로 대체. Metro{ type: 'empty' }, webpackresolve.fallback: false매핑
onAstFunction
섹션 제목: “onAstFunction”AstFunctionInfo: name / directives / closureVars / params / sourcePath / bodyText /
flags: { async, generator }.
AstFunctionResult: stripDirective? / trailingCode?: string[].
App 빌드 (Vite-style HTML 엔트리)
섹션 제목: “App 빌드 (Vite-style HTML 엔트리)”import { buildAppSync, prepareAppDevSync } from "@zntc/core";
// 프로덕션: HTML 엔트리에서 module / CSS / asset 스캔 → outdirconst r = buildAppSync({ root: ".", outdir: "dist", entryHtml: "index.html" });
// 개발: dev server 가 사용할 임시 prepare (mode = "development")const dev = prepareAppDevSync({ root: ".", outdir: ".zntc-dev" });AppBuildOptions / AppDevPrepareOptions 의 추가 필드: publicDir / base / mode / envDir /
envPrefixes / define / minify / sourcemap / splitting / compiler.
Config / Workspace API
섹션 제목: “Config / Workspace API”Unified config loader
섹션 제목: “Unified config loader”import { loadConfig, defineConfig } from "@zntc/core";
const env = { mode: "production", command: "build" };const config = await loadConfig({ cwd: process.cwd(), env });추가 export: findConfigPath, findModeConfigPath, loadModuleDefault, mergeUserConfigs,
importAndResolveDefault, defaultConfigEnv. 타입: UserConfig / UserConfigInput /
UserConfigFn / ConfigEnv / ModuleKind.
Workspace
섹션 제목: “Workspace”import { defineWorkspace, loadWorkspace } from "@zntc/core";
export default defineWorkspace([ "packages/*", { path: "apps/web", name: "web" }, { config: defineConfig({ bundle: { entryPoints: ["src/i.ts"] } }) },]);추가 export: loadWorkspace, filterWorkspaces, findWorkspacePath, identifyWorkspaceEntries,
loadIdentifiedConfig, WORKSPACE_EXT_PRIORITY. 타입: Workspace / WorkspaceEntry /
WorkspaceFn / IdentifiedWorkspace.
Utilities
섹션 제목: “Utilities”envToDefine(env, prefixes)—.env변수 →define매핑loadEnv(mode, dir, prefixes?)—.env[.mode][.local]우선순위 로드KNOWN_CONFIG_KEYS— 알려진 config 키 집합suggestKey(key)— 오타 추정 (Levenshtein 기반)warnUnknownKeys(obj)— 미지의 키 경고 출력isPlainObject(v)— 순수 객체 판별validateTsConfigRaw(raw)—tsconfigRawJSON 사전 검증
defineConfig(config)
섹션 제목: “defineConfig(config)”zntc.config.ts 에서 type-safe 한 config 작성용 helper. 런타임 동작 없음 — 단순 identity 함수.
import { defineConfig } from "@zntc/core";
export default defineConfig({ bundle: { entryPoints: ["src/index.ts"], outdir: "dist", minify: true, },});benchmark(options)
섹션 제목: “benchmark(options)”특정 phase 를 N 회 반복 실행하고 통계 (mean/median/p95/p99/stddev/min/max) 를 반환.
CLI zntc bench --phase=... 의 NAPI 대응 — 같은 engine 사용. 결과는 Benchmarks 참고.
import { benchmark } from "@zntc/core";
const r = benchmark({ file: "./src/App.tsx", phases: ["parse", "transform"], iterations: 100, warmup: 10,});console.log(r.phases.parse.mean_ms);BenchmarkOptions 필드:
source?또는file?— 둘 중 하나 필수filename?—source와 함께 (확장자 감지용)phases: string[]— 측정할 profile category.all/none불가iterations?(default 100) /warmup?(default 10)
BenchmarkPhaseStats: samples / mean_ms / median_ms / p95_ms / p99_ms / min_ms /
max_ms / stddev_ms. BenchmarkResult: phases: Record<string, BenchmarkPhaseStats>.
- 모든 export 상세 시그니처: API Reference (사이드바) (TypeDoc auto-generated)
- CLI — 동일 옵션을 명령행에서 사용
- Transpile 옵션 — JSON Schema 기반 전체 옵션 표
- Plugins 가이드 — plugin hook 작성법
- Vite 플러그인 —
@zntc/vite-plugin - Rspack / Webpack 통합 —
@zntc/rspack-loader