مقدمة لنصوص NPM

تعد نصوص NPM من بين ميزاتي المفضلة لـ NPM. إنها بسيطة. إنها تقلل من الحاجة إلى الأدوات. ومن ثم فهي تقلل من عدد ملفات التكوين والأشياء الأخرى التي تحتاج إلى تتبعها. وهم متعددون جدا. كما أنها تتيح لك أتمتة الكثير من المهام الشائعة. بعضها مدرج في نهاية المقال.

بدون مزيد من اللغط ، دعنا نتعمق في نصوص NPM!

ما هي البرامج النصية NPM؟

نصوص NPM هي ، حسنًا ، نصوص. نحن نستخدم البرامج النصية لأتمتة المهام المتكررة. على سبيل المثال ، بناء مشروعك ، تصغير أوراق الأنماط المتتالية (CSS) وملفات جافا سكريبت (JS). تستخدم البرامج النصية أيضًا في حذف الملفات والمجلدات المؤقتة وما إلى ذلك. هناك العديد من الطرق لسحب هذا - يمكنك كتابة نصوص bash / batch ، أو استخدام عداء مهام مثل Gulp أو Grunt. ومع ذلك ، ينتقل الكثير من الأشخاص إلى نصوص NPM لبساطتها وتنوعها. كما أنها توفر إمكانية وجود عدد أقل من الأدوات للتعلم والاستخدام والمتابعة.

الآن بعد أن أصبح لدينا (بعض) فكرة عن ماهية نصوص NPM وما يمكن أن تفعله لنا ، دعنا نمضي قدمًا ونكتب بعضها!

كائن البرامج النصية في package.json

سيحدث معظم عملنا في ملف package.json الذي يستخدمه NPM كمظهر من نوع ما. هذا هو الملف الذي تم إنشاؤه عند التشغيلnpm init.

فيما يلي نموذج لملف package.json:

{ "name": "super-cool-package", "version": "1.0.0", "scripts": { ... }, "dependencies": { ... } "devDependencies": { ... } }

إذا كنت تعمل مع NodeJS و NPM ، فستكون على دراية بملف package.json. لاحظ scriptsالكائن في الملف. هذا هو المكان الذي ستذهب إليه نصوص NPM الخاصة بنا. تتم كتابة البرامج النصية NPM كأزواج قيمة مفتاح JSON المعتادة حيث يكون المفتاح هو اسم البرنامج النصي والقيمة تحتوي على البرنامج النصي الذي تريد تنفيذه.

ربما يكون هذا هو البرنامج النصي الأكثر شيوعًا NPM (وهو أيضًا نوع خاص من البرامج النصية):

"scripts": { "start": "node index.js", ...}

ربما تكون قد رأيت هذا مرات عديدة في ملفات package.json الخاصة بك. وربما تعلم أنه يمكنك الكتابة npm startلتنفيذ البرنامج النصي. لكن هذا المثال يوضح الجانب الأول المهم من نصوص NPM - فهي ببساطة أوامر طرفية. يتم تشغيلها في غلاف نظام التشغيل الذي تم تنفيذها عليه. لذلك قد يكون bash لـ Linux و cmd.exe لنظام التشغيل Windows.

في هذه المرحلة ، قد لا تتأثر بالأحرى. لكن استمر في القراءة لترى مدى قوة نصوص NPM حقًا.

البرامج النصية المخصصة

النص الذي رأيناه للتو هو أحد نصوص NPM "الخاصة". يمكنك تنفيذه ببساطة عن طريق الكتابة npm start. هذه نصوص برمجية بأسماء يتعرف عليها NPM ويعلق عليها معنى خاصًا. على سبيل المثال ، يمكنك كتابة نص يسمى prepublish. سيقوم NPM بتنفيذ البرنامج النصي قبل حزم الحزمة الخاصة بك ونشرها ، وأيضًا عند التشغيل npm installمحليًا بدون أي وسيطات. المزيد عن هذه النصوص هنا.

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

