mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
84 lines
5.2 KiB
Plaintext
84 lines
5.2 KiB
Plaintext
---
|
|
title: "npm Dependencies"
|
|
---
|
|
|
|
scriptc can embed an npm package's JavaScript and execute it inside the compiled binary. Enable this behavior with `--dynamic`. Dependency code runs in [quickjs-ng](https://github.com/quickjs-ng/quickjs), while supported statically typed application code compiles to native code.
|
|
|
|
The embedded engine is also called the dynamic island. It has its own heap and job queue. Values crossing back into static types are validated at runtime.
|
|
|
|
## Use a package
|
|
|
|
Create `tool.ts`:
|
|
|
|
```ts:tool.ts
|
|
import { Command } from "commander";
|
|
|
|
const program = new Command();
|
|
|
|
program
|
|
.name("greet")
|
|
.argument("<name>", "who to greet")
|
|
.option("-u, --upper", "use uppercase")
|
|
.action((name: string, opts: { upper?: boolean }) => {
|
|
const text = `hello, ${name}`;
|
|
console.log(opts.upper ? text.toUpperCase() : text);
|
|
});
|
|
|
|
program.parse();
|
|
```
|
|
|
|
Install the dependency, then build and run the executable:
|
|
|
|
```console
|
|
$ npm install commander
|
|
$ scriptc build tool.ts --dynamic -o greet >/dev/null
|
|
$ ./greet ada --upper
|
|
HELLO, ADA
|
|
```
|
|
|
|
The callback body compiles statically. The `commander` implementation runs in the embedded engine. Use [`scriptc coverage --dynamic`](/docs/coverage#analyze-with-dynamic) to inspect a program's static and dynamic statement counts and the builtin modules its dependencies import.
|
|
|
|
## Package resolution and embedding
|
|
|
|
The compiler resolves packages from `node_modules` using Node.js package resolution, including `package.json` export conditions. Shipped or installed type declarations provide the types used to check application code.
|
|
|
|
The package's JavaScript and its resolved imports are embedded at build time. The executable does not load `node_modules` at runtime. Deploy it to a machine compatible with the build's target platform.
|
|
|
|
Packages can also expose TypeScript runtime entries (`.ts`, `.mts`, or `.cts`). The compiler emits JavaScript before collecting and embedding runtime imports, removing type annotations and type-only bindings. `import type` and `export type` declarations do not add runtime dependencies. See [Limitations](/docs/limitations#embedded-javascript-engine) for package source restrictions.
|
|
|
|
Workspace packages with a TypeScript executable entry compile as program modules, including `.js` import specifiers that resolve to `.ts` source. Workspace packages with JavaScript executable entries use the same policy as other JavaScript dependencies: execute them with `--dynamic`, or attempt static compilation with `--npm-static`.
|
|
|
|
## Runtime behavior
|
|
|
|
### Engine and builtin modules
|
|
|
|
Node.js builtin modules are provided by shims, some of which bridge to the native runtime. Each shim has a supported subset; the [coverage report](/docs/coverage#embedded-nodejs-builtins) lists the modules reached by the dependency graph, and the [compatibility reference](/compatibility) lists API support.
|
|
|
|
The engine is created lazily on first use, with one engine per process. A `--dynamic` build that does not use the engine emits the same code as a static build. Supported `any`-typed expressions also execute in the engine when `--dynamic` is enabled.
|
|
|
|
### Value conversion
|
|
|
|
Values passed between static and dynamic code are copied. Mutations to a copied value in one execution tier do not change the original in the other tier. This differs from ordinary JavaScript reference sharing.
|
|
|
|
Typed callback parameters and values returned to static code are validated. If the package supplies a value that does not match the expected type, the conversion throws a catchable `TypeError`. See [Limitations](/docs/limitations) for runtime differences and restrictions on values that can cross the boundary.
|
|
|
|
## Static package compilation (experimental)
|
|
|
|
`--npm-static <pkg[,pkg…]|auto>` attempts to compile packages' shipped JavaScript as static program modules, using their type declarations. Named packages are selected explicitly; `auto` selects eligible direct imports.
|
|
|
|
Support is partial. An accepted package may contain deferred operations: the build succeeds and coverage lists those sites, but executing an unsupported deferred operation raises a runtime error. A package rejected during preflight falls back to the embedded engine with a coverage note; that path requires `--dynamic`. Other unsupported forms can still prevent a static build.
|
|
|
|
Check the coverage report for each package before depending on static execution.
|
|
|
|
## Provenance sources (experimental)
|
|
|
|
`--provenance-sources` attempts to compile a package from source at its npm provenance-attested commit. This allows TypeScript source to compile as TypeScript instead of compiling the published JavaScript.
|
|
|
|
Packages without usable attestations retain the embedded-engine path, with a note. This option has the same partial-support restrictions as `--npm-static`.
|
|
|
|
## Type declarations and boundary restrictions
|
|
|
|
Packages require shipped or installed type declarations. If TypeScript reports that it cannot find a declaration file, install the corresponding `@types` package or add a local declaration.
|
|
|
|
Class instances and promises cannot pass into `any` slots in the engine. Closures can cross as host functions only in supported forms. Unsupported conversions produce compilation diagnostics with guidance where available.
|