ما هو Deno ؟ وهل يشكل خطرا على Node.js ؟

قبل مدة قصيرة نشرت على تويتر تغريدة عبرت فيها عن غبطتي للمطورين والمبرمجين من الميادين الأخرى غير الويب، ذلك أن الأوضاع عندهم مستقرة أكثر وغير فوضوية بالمقارنة مع ما يحدث في ميدان الويب وبالخصوص في عالم جافا سكريبت الذي وصفته بالعالم الهستيري.

هستيريا جافا سكريبت

لم يمضي سوى أسبوعين أو ثلاثة على تلك التغريدة حتى زدت اقتناعا بها بعدما بدأ الحديث عن مولود جديد قادم لعالم جافا سكريبت ومنتظر أن يكون له أثر واضح في غضون السنوات القليلة القادمة، ومن المتوقع أن يزاحم Node.js على عرشه الذي تربع عليه من دون منافس طيلة عقد من الزمن كحل وحيد لتشغيل جافا سكريبت خارج المتصفحات.

هذا المولود الجديد اسمه Deno أو دينو الذي اشتق اسمه من Node نفسه، وهو من برمجة وتصميم ريان دال بالذات الذي صمم وبنى Node.js في عام 2009.

في 13 من شهر ماي الجاري أعلن عن الإصدار الأول الرسمي من Deno بعد عامين تقريبا من العمل الدؤوب وتأجيل تاريخ الإطلاق أكثر من مرة.

في هذه التدوينة سنتعرف على Deno وأهم مميزاته، وسنبني في الأخير خلاصة حول ما إذا كان يشكل خطرا وجوديا على Node.js أم لا 🤔

فكرة Deno

في منتصف عام 2018، شارك Ryan Dahl في أحد مؤتمرات جافا سكريبت بعد غياب طويل عن الساحة وألقى هناك كلمة خصصها للحديث عن أكثر عشرة أشياء ندم عليها بخصوص Node.js. فالمعلوم أن ريان هو من قام بتصميم هذا الأ خير قبل 11 عاما وظل يشرف على ذلك المشروع حتى تركه عام 2012 للمساهمين الآخرين.

تلك الأشياء العشرة كانت عبارة عن أخطاء - كما اعتبرها - في تصميم Node.js منعته من التطور في الإتجاه الذي كان يتمناه Ryan، وفرضت عليه مجموعة من القيود التي لم يعد يستطيع التخلص منها بعد أن بلغ المشروع مرحلة متقدمة من الإستقرار والإنتشار.

بعد انتهائه من الحديث عن تلك السلبيات، أماط ريان اللثام عن مشروعه الجديد الذي بدأه من الصفر والذي هدف من خلاله إلى تدارك كل نقاط الضعف التي رأى بأن Node.js يعاني منها، وأسماه Deno.

ما هو Deno إذن ؟

يقول الموقع الرسمي بأن دينو هو عبارة عن:

A secure runtime for JavaScript and TypeScript.

وباللغة العربية: Deno هو بيئة آمنة لتشغيل جافا سكريبت وتايب سكريبت، وهذا نفس تعريف Node.js باستثناء أن هذا الأخير لا يوفر دعما افتراضيا للغة TypeScript كما يفعل دينو.

كذلك دينو يوفر طبقة حماية تمنع أي برنامج من الوصول إلى أي ملف أو مورد من موارد النظام دون السماح له بذلك بشكل صريح (مثلا قراء ملف أو الكتابة فيه)، وهذه الميزة غير موجودة في Node.js.

بني Deno حول محرك V8 المستعمل في متصفحات Chromium وكذلك في Node.js، وتم اعتماد لغة البرمجة Rust في برمجته عوض لغة ++C المستخدمة في Node. بالإضافة إلى ذلك تم اللجوء لمكتبة مفتوحة المصدر تدعى Tokio لدعم العمليات الغير متزامنة (Non-blocking I/O) من خلال توفير ميزة Event Loop. هذه المكتبة تمت برمجتها كذلك بواسطة Rust وعوض بها ريان دال مكتبة Libuv المستخدمة في Node.js والمبنية على C.

البنية التقنية لبيئة التشغيل دينو