لنلقِ نظرة على برنامج نصي NPM مخصص أساسي للغاية ينتج عنه "hello world" إلى وحدة التحكم. أضف هذا إلى كائن البرامج النصية لملف package.json الخاص بك:

"say-hello": "echo 'Hello World'"

يجب أن يبدو كائن البرامج النصية في ملف package.json بالشكل التالي:

..."scripts": { "start": "node index.js", "say-hello": "echo 'Hello World!'"}

حاول الآن الركض npm say-hello. لا يعمل؟ وذلك لأن البرامج النصية المخصصة NPM يجب أن يسبقها أحدهما run-scriptأو runليتم تنفيذها بشكل صحيح. حاول الجري npm run-script say-helloأو npm run say-hello. تقول وحدة التحكم ، "Hello World!"! لقد كتبنا أول برنامج نصي NPM لدينا!

إليك نصيحة سريعة - من أجل منع سجلات NPM الافتراضية من الإخراج إلى وحدة التحكم عند تنفيذ برنامج نصي ، أضف --silentالعلامة. هذا ما سيبدو عليه الأمر الخاص بك:

npm run --silent say-hello

استدعاء البرامج النصية NPM ضمن البرامج النصية الأخرى لـ NPM

يظهر جانب سلبي لاستخدام البرامج النصية NPM عندما يكون النص معقدًا (وطويلًا) إلى حد ما. تتفاقم هذه المشكلة بسبب حقيقة أن مواصفات JSON لا تدعم التعليقات. هناك عدة طرق للتغلب على هذه المشكلة. تتمثل إحدى الطرق في تقسيم البرنامج النصي إلى نصوص برمجية صغيرة ذات غرض واحد ثم استدعائها ضمن البرامج النصية الأخرى لـ NPM. طريقة استدعاء برنامج نصي NPM داخل آخر هو طريقة مباشرة. قم بتعديل scriptsالكائن الخاص بك بحيث يبدو كما يلي:

"scripts": { "say-hello": "echo 'Hello World'", "awesome-npm": "npm run say-hello && echo 'echo NPM is awesome!'"}

نظرًا لأن نصوص NPM يتم تنفيذها في shell ، فإن الاتصال npm run say-helloداخل برنامج نصي NPM آخر يكون أمرًا بديهيًا تقريبًا.

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

الآن عند التشغيل npm run awesome-npm، يتم تنفيذ النص البرمجي say-hello أولاً ، مع إخراج "Hello World" إلى وحدة التحكم ، متبوعًا بجزء من البرنامج النصي بعد the &&، والذي ينتج عنه "NPM رائع!"

إليك حالة استخدام حيث قد يكون ذلك مفيدًا. افترض أنك تقوم بأتمتة عملية إنشاء التطبيق الخاص بك. لنفترض أنك تستخدم Webpack كمجمع وأن كود التوزيع الخاص بك ينتقل إلى دليل يسمى "dist".

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

rm -r dist && mkdir dist
لاحظ أن هذا يستخدم أوامر bash. سوف تتعلم كيفية كتابة نصوص NPM عبر الأنظمة الأساسية لاحقًا في هذه المقالة.

بعد ذلك ، يمكنك استدعاء المجمّع من خلال تنفيذ webpackالأمر.

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

إليك ما سيبدو عليه كائن البرامج النصية في حالة الاستخدام هذه:

"scripts": { ... "clean": "rm -r dist && mkdir dist", "build": "npm run clean && webpack"}

ها أنت ذا! كيفية تقسيم مهمة أكثر تعقيدًا إلى نصوص برمجية NPM أصغر.

استدعاء البرامج النصية شل والعقدة

في بعض الأحيان ، قد تضطر إلى كتابة نصوص أكثر تعقيدًا بكثير من تلك التي يمكن تحقيقها في 2-3 أوامر. عند ظهور هذا الموقف ، يتمثل أحد الحلول في كتابة نصوص bash أو JS (أو نصوص برمجية بأي لغة برمجة تريدها) واستدعائها من نصوص NPM.

