Εισαγωγή στα σενάρια NPM

Τα σενάρια NPM είναι από τα αγαπημένα μου χαρακτηριστικά του NPM. Είναι απλά. Μειώνουν την ανάγκη για εργαλεία. Ως εκ τούτου, μειώνουν τον αριθμό των αρχείων διαμόρφωσης και άλλα πράγματα που πρέπει να παρακολουθείτε. Και είναι πολύ ευπροσάρμοστα. Σας επιτρέπουν επίσης να αυτοματοποιήσετε πολλές κοινές εργασίες. μερικά από τα οποία παρατίθενται στο τέλος του άρθρου.

Χωρίς άλλη παραλλαγή, ας δούμε σενάρια NPM!

Τι είναι τα σενάρια NPM;

Τα σενάρια NPM είναι, καλά, σενάρια. Χρησιμοποιούμε σενάρια για την αυτοματοποίηση επαναλαμβανόμενων εργασιών. Για παράδειγμα, δημιουργώντας το έργο σας, ελαχιστοποιώντας τα αρχεία Cascading Style Sheets (CSS) και JavaScript (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" στην κονσόλα. Προσθέστε αυτό στο αντικείμενο scripts του αρχείου package.json:

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

Το αντικείμενο scripts στο αρχείο 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. Η κονσόλα λέει, "Γεια σου Κόσμος!"! Έχουμε γράψει το πρώτο μας σενάριο 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 εκτελούνται στο κέλυφος, η κλήση npm run say-helloσε άλλο σενάριο NPM είναι σχεδόν διαισθητική.

Για όσους από εσάς δεν είστε πολύ άνετοι με εντολές τερματικού, &&το σενάριο χρησιμοποιείται για την οριοθέτηση δύο εντολών. Έτσι, η δεύτερη εντολή εκτελείται μετά την επιτυχή εκτέλεση της πρώτης εντολής.

Τώρα, όταν εκτελείτε npm run awesome-npm, το σενάριο «γεια-γεια» εκτελείται πρώτα, βγάζοντας το «Hello World» στην κονσόλα, ακολουθούμενο από το τμήμα του σεναρίου μετά το &&, το οποίο εξάγει «Το NPM είναι φοβερό!»

Ακολουθεί μια περίπτωση χρήσης όπου αυτό μπορεί να είναι χρήσιμο. Ας υποθέσουμε ότι αυτοματοποιείτε τη διαδικασία δημιουργίας της εφαρμογής σας. Ας υποθέσουμε ότι χρησιμοποιείτε το Webpack ως πακέτο και ο κωδικός διανομής σας πηγαίνει σε έναν κατάλογο που ονομάζεται "dist".

Μπορείτε να ξεκινήσετε με τον καθαρισμό του καταλόγου. Αυτό μπορεί να γίνει είτε με τη διαγραφή του περιεχομένου του είτε με τη διαγραφή του ίδιου του καταλόγου και, στη συνέχεια, με τη δημιουργία του ξανά. Ας ακολουθήσουμε την τελευταία προσέγγιση. Η εντολή σας μπορεί να μοιάζει με αυτό:

rm -r dist && mkdir dist
Σημειώστε ότι αυτό χρησιμοποιεί εντολές bash. Θα μάθετε πώς να γράφετε σενάρια NPM μεταξύ πλατφορμών αργότερα σε αυτό το άρθρο.

Μετά από αυτό, μπορείτε να καλέσετε το bundler εκτελώντας την webpackεντολή.

Μπορείτε να εκτελέσετε αυτές τις εντολές διαδοχικά χρησιμοποιώντας το &&χειριστή. Ωστόσο, για λόγους επίδειξης και αρθρωτότητας, ας το χωρίσουμε σε δύο σενάρια NPM που καλούν το ένα το άλλο.

Εδώ θα μοιάζει το αντικείμενο σεναρίων σε αυτήν την περίπτωση χρήσης:

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

Ορίστε! Πώς να χωρίσετε μια πιο περίπλοκη εργασία σε μικρότερα σενάρια NPM.

Κλήση σεναρίων Shell και Node

Μερικές φορές, ίσως χρειαστεί να γράψετε σενάρια πολύ πιο περίπλοκα από αυτά που μπορούν να επιτευχθούν σε 2-3 εντολές. Όταν προκύπτει αυτή η κατάσταση, μια λύση είναι να γράψετε σενάρια bash ή JS (ή σενάρια σε οποιαδήποτε γλώσσα δέσμης ενεργειών θέλετε) και να τα καλέσετε από σενάρια NPM.

Let’s quickly write a bash script that says hello to you. Create a file called hello.sh in your root directory and paste this code in it:

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

It’s a simple script that echoes your name back to you. Now modify the package.json file so that the scripts object has this line of code:

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

Now, when you run npm run bash-hello, it asks you for your name and then says hello to you! Brilliant.

You can do the same thing with JS scripts run using node. An advantage of this approach is that this script will be platform independent since it uses node to run. Here’s a slightly more complex JS script to add two integers received as command line arguments (put this in a file named 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

Λαμπρός! Τώρα είμαστε σε θέση να γράφουμε πολύ πιο ισχυρά σενάρια και να αξιοποιήσουμε τη δύναμη άλλων γλωσσών σεναρίου.

Προ και Post Hooks

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.

Καλή κωδικοποίηση! :)