TuBrief
Subscribed Channels
Videos
Community

العقبات والحلول أثناء نقل pnpm monorepo إلى Nub

TuBrief Editorial
July 27, 2026
0
Computing/Software

Written with AI assistance from the source video. The video is the authority.

العربية한국어EnglishEspañol中文हिन्दीFrançaisPortuguêsDeutschРусскийBahasa Indonesia日本語

Related Video

هل هناك مدير حزم جديد؟! (بديل لـ Bun)8:29

هل هناك مدير حزم جديد؟! (بديل لـ Bun)

Better Stack

More from the community

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

September 13, 2026

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

September 13, 2026

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

September 13, 2026

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

September 13, 2026

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

September 12, 2026

Apple Won the AI Race

September 12, 2026

Comments (0)

Log in to leave a comment

No posts yet

© 2026 . All rights reserved.

TuBrief
Subscribed Channels
Videos
Community
Log in

العقبات والحلول أثناء نقل pnpm monorepo إلى Nub

منظومة Node.js تعاني من الإرهاق. فبيئة البناء التي تعتمد على طبقات متراكمة من tsx وdotenv-cli وnvm وpnpm أصبحت ثقيلة، وكلما أردت تحديث شيء واحد، تتشابك البرامج النصية (scripts). وعندما ظهرت Nub — وهي مجموعة أدوات متكاملة مكتوبة بلغة Rust لدمج هذه الفوضى من الحزم في ملف تنفيذي ثنائي واحد (single binary) — أكون صريحًا: سعدتُ بالفكرة ولكن خالطني بعض الشك.

وعندما قمتُ بالفعل بتحويل pnpm-workspace monorepo المستخدم في بيئة الإنتاج إلى Nub، وجدتها جذابة للغاية. لكن بالطبع، لم تكن العملية سلسة بدون عقبات؛ حيث ظهرت مشاكل مباشرة في بيئة العمل الحقيقية بدءًا من تعارض الاعتمادات (dependencies)، وسياسة القفل الأمني لمدة 24 ساعة، وحتى مشكلة فصل التخزين المؤقت (cache) في CI.

كيفية التعامل مع شجرة الاعتمادات عند التحول إلى Workspaces

يتعرف محرك الحزم الخاص بـ Nub والمسمى aube على pnpm-workspace.yaml الحالي وworkspaces في package.json بشكل مباشر. وكما يُذكر في وصفه بأنه متوافق على مستوى البايت مع مخطط pnpm-lock.yaml v9، فإنه يستغل هيكل المتجر الافتراضي الحالي (node_modules/.store/) بشكل أساسي.

المشكلة تكمن في الأدوات القديمة التي تفترض ضمنيًا وجود هيكل node_modules مسطح (hoisted). فعند تشغيلها مباشرة بعد عملية الهجرة، تفشل وتخرج بخطأ MODULE_NOT_FOUND. ولجعل الخدمة تعمل فورًا، عليك البدء بفرد شجرة الحزم باستخدام الخيار --node-linker hoisted.

بناءً على التثبيت الدافئ (Warm install) مع تفعيل التخزين المؤقت، يستغرق وضع GVS الافتراضي 346 مللي ثانية. أما وضع Hoisted فيستغرق 1461 مللي ثانية، وهو أبطأ بأكثر من 4 أضعاف، ولكنه يظل أسرع بأكثر من مرتين مقارنة بـ 3453 مللي ثانية في pnpm v10+. في البداية، من الأسهل لك ضمان التوافق باستخدام وضع Hoisted، ثم الانتقال إلى وضع GVS الافتراضي بعد التخلص من الاعتمادات على الأدوات القديمة.