وعلى سبيل المزاح، يمكن اعتبار Deno المشروع الوحيد الذي جمع بين الثلاثة الكبار الذين لا يجتمعون عادة وهم: جوجل (V8)، مايكروسوفت (TypeScript) وموزيلا (Rust) 😅 😅

مميزات دينو

إذن كما قلنا، يتميز Deno عن Node.js بعدد من المميزات التي من الممكن أن يراها الكثير من الناس نقاطا تحسب لصالحه.

سنذكر منها الأهم فيما يلي.

1. دعم تايب سكريبت

يدعم Deno بشكل أصلي لغة البرمجة تايب سكريبت ويعطي لها اهتماما خاصا، حيث تم دمج مترجم خاص بهذه اللغة داخل Runtime مما يعني أن المطور لن يكون بحاجة لأي إعدادات أو حزم خارجية كما هو الحال في Node.js حيث يتم اللجوء لحزمة ts-node من طرف كل مستخدم يريد كتابة أكواد Node.js بلغة البرمجة TypeScript.

الدعم الإفتراضي لتايب سكريبت لا يعني بأي حال بأن دينو لا يدعم جافا سكريبت! بل على العكس، كلا اللغتين مدعومتين كما يجب مع الحرص على عدم إرسال أكواد جافا سكريبت لمترجم تايب سكريبت لأن هذا غير ضروري بطبيعة الحال.

2. الحماية

لكي نفهم جيدا عن ماذا سنتحدث هنا، سنبدأ في كتابة بعض أكواد Deno 😃

سنحاول مثلا قراءة محتوى ملف نصي وعرض ذلك المحتوى عبر console.log.

لنفترض بأنه لدينا ملف file.txt ومحتواه عبارة عن نص Hello World!.

أبسط طريقة لقراءة هذا الملف هي كالتالي:

قبل تجربة أي كود، ينبغي علينا طبعا تثبيت بيئة التشغيل Deno في جهازنا باتباع الطرق والخطوات المبينة في هذا الرابط.

index.ts
const decoder = new TextDecoder('utf-8');

const content: string = decoder.decode(await Deno.readFile('file.txt'));

console.log(affirmation);

تلاحظون بأننا قمنا بقراءة محتوى الملف عن طريق الوظيفة readFile()، وهي كما تلاحظون وظيفة غير متزامنة (Async).

لتشغيل هذا الكود، ينبغي علينا تنفيذ ما يلي:

deno run index.ts

index.ts هو اسم الملف حيث أكواد مشروعنا.

نتوقع أن يظهر لنا محتوى ملفنا Hello World! بعد تنفيذ ما سبق، ولكن على غير المنتظر نحصل على هذا الخطأ الذي يتسبب في توقف البرنامج.

error: Uncaught PermissionDenied: read access to "/path/to/your-app/file.txt", run again with the --allow-read flag

رسالة الخطأ واضحة وتقول بأنه ليس لدينا التصريح اللازم للوصول إلى ملف file.txt.

للحصول على ذلك التصريح ينبغي علينا استعمال العلم --allow-read. نفس الشيء سيواجهنا إذا حاولنا الكتابة في أي ملف حيث سيطلب منا حينذاك استخدام العلم --allow-write.

deno run index.ts --allow-read

الآن بعد إعطائنا الإذن اللازم للسكريبت للوصول إلى الملف، ستتم قراءة الأخير بنجاح وسيتم عرض محتواه كما يلي:

Compile file:///path/to/your-app/index.ts
Hello World!

هذه ميزة جيدة في الحقيقة إذ لا يمكن لأي برنامج Deno الوصول ل File System إلا بإذن صريح منا . وذات الحال ينطبق على عدد من المهام الأخرى مثل الوصول إلى متغيرات البيئة (ENV variables) عن طريق --allow-env، وكذلك إمكانية الوصول إلى شبكة الإنترنت عن طريق --allow-net إلخ...

3. نظام وحدات متوافق مع معايير ES2015

