Skip to content

Tags: vercel/ncc

Tags

0.45.0

Toggle 0.45.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: update @vercel/webpack-asset-relocator-loader to 1.10.3 (#1342)

Bumps `@vercel/webpack-asset-relocator-loader` from **1.7.3** to
**1.10.3** (latest).

## What's in the bump

| Version | Change |
| --- | --- |
| 1.7.4 | Use a computed `node-gyp-build` path
([#185](vercel/webpack-asset-relocator-loader#185))
|
| 1.7.5 | Fix `__nccwpck_require__ is not defined` regression
([#195](vercel/webpack-asset-relocator-loader#195))
|
| 1.8.0 | Support `node:path` as an alias of `path`
([#197](vercel/webpack-asset-relocator-loader#197))
|
| 1.9.0 | Load native addons from the `prebuilds` directory
([#198](vercel/webpack-asset-relocator-loader#198))
|
| 1.9.1 | Support the packaging format of sharp v0.34.x
([#199](vercel/webpack-asset-relocator-loader#199))
|
| 1.10.0 | Ship the loader as source instead of a prebuilt bundle
([#200](vercel/webpack-asset-relocator-loader#200))
|
| 1.10.2 | Packaging/CI fixes |
| 1.10.3 | Percent-decode the ESM asset base
([#220](vercel/webpack-asset-relocator-loader#220))
|

Because 1.10.0 publishes `src/` rather than an ncc-built `dist/`, the
loader's previously bundled dependencies are now real transitive
dependencies — that accounts for the lockfile growth. The
`relocate-loader` build emits no new assets, and
`dist/ncc/loaders/relocate-loader.js.cache.js` actually shrinks slightly
(499.37KB → 492.13KB).

## Why the unit fixtures change

The loader now registers the asset base through a webpack
`RuntimeModule` instead of the deprecated
`mainTemplate.hooks.requireExtensions`. Two consequences show up in
`test/unit/*/output*.js`:

1. The block is labelled `/* webpack/runtime/asset-relocator-loader */`
instead of `/* webpack/runtime/compat */`, and is emitted earlier in the
runtime.
2. Bundles that never reference `__nccwpck_require__` no longer carry
the dead `if (typeof __nccwpck_require__ !== 'undefined')
__nccwpck_require__.ab = ...` assignment — the runtime module is only
added when `RuntimeGlobals.require` is actually in the tree. The guard
was always false in those bundles, so this is dead-code removal, not a
behaviour change.

I specifically checked that the second point is not a regression.
`__nccwpck_require__.ab` is still emitted wherever it is referenced,
verified by hand for CJS, ESM, and concatenated-TypeScript builds that
relocate an asset, and by the asset-heavy integration tests (`sharp`,
`canvas`, `ffmpeg`, `oracledb`, `leveldown`, `binary-require`), which
all pass.

## The Windows fix now comes from upstream

The first push was green on Linux and macOS but failed on all three
Windows jobs:

```
Cannot find module 'C:/Users/RUNNER%7E1/AppData/Local/Temp/.../runtime.json'
```

The relocator derives the ESM asset base from `new URL('.',
import.meta.url).pathname`, which is percent-encoded. The Windows
runner's temp dir is an 8.3 short name (`RUNNER~1`), so `~` became
`%7E`. This is **not** platform-specific — paths containing spaces break
identically everywhere:

```
$ ncc build input.mjs -o '/tmp/out dir'
Cannot find module '/tmp/out%20dir/runtime.json'
```

That expression is byte-identical in 1.7.3 and 1.10.2, so the bug is
pre-existing. It was simply unreachable for this fixture before: 1.7.3
had no `node:` specifier support, so `import { resolve } from
"node:path"` was not statically analyzable and `runtime.json` was never
relocated. 1.8.0 added `node:path` as an alias of `path`, so the
reference is now resolved, emitted as an asset, and rewritten to
`__nccwpck_require__.ab + ...` — which is where the latent bug surfaces.

This PR originally carried the one-line fix (wrap the pathname in
`decodeURIComponent`) as a `patchedDependencies` entry. **That patch has
now shipped upstream in 1.10.3**, so this PR bumps to 1.10.3 and
deletes:

- `patches/@vercel__webpack-asset-relocator-loader@1.10.2.patch`
- the matching `patchedDependencies` entry in `pnpm-workspace.yaml`
(that file is now identical to `main` again)

1.10.3 is 1.10.2 plus exactly that change — `diff`ing the two published
tarballs shows only the version field and the one `requireBase` line
(plus an explanatory comment). Confirmed empirically:
`update-fixtures.sh` regenerates every `test/unit/*/output*.js` with
**zero drift** against the patched-1.10.2 fixtures already in this PR.

## Also fixed

`update-fixtures.sh` invoked `node node_modules/.bin/jest` for the
coverage pass. Under pnpm that path is a shell shim rather than a JS
entry point, so the step crashed with `SyntaxError: missing ) after
argument list` and never regenerated any `output-coverage.js`. Switched
both invocations to `node_modules/jest/bin/jest.js`, matching the `test`
script in `package.json`.

That broken step is why two `output-coverage.js` fixtures had drifted on
`main` before this PR (`import-meta-cjs` and `ts-json-resolve`). Their
regenerated output here therefore contains one small change each that is
unrelated to the relocator. The drift went unnoticed because
`test/integration.test.js` calls `process.exit(0)` in `afterAll` under
coverage, so `pnpm test-coverage` exits 0 even when `test/unit.test.js`
fails.

## Testing

Re-run on Linux / Node 22.22.2 after the bump to 1.10.3:

- `pnpm test` — **121 passed, 1 failed**. The only failure is
`binary-require.js` (`Cannot find module './hello.node'`), because `pnpm
build-test-binary` needs a C++ toolchain that the machine used for this
re-run does not have, so `test/integration/hello.node` was never
produced. CI installs `node-gyp` and builds it, and this test passed on
the previous push.
- `jest --coverage --globals '{"coverage":true}' test/unit` — **28
passed**
- `bash update-fixtures.sh` — regenerates all fixtures, `git status`
clean afterwards
- `pnpm install --frozen-lockfile` — succeeds with no config override

The `%20`/`%7E` case is now covered end-to-end rather than by hand:
running the `create-require-runtime` integration test with
`TMPDIR="/tmp/tmp dir~short"` reproduces the Windows failure mode on
Linux. It passes on 1.10.3, and to confirm the check is actually
sensitive I reverted `decodeURIComponent` in the built loader and
watched it fail with exactly the CI error:

```
Cannot find module '/tmp/tmp%20dir%7Eshort/<hash>/runtime.json'
```

Two pre-existing quirks I ran into and confirmed also reproduce on
`main`, so they are **not** introduced here and are left alone:

- Under `--runInBand`, if `test/watcher.test.js` runs before
`test/unit.test.js` in the same process, a unit test fails with
`TypeError: Cannot read properties of undefined (reading 'then')` inside
webpack's `FileSystemInfo`. Reproduced at 1.7.3.
- The stale coverage fixtures described above.

## One thing to flag

1.10.3 was published a few minutes before this update was pushed, and
`pnpm-workspace.yaml` sets `minimumReleaseAge: 2880` (48h), so a fresh
resolution of this version is blocked today. I generated the lockfile
with a one-off `--config.minimumReleaseAge=0` and deliberately did
**not** add a `minimumReleaseAgeExclude` entry, so the repo's
supply-chain policy is unchanged. CI is unaffected: both install steps
in `ci.yml` use `pnpm install --frozen-lockfile`, which skips resolution
and installs 1.10.3 from the lockfile (verified locally — it succeeds
with no override). Once 1.10.3 is 48h old the constraint stops mattering
entirely — hold this PR until then if you'd rather the policy not be
bypassed at all.

## Related

- Fixes #1307

Confirmed this bump does address it. That `TypeError: Cannot mix BigInt
and other types` originates in the relocator's static evaluator
(`relocate-loader.js.cache.js`), whose `BinaryExpression` handler is
unguarded in 1.7.3. 1.10.x wraps it in a `try`, with a comment naming
that exact error, and adds the matching guard for the `UnaryExpression`
BigInt case.

---------

Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: Steven <229881+styfle@users.noreply.github.com>

0.44.1

Toggle 0.44.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: preserve runtime createRequire in ESM builds (#1334)

## Problem

Since 0.38.2, an ESM build can replace a runtime
`createRequire(...)` binding with `undefined`, causing the later runtime
`require(...)` call to throw.

## Change

- Disable Webpack's `createRequire` parser handling in ncc so Node
evaluates
  the call at runtime.
- Add a normal integration fixture with an `.mjs` entry that imports the
  TypeScript runtime payload and loads a runtime-selected JSON module.

This keeps the fix at ncc's Webpack configuration boundary and covers
the
reported runtime behavior without changing dependency tracing.

## Validation

- `node scripts/build.js --no-cache`
- `node --expose-gc --max_old_space_size=4096
node_modules/jest/bin/jest.js test/integration.test.js --runInBand
--testNamePattern create-require-runtime`
  - 1 passed
- `pnpm test -- test/unit.test.js`
  - 28 passed
- `node --expose-gc --max_old_space_size=4096
node_modules/jest/bin/jest.js --runInBand test/integration.test.js
--testNamePattern='^(?!should execute "ncc run
(?:axios\.js|canvas\.js|isomorphic-unfetch\.js|request-ts\.ts|request\.js|sharp\.js|socket\.io\.js)"$).*'`
  - 62 passed; 7 local environment-dependent cases skipped
- Negative control with Webpack's `createRequire` parsing restored
reproduced
  `TypeError: input_require is not a function`.

## Risk

The parser option applies to all JavaScript handled by ncc. It
intentionally
preserves `createRequire` for Node to evaluate at runtime, so modules
selected
only at runtime must still be deployed with the bundle.

The cross-platform Node 22/24/26 matrix remains for CI. A local CLI
watch test
failed with Watchpack `EMFILE` errors and reproduced identically on
`origin/main`, so it is not attributed to this change.

## Out of scope

- Changing how ncc traces or deploys runtime-selected modules.
- Dependency or lockfile updates.

## Issue linkage

Fixes #1312

0.44.0

Toggle 0.44.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(deps): Bump actions/checkout from 5 to 6 (#1300)

0.43.0

Toggle 0.43.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: remove npm devDependency (#1332)

I believe this was causing npm publish to fail since its an outdated npm
version


https://github.com/vercel/ncc/actions/runs/27214803275/job/80353387410#step:13:440

0.42.0

Toggle 0.42.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: add publishConfig to package.json (#1331)

This appears to be necessary for trusted publishing

0.41.0

Toggle 0.41.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(ci): upgrade python and remove LLVM LTO flags from MSVC build to…

… fix Node 26 Windows CI (#1330)

## Root Cause

Node.js 26 on Windows is compiled using Clang with thin LTO enabled
(`enable_thin_lto=true`, `lto_jobs=2`). When `node-gyp rebuild` runs
without `--nodedir`, it generates `build/config.gypi` from the running
Node.js binary's `process.config`. This causes Node.js's `common.gypi`
to inject LLVM/Clang-specific flags into the MSVC build:

- `-flto=thin` → compiler/linker warning (ignored by MSVC)
- `/opt:lldltojobs=2` → **fatal linker error `LNK1117`** (MSVC does not
understand LLVM LTO job flags)

## Fix

Modified `test/binary/binding.gyp` to strip the incompatible LLVM LTO
flags when building on Windows with MSVC:

- Added a `"lto_jobs%": ""` default variable as a safe fallback for Node
versions that do not define this variable
- Added a Windows-specific `conditions` block using GYP's
`AdditionalOptions!` list-removal operator to remove `-flto=thin`,
`-flto=full`, and `/opt:lldltojobs=<(lto_jobs)` from both
`VCCLCompilerTool` and `VCLinkerTool` options

The fix is a no-op on Node 22/24 (LTO not enabled, no flags to remove)
and does not affect Linux or macOS builds.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

0.40.0

Toggle 0.40.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: delete .github/CODEOWNERS (#1324)

This is how our other repos are managed - they just require one approval
by a Vercelian.

For example, see https://github.com/vercel/ms

0.39.2

Toggle 0.39.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(security): Predictable global cache directory in /tmp enables sym…

…link/hijack risks (#1314)

## Problem

The cache directory is a fixed, shared path (`/tmp/ncc-cache`). On
multi-user systems this can be pre-created or manipulated by another
user (symlink/hardlink attacks), potentially causing cache poisoning,
unintended file writes, or data leakage between builds/users depending
on how cache files are later written.

**Severity**: `medium`
**File**: `src/utils/ncc-cache-dir.js`

## Solution

Use a per-user/per-project cache directory with secure creation
semantics (e.g., `fs.mkdtemp` under user-owned base dir), enforce
permissions (`0700`), and verify path is not a symlink before writing.

## Changes

- `src/utils/ncc-cache-dir.js` (modified)

## Testing

- [ ] Existing tests pass
- [ ] Manual review completed
- [ ] No new warnings/errors introduced

---------

Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com>
Co-authored-by: Steven <steven@ceriously.com>

0.39.1

Toggle 0.39.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: Reorder extension resolution to prioritise TypeScript over JSON (#…

…1315)

When a directory contains both `test.json` and `test.ts`, an
extensionless import like:

```ts
import { myFunction } from './test';
```

resolves to `test.json` instead of `test.ts`, causing all exported
methods from the TypeScript file to be unresolvable during the build.

Webpack resolves extensions in the order they appear in the
`resolve.extensions` array.

Since `.json` appears before `.ts` and `.tsx`, webpack picks the JSON
file first when both exist.

### Reproduce

(The test project need a `tsconfig.json` with
`compilerOptions.resolveJsonModule: true`)

1. Create a directory with two files sharing the same base name: 

   **`src/test.json`**
   ```json
   { "key": "value" }
   ```

   **`src/test.ts`**
   ```ts
   export function greet(): string {
     return "hello";
   }
   ```

2. Import without an extension from another TypeScript file:

   **`src/index.ts`**
   ```ts
   import { greet } from './test';
   console.log(greet());
   ```

3. Run `ncc build src/index.ts` the build fails because `./test`
resolves to `test.json`, which has no `greet` export.

0.39.0

Toggle 0.39.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: support TypeScript 6 transpile builds (#1316)

## Summary

Updates `ts-loader` to `9.5.7` so ncc's bundled TypeScript loader
preserves configured `rootDir` during `transpileModule` builds.

This fixes TypeScript 6 `TS5011` failures like:

```text
TS5011: The common source directory of 'tsconfig.json' is './actions/javascript/...'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.
```

`ts-loader` fixed this upstream in
TypeStrong/ts-loader#1679.

## Verification

- Ran `yarn build`