DEV Community

Wen Ping
Wen Ping

Posted on

When npmjs is flaky in China: switch to a team registry with PROXY cache

npm install hangs on registry.npmjs.org with timeouts, ECONNRESET, occasional TLS handshake failures, or upstream 502. I have seen the same office network where a phone hotspot works and company DNS fails every time—and CI images where NPM_CONFIG_REGISTRY still points at the official host after the laptop already switched. Bookmarking another public mirror URL often treats the symptom: private packages still need a second address, and CI drifts from local. A stabler path: developers / CI only know the team GROUP, public packages cache through PROXY, internals stay on HOSTED. This article assumes the three repos and tokens are already set up per “Start a free cloud npm private registry” or “How to set up a private npm registry,” and focuses on reachability diagnosis and cache-hit acceptance.

Takeaway: Use a private registry GROUP as the only install source and PROXY to cache npmjs—you can replace direct hits to the official registry from developers/CI. PROXY still needs outbound access to npmjs on a cold miss; after a local hit, build machines stop each slamming upstream jitter. This does not replace npmjs’s global package identity or account system.

Repo creation, .npmrc getting started, and the npm publish loop: Start a free cloud npm private registry / How to set up a private npm registry. Below starts from the “flaky” symptoms.

1. Recognize what “flaky” looks like

Client symptom More likely layer Do this before swapping registries
ENOTFOUND / slow resolve DNS / office hijack nslookup registry.npmjs.org; compare phone hotspot
ECONNRESET, TLS alert, handshake drop TLS / MITM proxy / cert chain Check corporate HTTPS proxy; do not paper over production CI with self-signed certs
Long hang then timeout Congestion or slow upstream Note failure time; retry the same command via GROUP
401 / E401 Token or registry path—not “China network” Check _authToken host path and trailing / (failure table)
Occasional 502 / 503 from npmjs Upstream or a gateway on the path Should be rarer after PROXY hits; cold misses can still reproduce

“npmjs alternative” here means unified registry + cache + private packages on one host—not a claim to replace the whole ecosystem.

1.1 Public mirrors vs private registry (scope)

Need Public mirror (e.g. regional) Private GROUP + PROXY
Only make public packages faster / more reachable Usually enough Works, but heavier
Private scope and public packages on one registry Usually no HOSTED + PROXY in one GROUP
Per-repo ACL / Deploy Token / audit No Yes
Fully air-gapped builds No Warm cache first—see offline builds

2. Traffic boundary (read GROUP, write HOSTED)