دعنا نكتب سريعًا نصًا باش يقول مرحبًا لك. قم بإنشاء ملف يسمى hello.shفي الدليل الجذر الخاص بك والصق هذا الرمز فيه:

#!/usr/bin/env bash
# filename: hello.shecho "What's your name?"read nameecho "Hello there, $name!"

إنه نص بسيط يردد اسمك لك. الآن قم بتعديل package.jsonالملف بحيث scriptsيحتوي الكائن على سطر التعليمات البرمجية هذا:

"bash-hello": "bash hello.sh"

الآن ، عندما تجري npm run bash-hello، يسألك عن اسمك ثم يقول لك مرحبًا! متألق.

يمكنك فعل الشيء نفسه مع نصوص JS التي تعمل باستخدام العقدة. ميزة هذا النهج هي أن هذا البرنامج النصي سيكون مستقلاً عن النظام الأساسي لأنه يستخدم عقدة للتشغيل. إليك نص JS أكثر تعقيدًا قليلاً لإضافة عددين صحيحين تم استلامهما كوسيطات سطر أوامر (ضع هذا في ملف باسم add.js):

// add.js// adds two integers received as command line arguments
function add(a, b) { return parseInt(a)+parseInt(b);}
if(!process.argv[2] || !process.argv[3]) { console.log('Insufficient number of arguments! Give two numbers please!');}
else { console.log('The sum of', process.argv[2], 'and', process.argv[3], 'is', add(process.argv[2], process.argv[3]));}
يحتوي الكائن process.argv على وسيطات سطر الأوامر المعطاة للبرنامج النصي. يتم حجز أول عنصرين ، process.argv[0]و process.argv[1]بواسطة العقدة. وهكذا process.argv[2]و process.argv[3]تتيح لك الوصول إلى وسائط سطر الأوامر.

أضف الآن هذا السطر إلى scriptsكائن package.jsonالملف:

"js-add": "node add.js"

أخيرًا ، قم بتشغيل البرنامج النصي باعتباره برنامج نصي npm عن طريق إعطائه رقمين كوسائط سطر أوامر:

npm run js-add 2 3

وفيولا! الإخراج

The sum of 2 and 3 is 5

متألق! نحن الآن قادرون على كتابة نصوص أكثر قوة والاستفادة من قوة لغات البرمجة النصية الأخرى.

خطاف ما قبل وبعد

Remember how we talked about a special npm script called prepublish that runs before you publish your package? Such a functionality can be achieved with custom scripts too. We’ve discussed one way to do this in the previous section. We can chain commands using the &&operator, so if you wanted to run script-1 before script-2, you would write:

"script-2": "npm run script-1 && echo 'I am script-2'"

However, this makes our scripts a little dirty. This is because the core functionality of the script is reflected only in the second part of the command (after the && ). One way to write clean scripts is to use pre and post hooks.

Pre and post hooks are exactly what they sound like — they let you execute scripts before and after you call a particular script. All you have to do is define new scripts with the same name as your main script. Yet these are prefixed with “pre” or “post” depending on whether the script is executed before the main script or after it.

Let’s look at our say-hello script again. Say we want to execute the command echo 'I run before say-hello' before say-hello and echo 'I run after say-hello' after say-hello. This is what your scripts object would look like:

"scripts": { "say-hello": "echo 'Hello World'", "presay-hello": "echo 'I run before say-hello'", "postsay-hello": "echo 'I run after say-hello'" }

The “pre” and “post” before the script names tell npm to execute these before and after the script called say-hello respectively.

Now, when you run npm run say-hello, the output of all three scripts shows up in order! How cool is that?

Since all three scripts output to the console and the NPM logs clutter the output, I prefer using the -silent flag while running these. So your command would look like this:

npm run --silent say-hello

And here’s the output:

I run before say-helloHello WorldI run after say-hello