الحقيقة التي لم أشر إليها لحد الآن هي أن Deno يحاول قدر المستطاع الحفاظ على كافة الواجهات البرمجية والمزايا المتعارف عليها في متصفحات الويب، بحيث يتم ضمان توافقية جيدة في معظم الحالات بين كود Deno وأكواد جافا سكريبت أو تايب سكريبت التي يتم كتابتها للمتصفحات.

نظام الوحدات أوModules هو بالطبع من بين تلك المزايا المهمة التي ظهرت في عالم جافا سكريبت رسميا مع إصدار ES2015 الذي أضاف الشيء الكثير لهذه اللغة. لهذا السبب يدعم دينو بشكل افتراضي نظام وحدات ECMAScript وهي الميزة التي لم يوفرها Node.js للمطورين إلا في المدة الأخيرة بعد سنوات طويلة من الإعتماد على نظام CommonJS. وإلى اليوم مازال الأخير يستعمل على نطاق واسع في بيئة Node.

استيراد الوحدات في دينو يتم من خلال أي مسار أو رابط على هذا الشكل:

import Module from 'https://example.com/my-module.ts';
import { Test } from './my-module.ts';

أما التصدير (Export) فهو كذلك يتم بشكل اعتيادي بحيث لن نجد صعوبة في التعامل مع الوحدات في دينو ما دمنا تعاملنا في السابق معها في React على سبيل المثال أو غيرها من أطر عمل جافا سكريبت التي تشتغل في المتصفحات.

my-module.ts
export const myVar = "some text";
export function functionName(){...}
export default function functionName(){...}
export class ClassName {...}
export default class ClassName {...}
...

4. إدارة الحزم

إدارة الحزم من أكثر التغييرات الجذرية في دينو بالمقارنة مع ما هو موجود في Node.js.

نظام Package Management أعيد تعريفه بشكل كامل ليصبح شبيها بما هو موجود في الويب، حيث يمكن إعطاء المتصفح كود جافا سكريبت من أي رابط أو مسار. ليس شرطا أن تكون الحزمة موجودة في مكان مركزي مثل NPM، ولا وجود لهذا المكان (رسميا) أصلا في بيئة Deno.

إذن عندما نريد استدعاء حزمة في دينو فإننا نحتاج للرابط url أو المسار حيث هي موجودة، تماما مثلما نفعل دائما في تطبيقات الويب ناحية المتصفح.

import { serve } from 'https://deno.land/std@0.50.0/http/server.ts';

بعد أن يقوم دينو بتحميل تلك النسخ يقوم بوضعها في نظام cache خاص للرجوع إليها في المرات القادمة.

لإجبار Deno على إعادة تحميل النسخ من الإنترنت عوض الكاش نقوم بتمرير العلم --reload.

التحكم في الإصدارات (Versions)

للتحكم في نسخ الحزم المستخدمة في المشروع ينصح بإنشاء ملف اسمه deps.ts وإدراج جميع تلك الحزم فيه وتصديرها من هناك. هكذا سيكون لدينا مكان واحد يمكننا الرجوع إليه في حال أردنا تغيير نسخة أو إصدار واحدة من تلك الحزم.

deps.ts
export * as path from "https://deno.land/std@0.51.0/path/mod.ts";
index.ts
import { path } from './deps.ts';

5. مكتبة رسمية لعدد من الحزم الأساسية

يوفر دينو مكتبة مدعومة بشكل رسمي (Standard Library) ليتم التأكد من عملها بشكل جيد معه. وتشمل هذه المكتبة مجموعة من أهم الحزم والمكتبات الأكثر استخداما من طرف المطورين، وبالتالي يصبح لهؤلا مكان محدد وموثوق للحصول على تلك الحزم وضمان عملها وتوافقها بشكل ممتاز مع بيئة العمل.

أمثلة لتلك المكتبات:

  • ws: للتعامل مع WebSockets.
  • uuid: لتوليد معرفات عشوائية.
  • datetime: التعامل مع التواريخ .
  • http: خادم HTTP.
  • ...

6. السعي للتوافق مع كثير من معايير المتصفح

ذُكر آنفا أن أحد أهداف Deno هو الحفاظ على نوع من التوافق والتشابه بين ما يوفره من واجهات برمجية وما هو موجود في الويب كمعايير متعارف عليها.