Dev / CI
  registry = …/npm/npm-all/          (GROUP, only install entry)
       ├─ npm-hosted                 (HOSTED, internals first)
       └─ npmjs-proxy                (PROXY → https://registry.npmjs.org)
Enter fullscreen mode Exit fullscreen mode
  • Read: only configure GROUP (member order hosted → proxy).
  • Write: only npm publish to HOSTED (steps in the free-cloud npm article—not repeated here).
  • Auth: .npmrc uses URL-scoped _authToken=${NPM_TOKEN}; never commit the token. No out-of-the-box tenant_id.
  • Outbound: the repository node must still reach https://registry.npmjs.org—on a cold miss the unified registry concentrates upstream jitter on the repo side.

Cloud sample host: repo.anguskit.com; self-host swaps your domain.

3. Diagnosis: flaky direct → confirm switch → accept PROXY

3.1 Confirm where traffic actually goes

On the same failing machine / same CI job:

# Effective registry (including project overrides)
npm config list -l | rg -i 'registry'

# Env vars CI images often inject quietly
env | rg -i 'npm_config_registry|NPM_CONFIG_REGISTRY'

# Lock files still pinning the official host?
rg -n 'registry\.npmjs\.org' package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null | head
Enter fullscreen mode Exit fullscreen mode

If registry is still https://registry.npmjs.org/, or locks are full of resolved pointing at npmjs, every later “switch” check is invalid—fix config or clear the lock and reinstall first (detail: free-cloud npm article §3.2 three traps).

3.2 Compare: direct fail vs via GROUP

Do not invent speed numbers. Same command, same dependency, two adjacent runs—watch whether the failure shape changes:

# A. Direct official (reproduce flaky)
npm install lodash --registry https://registry.npmjs.org/ --prefer-online

# B. Via team GROUP (should hit PROXY; first run may miss)
npm install lodash --registry https://repo.anguskit.com/npm/npm-all/ --prefer-online
Enter fullscreen mode Exit fullscreen mode

Reading:

A (direct) B (GROUP) Meaning
Timeout / TLS / 502 Success or clearly stabler Unified path helps; continue §3.3 cache acceptance
Success 401 Path works; token / _authToken path is wrong
Timeout Same timeout Check repo outbound to npmjs; or the machine cannot reach the repo host
401 401 Stop talking about network; fix auth first

3.3 Confirm PROXY cache, not every request going upstream

Goal: the second install does not spend a long time missing; the console shows PROXY-side cache entries (field names follow the console).

  1. Open npmjs-proxy (or your PROXY name) → check whether the package you just installed (e.g. lodash) appears in cache / artifact lists.
  2. Install again in the same clean directory (delete node_modules, keep a lock already pointed at GROUP):
rm -rf node_modules
npm install lodash --registry https://repo.anguskit.com/npm/npm-all/
Enter fullscreen mode Exit fullscreen mode
  1. Observe: the second run should be clearly faster or stop hanging on “resolving / downloading registry.npmjs.org”; if it still spends a long time missing, check PROXY remote URL is https://registry.npmjs.org, repo outbound, and whether --prefer-online / cache policy forces a refresh (console + manuals).
  2. On failure, prioritize repo outbound and PROXY config—not a third mirror URL on every laptop.

Warming core deps and weak/offline builds: offline build warm-up.

3.4 Boundaries where the unified registry can still “feel like official”

Case Notes
PROXY cold miss Still depends on npmjs and repo outbound; unified registry concentrates jitter, it does not erase upstream
Global ~/.npmrc overrides the project One laptop still goes direct; use §3.1 on the offending machine
CI base image hard-codes registry npm config get registry in the job log shows it immediately
Only company scope switched; public packages still direct Fine during migration; when public packages are flaky, set whole-project registry= to GROUP

4. Boundaries and failure table

Symptom Cause Fix
Still hits npmjs Global .npmrc / env / lock override §3.1 three commands; clear lock and reinstall
GROUP install 401 _authToken host path mismatch or missing trailing / Scoped line has no https://; align with registry URL
Private package 404 Published to wrong repo or GROUP missing HOSTED Check member order; publish steps in free-cloud npm article
Assumed “alternative” means no npmjs Cold PROXY still misses Allow repo outbound; warm hot packages
Dependency confusion Internal name equals public and order is wrong HOSTED first; company scope for internals

For partners installing anonymously, use /explore and a public HOSTED—see public portal.

FAQ

Does this replace npmjs.org?

For the team default install source and private package hosting, yes. Publishing to public npmjs and the official account/org system stay on npmjs. “Alternative” here is unified registry / cache—not replacing the ecosystem.

How to choose vs Taobao-style public mirrors?

See §1.1: public mirrors buy reachability; private registry buys private packages + cache + ACL + audit on one host. They can coexist; migration can start with company scope only.

How does this map to Nexus / Verdaccio?

Multi-format and alternative scenarios: selection article; leaving Verdaccio: Verdaccio migration.

Takeaways

  • Separate DNS / TLS / timeout / 401 before talking about switching registries.
  • Use §3.1–3.3 to accept “already on GROUP” and “PROXY cache hit.”
  • A unified registry does not cancel upstream: cold misses can still feel npmjs.

Reference articles

Top comments (0)