`bash
#!/usr/bin/env bash
set -euo pipefail

echo "==> [1/4] التحقق من ثنائي Nub"
if ! command -v nub &> /dev/null; then
echo "Error: Nub غير موجود. يرجى تشغيل 'npm i -g @nubjs/nub' أولاً."
exit 1
fi

echo "==> [2/4] التحقق من مخطط pnpm-lock.yaml"
if [ -f "pnpm-lock.yaml" ]; then
nub pm use nub
fi

echo "==> [3/4] تحديد محرك التشغيل في package.json"
node -e '
const fs = require("fs");
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
pkg.devEngines = pkg.devEngines || {};
pkg.devEngines.packageManager = {
name: "nub",
version: "^0.4.0",
onFail: "warn"
};
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2) + "\n");
'

echo "==> [4/4] إنشاء Lockfile"
nub install --frozen-lockfile=false

`

باستخدام هذا البرنامج النصي لتحويل pnpm-lock.yaml إلى nub.lock، يمكنك توفير أكثر من ساعتين أسبوعيًا من الوقت الذي كان يضيع في إصلاح الأخطاء الناتجة عن تعديل السكريبتات في كل مرة.

التقييد العُمري للإصدارات لمدة 24 ساعة والتعامل مع الإصلاحات العاجلة (Hotfixes)

تتميز Nub بسياسة أمنية صارمة للغاية؛ حيث تحظر سكريبتات دورة الحياة افتراضيًا، وترمي الخطأ ERR_NUB_TRUST_DOWNGRADE إذا لم يكن هناك توقيع npm Provenance. والشيء الأكثر إرباكًا هو الخيار minimumReleaseAge؛ حيث يعتبر إصدارات الحزم التي لم يمر على نشرها 24 ساعة في حالة انتظار للتحقق الأمني، ويمنع تثبيتها.

في الأوقات العادية، تعد هذه درعًا واقيًا ممتازًا، ولكن عندما تظهر ثغرة يوم الصفر (zero-day) وتحتاج إلى نشر إصدار إصلاحي صدر قبل ساعة واحدة فقط، تصبح هذه السياسة عائقًا كبيرًا. في هذه الحالة، يجب عليك تحديد الحزم المسموح ببرامج البناء الخاصة بها في package.json الرئيسي وتجاوز التقييد عبر الأوامر.

`json
{
"name": "@org/monorepo-root",
"private": true,
"allowBuilds": {
"esbuild": true,
"sharp": true,
"@fast-cve/patch-pkg": true
}
}

`

تدفق العمل لتجاوز المحظر وتطبيق حزمة الإصلاح العاجل يكون كالتالي:

`bash

1. الموافقة اليدوية وإضافة حزمة الإصلاح العاجل التي لم تمضِ عليها 24 ساعة

nub add --allow-build=@fast-cve/patch-pkg @fast-cve/patch-pkg@1.0.1-hotfix

2. الموافقة الجماعية على سكريبتات البناء الموجودة في قائمة الانتظار

nub approve-builds

`

عند تشغيل nub approve-builds، يتم رفع الحظر ومتابعة عملية البناء فورًا. أما الحزم المسجلة في قاعدة بيانات OSV كبرمجيات خبيثة (MAL-*)، فلن يتم تجاوزها حتى بهذا الأمر، وفي تلك الحالة يتعين عليك البحث عن إصدار بديل أعلى.

فصل طبقات التخزين المؤقت (Cache Layers) في GitHub Actions وDocker

لرفع سرعة CI/CD، تحتاج إلى معرفة مسارات التخزين المؤقت لـ Nub. يتم تخزين ملفات Node الثنائية في ~/.cache/nub/node/<version>/، بينما ينقسم متجر الحزم القابل للعنونة بالمحتوى (CAS) بين ~/.cache/nub/ وnode_modules/.store/.

في بناء Docker متعدد المراحل، يجب استخدام نقطة تثبيت التخزين المؤقت (cache mount) الخاصة بـ BuildKit لعزل طبقة التثبيت تمامًا للاستفادة من التخزين المؤقت.