بتعبير آخر، قام Deno باختيار أسماء مماثلة لتلك المستخدمة في بيئة الويب لعدد كبير من الوظائف والأحداث وكذلك الكلاسات، فحتى الكائن window تم الإحتفاظ به وهو الإسم الذي رأى القائمون على Node.js في الجهة المقابلة أن تغييره إلى global أفضل وأقرب إلى المنطق مادام لا يوجد شيء اسمه Window في بيئة الخادم.

وفيما يلي مجموعة من واجهات دينو البرمجية والوظائف التي ربما سبق لكثير منا التعامل معها في تطبيقات المتصفحات بنفس الأسماء:

  • addEventListener
  • fetch
  • Worker
  • onload
  • onunload
  • clearInterval
  • clearTimeout
  • dispatchEvent
  • removeEventListener
  • setInterval
  • setTimeout
  • File
  • FormData
  • console
  • location
  • self
  • window
  • Event
  • EventTarget
  • TextDecoder
  • TextEncoder
  • [...]

7. سلة أدوات مدمجة

يعج عالم جافا سكريبت اليوم أكثر من أي وقت مضى بأدوات لا حصر لها.. هذه أداة لترجمة الأكواد إلى ما تفهمه المتصفحات (Babel مثلا)، وتلك الأداة لتحزيم الوحدات (مثل ويب باك و parcel)، والأخرى لعمل الإختبارات (Testing)، دون أن ننسى ترتيب وتجميل الكود بواسطة مكتبات مثل Prettier.

هذه الأنواع الأربعة من الأدوات هي أقل ما يمكن أن تجده في مشروع لجافا سكريبت في يومنا هذا، ما يجعل حياة المطور ـ المبتدئ خاصة ـ أشبه بعذاب وكابوس لا يستيقظ منه حتى يجد نفسه في كابوس آخر ربما أسوء 😧

تقنية Deno حاولت وضع حد لهذه الحالة من التشتت وذلك بتوفير كثير مما سبق للمطور بالمجان ودون الحاجة لمكتبات خارجية أو إعدادات إضافية معقدة. فالمكتبة الرسمية مثلا توفر حزمة خاصة لإجراء اختبارا الأكواد البرمجية، وهناك أيضا ميزة Bundling و Compiling لعمل تحزيم وترجمة الكود المصدري مع إمكانية تخصيص تلك العملية لملاءمة احتياج المطور.

أما Code Formatting فيمكن عمله بواسطة واجهة deno fmt <file_name> بكل بساطة وبدون صداع رأس.

من الطبيعي ألا تتوفر لدى Deno كل الإمكانيات التي نجدها في مكتبات النظام البيئي ل NodeJs، ولكن هذه مجرد بداية ومن المتوقع أن يتم تحسين كل الأدوات أعلاه وإضافة أدوات أخرى لتغطية كافة الحالات الممكنة.

في الختام

لا شك في أن Deno جاء ليحاول لعب أدوار Node.js بطريقته الخاصة، وهي طريقة لاقت إعجاب شريحة عريضة من مطوري جافا سكريبت.

من جهة أخرى، Node.js لاعب لديه نقاط قوته كذلك وناضج بما فيه الكفاية ليبقى صامدا ومحتكرا للشريحة التي يسيطر عليها لفترات قادمة. وأمام دينو الكثير من العمل والجهد حتى يثبت للجميع بأنه خيار موثوق وقادر على جعلهم يعيدون النظر في اختياراتهم.

العديد من الشركات والمقاولات الكبرى استثمرت أموال وموارد مهمة في Node.js، وبطبيعة الحال ليس سهلا أن تتغير الأوضاع بين عشية وضحاها لمجرد ظهور لاعب جديد هنا أو هناك.

وبالنسبة لنا كمطورين من الجيد أن نبقى على اطلاع بكل هذه الصيحات الجديدة ونظل على استعداد للتأقلم مع متطلبات السوق متى احتاج الأمر لذلك.

شاركني رأيك في هذه التقنية الجديدة، وهل في رأيك ستزاحم بشكل جدي Node.js في السنوات القليلة المقبلة ؟


مراجع مهمة