TypeScript Package Management
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| CA | Certificate Authority | 证书颁发机构 |
| CI | Continuous Integration | 持续集成 |
| ESM | ECMAScript Modules | JavaScript 标准模块系统 |
| TLS | Transport Layer Security | 传输层安全协议 |
Links#
https://docs.npmjs.com/cli/v11/configuring-npm/package-json
https://docs.npmjs.com/cli/v11/using-npm/config
https://docs.npmjs.com/cli/v11/configuring-npm/npmrc
https://docs.npmjs.com/cli/v11/commands/npm-ci
https://docs.npmjs.com/cli/v11/commands/npm-publish
https://docs.npmjs.com/cli/v11/commands/npm-pack
https://nodejs.org/api/packages.html1. Important Points#
TypeScript package management:
npm is the default package manager in Node.js ecosystem
package.json defines package metadata and scripts
package-lock.json locks exact dependency versions
npm ci should be used in CI/container builds
dependencies and devDependencies must be separated
private registry auth should not be committed
production rules:
commit package-lock.json
use npm ci
use private registry or proxy registry in enterprise
keep auth token in secret manager / CI secret
do not bake .npmrc token into Docker image2. package.json#
{
"name": "@my-org/order-client",
"version": "1.0.0",
"type": "module",
"private": false,
"description": "Order API client",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "tsc",
"typecheck": "tsc --noEmit",
"prepack": "npm run build",
"pack": "npm pack",
"publish:dry": "npm publish --dry-run",
"publish:registry": "npm publish --access restricted"
},
"dependencies": {
"zod": "latest"
},
"devDependencies": {
"typescript": "latest",
"@types/node": "latest"
},
"engines": {
"node": ">=20"
},
"publishConfig": {
"access": "restricted",
"registry": "https://registry.npmjs.org/"
}
}important fields:
name:
scoped package uses @org/name
type:
module means ESM package
main:
runtime entrypoint
types:
TypeScript declaration entrypoint
exports:
public package entrypoints
files:
package allowlist
avoid publishing src / config / test accidentally
prepack:
runs before npm pack and npm publish
publishConfig:
default registry and access for publish3. Install Dependencies#
npm install zod
npm install -D typescript @types/nodenpm cinpm install:
local development
updates package-lock.json when dependency changes
npm ci:
CI / Docker build
requires package-lock.json
clean reproducible install4. npm Registry#
default registry#
npm config get registry
npm config set registry https://registry.npmjs.org/project .npmrc#
registry=https://registry.npmjs.org/
@my-org:registry=https://npm.pkg.github.com/
always-auth=trueproject .npmrc:
can be committed if it has no token
can define registry routing
should not contain real credentialsuser .npmrc#
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}user .npmrc:
usually stored at ~/.npmrc
should contain personal or CI token
should not be committed5. Private Registry Auth#
npm token#
npm login --registry=https://registry.npmjs.org/export NPM_TOKEN="***"
npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"scoped private registry#
@my-org:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
always-auth=trueCI#
cat > .npmrc <<'EOF'
@my-org:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
always-auth=true
EOF
npm ciCI rule:
token comes from CI secret
create .npmrc during job
delete it after install if artifact may be reused6. TLS / CA#
npm CA config#
strict-ssl=true
cafile=/etc/ssl/private/company-ca.pemenvironment variables#
export NODE_EXTRA_CA_CERTS=/etc/ssl/private/company-ca.pem
export npm_config_cafile=/etc/ssl/private/company-ca.pem
export npm_config_strict_ssl=truewhen needed:
private registry uses company CA
corporate proxy intercepts TLS
internal package registry has private certificate chain
do not:
set strict-ssl=false in production
set NODE_TLS_REJECT_UNAUTHORIZED=0 in productionDocker build with CA#
FROM node:22-bookworm-slim
COPY certs/company-ca.pem /usr/local/share/ca-certificates/company-ca.crt
RUN update-ca-certificates
ENV NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/company-ca.crt npm_config_cafile=/usr/local/share/ca-certificates/company-ca.crt npm_config_strict_ssl=true私有 npm 凭据和 SSH 私钥不 COPY 进镜像;构建时使用 Secret/SSH mount,并防止凭据进入产物与日志。
note:
certificate file is not secret if it is a public CA certificate
private key must never be copied into image7. Docker With Private Packages#
# syntax=docker/dockerfile:1
FROM node:22-bookworm-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm cidocker build --secret id=npmrc,src="$HOME/.npmrc" -t order-api:local .why:
npm token is available only during RUN
token is not copied into image layer
safer than COPY .npmrc8. Create A Package#
source#
src
├── index.ts
└── OrderClient.ts// src/OrderClient.ts
export type CreateOrderRequest = {
userId: string;
amount: number;
};
export type Order = {
orderId: string;
userId: string;
amount: number;
status: "PENDING" | "PAID" | "CANCELLED";
};
export class OrderClient {
constructor(private readonly baseUrl: string) {}
async createOrder(request: CreateOrderRequest): Promise<Order> {
const response = await fetch(`${this.baseUrl}/orders`, {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(request)
});
if (!response.ok) {
throw new Error(`create order failed: ${response.status}`);
}
return response.json() as Promise<Order>;
}
}// src/index.ts
export { OrderClient } from "./OrderClient.js";
export type { CreateOrderRequest, Order } from "./OrderClient.js";tsconfig for package#
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"]
}declaration:
generate .d.ts files for package consumers
exports:
control public import path9. Pack And Publish#
preview package#
npm run build
npm pack --dry-runnpm packinstall local tarball#
npm install ../order-client/my-org-order-client-1.0.0.tgzpublish#
npm publish --access restrictedpublish checklist:
version updated
package name correct
files allowlist reviewed
dist generated
.d.ts generated
npm pack --dry-run reviewed
registry and access reviewed10. Monorepo#
{
"name": "order-platform",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
]
}workspace:
multiple packages in one repo
shared lockfile
local package linking
common structure:
packages/order-client
packages/config
apps/order-api
apps/order-worker11. Production Checklist#
install:
package-lock.json committed
npm ci used in CI
registry pinned if enterprise requires it
token stored in secret manager
security:
no token in committed .npmrc
no token copied into Docker image
strict-ssl enabled
company CA configured when needed
publish:
package has exports
package has types
files allowlist reviewed
npm pack --dry-run reviewed
publishConfig reviewed