There you have it!

Let’s apply this knowledge to our build script example. Modify your package.json file so that it looks like this:

"scripts": { ... "clean": "rm -r dist && mkdir dist", "prebuild": "npm run clean" "build": "webpack"}

Now our scripts look much cleaner. When you run npm run build, prebuildis called because of the “pre” hook, which calls clean, which cleans up our dist directory for us. Sweet!

Making Our Scripts Cross-Platform

There is one drawback of writing terminal/shell commands in our scripts. This is the fact that shell commands make our scripts platform dependently. This is perhaps what draws our attention to tools like Gulp and Grunt. If your script is written for Unix systems, chances are, it won’t work on Windows, and vice versa.

The first time I used NPM scripts, which called other bash/batch scripts, I thought of writing two scripts per task. One for Unix and one for the Windows command line. This approach may work in use cases where the scripts aren’t that complex and there aren’t many scripts. However, it quickly becomes clear that they are not a good solution to the problem. Some of the reasons behind this are:

  • You have another thing to keep track of that distracts you from your primary task of working on the application. Instead, you end up working in the development environment.
  • You’re writing redundant code — the scripts you write are very similar and accomplish the same task. You’re essentially rewriting code. This violates one of the fundamental principles of coding — DRY: Don’t Repeat Yourself.

So how do we get around this? There are three approaches that you may use:

  1. Use commands that run cross-platform: Many useful commands are common to Unix and Windows. If your scripts are simple, consider using those.
  2. Use node packages: You can use node packages like rimraf or cross-env instead of shell commands. And obviously, you can use these packages in JS files if your script is large and complex.
  3. استخدم ShellJS: ShellJS عبارة عن حزمة npm تقوم بتشغيل أوامر Unix عبر Node. لذلك يمنحك هذا القدرة على تشغيل أوامر Unix على جميع الأنظمة الأساسية ، بما في ذلك Windows.
تم أخذ الأساليب المذكورة أعلاه من هذه المقالة الرائعة من قبل Cory House حول سبب تركه Grunt و Gulp لبرامج NPM. تفاصيل المقال أشياء كثيرة لم يتم تناولها في هذه السلسلة ويختتم بقائمة من الموارد الممتازة. أوصي بالتأكيد بقراءته لزيادة فهمك لنصوص NPM.

حالات استخدام قليلة لنصوص NPM

أخيرًا ، هناك الكثير الذي يمكنك القيام به باستخدام البرامج النصية NPM. بعض حالات الاستخدام هي:

  • تصغير / تقصير CSS / JavaScript
  • أتمتة عملية البناء
  • فحص التعليمات البرمجية الخاصة بك
  • ضغط الصور
  • إدخال التغييرات تلقائيًا باستخدام BrowserSync

And a lot more. To learn about how to automate the above-mentioned tasks using NPM scripts, check out this brilliant article on the topic.

Bonus: Commander for Creating CLI Applications Using NodeJS

While we’re discussing NPM scripts and the CLI, I’d like to quickly tell you about a really cool package called commander. Commander allows you to create your own CLI applications. This isn’t really related to NPM scripts, but it’s a cool piece of technology to know. Check out the commander docs here or try one of these tutorials:

  • Build An Interactive Command-Line Application with Node.js — Scotch.io
  • Writing Command Line Applications in NodeJS — freeCodeCamp

Concluding Words

هذا كل شيء لهذه المقالة حول استخدام البرامج النصية NPM. آمل أن تكون قد اكتسبت بعض الأفكار حول كيفية دمجها في مشاريعك الخاصة. هذه المقالة ليست بأي حال من الأحوال برنامج تعليمي متعمق حول البرامج النصية NPM. ومن ثم ، فإنني أوصيك بمعرفة المزيد من الموارد الأخرى ومن استخدام البرامج النصية لـ NPM في مشاريعك الخاصة.

أيضًا ، تواصل معي على GitHub و LinkedIn.

ترميز سعيد! :)