مشكلات التوافق وتحسين CI التي يجب معالجتها قبل الانتقال إلى TypeScript 7
29 de julho de 2026
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
تم إطلاق TypeScript 7 الذي أُعيدت كتابة المترجم الخاص به باستخدام لغة Go. ومع الأخبار التي تفيد بأن سرعة التحقق من الأنواع أصبحت أسرع بما يصل إلى 12 مرة، ستكون الفرق التي تدير مستودعات موحدة (Monorepos) ضخمة حريصة على الانتقال إليه في أقرب وقت ممكن. في الواقع، صرّح فريقا الهندسة في Vanta و VS Code بأنهما تمكنا من تقليل وقت بناء خطوط أنابيب CI بنسبة تتجاوز 80%.
ولكن تطبيق التحديث بشكل عشوائي قد يؤدي إلى تعطل خط أنابيب CI بالكامل. يعود ذلك إلى أنه مع التحول إلى الثنائيات المضمنة (Native binaries)، تم تأجيل دعم واجهات برمجة تطبيقات التحليل الاستاتيكي (Static Analysis APIs) الحالية إلى الإصدارات اللاحقة. وبالتالي، فإن الأدوات التي كانت تفحص واجهات برمجة التطبيقات الداخلية عبر require('typescript') مثل @typescript-eslint أو ts-morph ستتوقف عن العمل تمامًا. وعلى الرغم من أن الأداء مغرٍ جدًا، إلا أن انكسار سلسلة الأدوات (Toolchain) يُعد مشكلة أخرى. وللحفاظ على استمرارية النشر مع الاستفادة من ميزة السرعة، يلزمك اتخاذ بعض الحلول البديلة.
يمنع ثنائي tsc في TypeScript 7.0 استدعاء الوحدات النمطية الداخلية لـ Node.js تمامًا. وتتسبب الحزم التي كان يتم استيرادها واستخدامها في بيئة JS كالمعتاد في إطلاق أخطاء فورية أثناء وقت البناء. وإذا قمت بزيادة رقم الإصدار فقط دون تحضير، فسيؤدي ذلك إلى شلل خط أنابيب CI بالكامل.
من الأفضل وضع نص برمجي للتشخيص في أعلى خط الأنابيب للأمان. تقوم هذه الطريقة بمسح جميع ملفات package.json و tsconfig.json داخل مساحة العمل للعثور على الخيارات أو الحزم التي يرفضها TS 7. وإذا كانت هناك إعدادات من إصدارات قديمة مثل ignoreDeprecations أو target: es5 متبقية، فسيتسبب ذلك في إخراج خطأ فورًا وإيقاف العملية.
`javascript
// scripts/check-ts7-compatibility.mjs
import fs from 'node:fs';
import { globSync } from 'glob';
const INCOMPATIBLE_DEPS = [
'ts-morph',
'ts-node',
'@babel/plugin-transform-typescript',
'typescript-eslint',
'@typescript-eslint/parser'
];
const DEPRECATED_TSCONFIG_OPTIONS = ['target:es5', 'moduleResolution:node', 'baseUrl', 'ignoreDeprecations'];
function runDiagnostics() {
console.log('TypeScript 7 호환성 사전 진단 시작...');
let hasError = false;
const packageFiles = globSync('/package.json', { ignore: '/node_modules/' });
for (const file of packageFiles) {
const content = JSON.parse(fs.readFileSync(file, 'utf8'));
const allDeps = { ...content.dependencies, ...content.devDependencies };
for (const dep of INCOMPATIBLE_DEPS) {
if (allDeps[dep]) {
console.warn([의존성 경고] ${file}: '${dep}' 패키지는 TS7 네이티브 API와 호환되지 않습니다.);
hasError = true;
}
}
}
const tsconfigFiles = globSync('/tsconfig*.json', { ignore: '/node_modules/' });
for (const file of tsconfigFiles) {
const rawContent = fs.readFileSync(file, 'utf8');
for (const opt of DEPRECATED_TSCONFIG_OPTIONS) {
if (rawContent.includes(opt)) {
console.error([설정 오류] ${file}: 무효화된 옵션 발견 -> '${opt}');
hasError = true;
}
}
}
if (hasError) process.exit(1);
}
runDiagnostics();
`
كما أن محولات AST المخصصة التي تعتمد على ts.createProgram() أو ts.transform() لن تعمل أيضًا. لا يدعم TS 7.0 حقن إضافات JS الخارجية. ويجب استبدال هذه المنطق بـ وحدات ربط Rust/C++ مثل SWC أو Babel، أو فصلها خارج مرحلة التجميع.
| خيار المترجم | سلوك TypeScript 6.0 | سلوك TypeScript 7.0 | كيفية التعامل |
|---|---|---|---|
target |
تحذير عند استخدام es5 |
Hard Error (إيقاف التجميع) | التغيير إلى es2022 أو أعلى |
moduleResolution |
السماح بإعداد node |
Hard Error | التغيير إلى bundler أو node16 |
baseUrl |
السماح بالاستخدام المنفرد | Hard Error | التحول لاستخدام compilerOptions.paths بمفرده |
ignoreDeprecations |
تجاهل التحذير يعمل | إبطال الخيار وحدوث خطأ | حذف الإعداد المعني تمامًا |
strict |
القيمة الافتراضية false |
القيمة الافتراضية true |
تعيين قيمة صريحة داخل tsconfig.json |
يستفيد TypeScript 7 من نموذج الخيوط (Threading model) الخاص بلغة Go. فهو يوفر خيارات جديدة مثل --checkers لمعالجة فحص الأنواع بالتوازي و --builders للتحكم في بناء مراجع المشروع. استخدم فريق الهندسة في Slack هذه الخيارات معًا لتقليل وقت فحص الأنواع من 20 دقيقة إلى 4.5 دقيقة. ولكن إذا قمت بتعيين عدد خيوط مفرط لا يتناسب مع عدد الأنوية، فسيزداد الحمل الإضافي لتبديل السياق (Context switching overhead) في وحدة المعالجة المركزية، وسيتعطل البناء بسبب نفاد الذاكرة (OOM).
من الأفضل تحديد عدد الخيوط وفقًا للصيغة التالية بناءً على مواصفات المشغل (Runner). إذا افترضنا أن عدد الأنوية المخصصة للجهاز الافتراضي هو ، وإجمالي الذاكرة ، والذاكرة المحجوزة لنظام التشغيل ()، ومتوسط استهلاك الذاكرة لكل عامل ()، فإن العدد الأمثل للخيوط للمشروع الواحد سيكون كالتالي:
N_{checkers} = minleft( C_{vCPU}, leftlfloor rac{M_{total} - M_{OS}}{M_{worker}} ight floor ight)يجب ألا يتجاوز إجمالي مجموع الخيوط قيمة . على سبيل المثال، في بيئة مشغل بـ 8 vCPU / 16GB، يكون الإعداد المناسب هو --checkers 4 و --builders 2.
`yaml
name: Monorepo Parallel Typecheck
on:
push:
branches: [main]
jobs:
typecheck:
runs-on: ubuntu-latest-8-core
steps:
- name: Checkout Codebase
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Purge Legacy TS 6.0 Cache
run: find . -name "*.tsbuildinfo" -not -path "*/node_modules/*" -delete
- name: Execute TS 7 Parallel Check
run: npx tsc --build --checkers 4 --builders 2 --verbose
`
هناك نقطة تنبيه مهمة. محرك التجميع التزايدي (Incremental compilation engine) في TS 7 لا يتوافق في التنسيق مع ملفات ذاكرة التخزين المؤقت .tsbuildinfo الخاصة بالإصدار القديم TS 6. وإذا لم تقم بحذف ذاكرة التخزين المؤقت للإصدار القديم قبل البناء باستخدام find . -name "*.tsbuildinfo" -delete، فسيكون هناك خطأ في التجزئة (Segmentation fault).
تم أيضًا إصلاح خادم اللغة الخاص بالمحررات ليعتمد على ثنائي Go المبنّي على LSP. وفقًا لنتائج اختبار AWS CodeBuild، انخفض الوقت الاستغراقي لظهور أول خطأ في النوع عند فتح ملف في مستودع موحد ضخم من 17.5 ثانية إلى 1.3 ثانية.
لتوحيد بيئة VS Code لأعضاء الفريق، يمكنك إدراج الإعدادات التالية في .vscode/settings.json في جذر المستودع الموحد:
`json
{
"typescript.tsdk": "node_modules/typescript/lib",
"js/ts.experimental.useTsgo": true,
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"files.associations": {
"*.tsbuildinfo": "json"
}
}
`
في بعض الأحيان، قد يحدث تعارض مع الإضافات الخاصة بلغات القوالب مثل Vue أو Svelte، مما يؤدي إلى توقف تحليل القواعد (Syntax parsing). في هذه الحالة، يمكنك الضغط على (Ctrl+Shift+P) لفتح لوحة الأوامر واختيار TypeScript: Select TypeScript Version... للرجوع إلى محرك TS 6.0 الحالي والعمل عليه.
إذا كانت هناك حزم قديمة متشابكة في المشروع ولا يمكنك ترقية ESLint إلى بيئة TS 7 في الوقت الحالي، يمكنك الالتفاف على ذلك باستخدام تكوين المحرك المزدوج (Dual engine) الذي يستخدم المترجمين معًا. تقوم بتوصيل واجهة برمجة تطبيقات TS 6 بأدوات التحليل الاستاتيكي، بينما تسند عملية الفحص الفعلي للأنواع والبناء فقط إلى الثنائي المضمن في TS 7.
قم بتحديد أسماء مستعارة للحزم (Package Alias) في package.json لتثبيت المترجمين في نفس الوقت:
`json
{
"name": "monorepo-root",
"private": true,
"devDependencies": {
"typescript": "npm:@typescript/typescript6@^6.0.2",
"@typescript/native": "npm:typescript@^7.0.2",
"eslint": "^9.0.0",
"typescript-eslint": "^8.0.0"
},
"scripts": {
"typecheck": "ts-native --build",
"typecheck:legacy": "tsc6 --noEmit",
"lint": "eslint ."
}
}
`
في هذه الحالة، سيكون من الآمن إرفاق نص برمجي للبناء الخفي (Shadow Build) بـ CI. يمكنك مقارنة نتائج التشخيص من TS 6 الحالي و TS 7 باستخدام diff لمراقبة ما إذا كانت النتائج تتغير في أنواع القوالب النصية (Template literal types) أو استنتاج الأنواع الشرطية (Conditional type inference).
`bash
#!/usr/bin/env bash
set -e
echo "=== 1. 기존 TS 6.0 컴파일러 진단 출력 생성 ==="
npx tsc6 --noEmit --pretty false > ./ts6-baseline.log 2>&1 || true
echo "=== 2. 신규 TS 7.0 네이티브 컴파일러 진단 출력 생성 ==="
npx --package @typescript/native tsc --noEmit --pretty false > ./ts7-output.log 2>&1 || true
echo "=== 3. 진단 결과 Diff 대조 검증 ==="
DIFF_RESULT=$(diff ./ts6-baseline.log ./ts7-output.log || true)
if [ -z "DIFF_RESULT"
exit 0
fi
`
وحتى يتم حل مشكلات توافق سلسلة الأدوات، فمن العملي فصل أدوار الـ Linting وفحص الأنواع وتشغيل كل منهما على حدة. من خلال تنظيف الخيارات التي قد تسبب مشاكل باستخدام النص البرمجي للتشخيص المسبق، وضبط الخيوط لتتناسب مع مواصفات البنية التحتية لـ CI، يمكنك الحصول على مزايا تحسين السرعة دون حدوث المؤسفة المتمثلة في توقف خط أنابيب النشر.