`dockerfile
FROM ghcr.io/nubjs/nub:latest AS base
WORKDIR /app

FROM base AS dependencies
COPY package.json nub.lock pnpm-workspace.yaml ./
COPY packages/core/package.json ./packages/core/
COPY packages/api/package.json ./packages/api/

إعادة استخدام المتجر عبر نقطة تثبيت التخزين المؤقت لـ BuildKit

RUN --mount=type=cache,target=/root/.cache/nub
nub ci --prefer-offline

FROM dependencies AS builder
COPY . .
RUN nub run build --filter=@org/api

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

COPY --from=builder /app/packages/api/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000
CMD ["node", "dist/index.js"]

`

في GitHub Actions، يتم استخدام nubjs/setup-nub@v0 بدلاً من actions/setup-node.

`yaml
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

  - uses: nubjs/setup-nub@v0
    with:
      cache: true

  - run: nub ci
  - run: nub -r run build
  - run: nub -r run test

`

تصل سرعة nub ci عند دمج setup-nub مع التخزين المؤقت إلى حوالي 346 مللي ثانية. مقارنة بـ pnpm التقليدي (3453 مللي ثانية)، ينخفض وقت تثبيت الحزم في أنبوب التوصيل (pipeline) بشكل كبير، مما يقلل إجمالي وقت بناء CI إلى النصف. وبالتأكيد ستشعر بالرضا عند الاطلاع على فاتورة البنية التحتية السحابية في نهاية الشهر.

توحيد بيئة التطوير لأعضاء الفريق مرة واحدة باستخدام Shell Wrapper

يتضمن Nub مترجمًا مدمجًا للذاكرة (in-memory transpiler) يعتمد على oxc، مما يسمح بتشغيل كود TypeScript مباشرة دون الحاجة إلى tsx أو ts-node. كما أنه يقرأ ملفات .env تلقائيًا. ومع اختفاء حمل التمهيد الإضافي (bootstrapping overhead) لعملية Node.js الذي كان يظهر في كل مرة عند استخدام pnpm run (442.7 مللي ثانية)، ينخفض وقت تنفيذ السكريبت مع nub run إلى 14.7 مللي ثانية، وهو فارق ملموس للغاية.

ولمنع تشتت إصدارات Node.js بين أعضاء الفريق، يكفي وضع ملف .node-version في المجلد الرئيسي.

`bash
echo "22.15.0" > .node-version
nub src/index.ts

`

في Node 22.15.0 وما فوق، يختفي تأخير التشغيل البارد (cold start) تمامًا بفضل module.registerHooks() التزامني. وعند انضمام عضو جديد للفريق، فإن إعداد سكريبت أتمتة واحد هو أطرق طريقة لضبط البيئة دفعة واحدة دون الحاجة لشروحات معقدة.

`bash
#!/usr/bin/env bash
set -euo pipefail

echo "==> بدء إعداد بيئة التطوير"

if ! command -v nub &> /dev/null; then
if command -v brew &> /dev/null; then
brew install nubjs/tap/nub
else
npm install -g --ignore-scripts=false @nubjs/nub
fi
fi

توجيه أوامر pnpm و npm تلقائيًا إلى محرك Nub

nub pm shim
nub node install
nub install

if [ ! -f ".env.local" ] && [ -f ".env.example" ]; then
cp .env.example .env.local
fi

echo "==> اكتمل الإعداد. قم بالتجميع عبر 'nub run dev'."

`

بمجرد تشغيل nub pm shim، حتى لو قمت بكتابة pnpm install أو npm run بحكم العادة، سيتم اعتراض الأمر ومعالجته عبر مشغل Nub. وبالإضافة إلى تقليل الحمل الإضافي لتنفيذ CLI من pnpm exec (191 مللي ثانية) إلى nubx (11 مللي ثانية)، فإن هذا يوفر عليك ساعتين أسبوعيًا على الأقل من وقت تصحيح الأخطاء واستكشاف الأعطال الناتجة عن مقولات مثل "الأمر لا يعمل على جهوزي".