Node.js tutorial for beginners. Part 3





Good day, friends!



I continue to post a translation of this Node.js tutorial .



Other parts:



Part 1

Part 2

Part 3

Part 4



Getting user entered data in Node.js



How do I make a Node.js program interactive?



To do this, version 7 of Node.js introduces the readline module : it is used to get data from a stream for reading, such as process.stdin- the command line during the execution of a Node.js program.



const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
})

readline.question(`What is your name?`, name => {
    console.log(`Hi ${name}!`)
    readline.close()
})


This code asks for the username, after the user has typed and clicked enter, a greeting is displayed.



The method question()prints the first parameter (question) to the console and waits for the user's response. When pressed enter, the callback function is executed.



In this callback, we close the interface readline.



readlinecontains other methods, which you can read about in the documentation.



If you need to prompt for a password, it is best not to return it explicitly, but rather use symbols *.



One way to do this is to use the readline-sync package , which is simple to understand and easy to configure.



A more complete and abstract solution is provided by the Inquirer.js package .



We install it with the help npm install inquirerand use it as follows:



const inquirer = require('inquirer')

const questions = [
    {
        type: 'input',
        name: 'name',
        message: `What's your name?`
    }
]

inquirer.prompt(questions).then(answers => {
    console.log(`Hi ${answers['name']}!`)
})


Inquirer.js allows you to do a lot of cool things, like suggesting multiple choices, providing radio buttons, asking for confirmation, etc.



It is better known as an alternative to built-in solutions, but if you plan to take user experience to the next level, Inquirer.js is the best solution.



Extending Node.js File Functionality Using Export



Node.js has a built-in modular system.



The Node.js file can import functionality from other Node.js files.



When you want to import something you use const library = require('./library')

to import functionality exported in a file library.jslocated in the current directory.



In this file, functionality must be exported before it can be imported in another file.



Any other object or variable defined in a file is by default private (private) and cannot be used in other files.



This is what the interface module.exportsprovided by the modular system allows us to do .



When you assign an object or function as a new property of the objectexports, you export them, and then they can be imported elsewhere in the application or in another application.



This can be done in two ways.



The first way is to assign a value module.exports, which is the default object provided by the modular system. This method allows you to export only this object:



const car = {
    brand: 'Ford',
    model: 'Fiesta'
}

module.exports = car 

//   
const car = require('./car')


The second way is to add the exported object as a property of the object exports. This method allows you to export many objects, functions or data:



const car = {
    brand: 'Ford',
    model: 'Fiesta'
}

exports.car = car


or so



exports.car = {
    brand: 'Ford',
    model: 'Fiesta'
}


To use this object in another file, you must make a link to the import:



const items = require('./items')
items.car 


or



const car = require('./items').car 


What is the difference between module.exportsand exports?



The first one exports the referenced object, the second one a property of the object.



An introduction to the npm package manager



Introduction to npm


npmIs the default Node.js package manager.



As of January 2017, npm had over 350,000 packages, making it the largest repository of code in a single programming language on Earth, and you can rest assured that there are packages to do just about anything.



It all started with downloading and managing dependencies in Node.js, but soon this tool began to be actively used in the development of the client side of applications.



npmdoes several things.



An alternative to npm is yarn .



Loading


npmmanages the loading of project dependencies.



If a file exists in the project, package.jsonlaunching npm installwill install everything that the project requires into the directory node_modulesthat is created if it does not exist.



A specific package can be installed using npm install <package-name>.



Often the installation of a package is accompanied by flags:



  • --save - install the package and add an entry about it to the dependencies section of the file package.json
  • --save-dev - install the package and add an entry about it to the devDependencies section of the file package.json


The main difference is that devDependencies is used for development purposes, for example, for testing, and dependencies are used in production (when building a project).



Updating packages


Updating is easy with npm update.



npmwill check all packages for new versions that meet the established restrictions.



You can also update a specific package: npm update <package-name>.



Versioning


In addition to standard downloads, npm supports versioning, so you can specify any specific version of a package, or request a newer or older version.



You will often find that one library is only compatible with a certain (major) version of another library.



And also with the bugs of the latest releases that have not been fixed for a long time.



Versioning also aids team development because each team member knows which version to use before updating the file package.json.



In all these cases, versioning helps; in this regard, npmit follows accepted standards.



Executing tasks


package.jsonsupports a format for specifying commands to be executed in the terminal with npm run <task-name>.



For example:



{
    "scripts": {
        "start-dev": "node lib/server-development",
        "start": "node lib/server-production"
    },
}


It is common practice to use this capability to run Webpack:

{
    "scripts": {
        "watch": "webpack --watch --progress --colors --config webpack.conf.js",
        "dev": "webpack --progress --colors --config webpack.conf.js",
        "prod": "NODE_ENV=production webpack -p --config webpack.conf.js"
    },
}


This allows, instead of a set of long commands that are easy to forget or which are easy to make mistakes, to do this:



npm run watch 
npm run dev 
npm run prod 




Where does npm install packages?



When installing packages using, npmyou can choose between two types of installation:



  • local
  • global


By default, when you enter npm installfor example:



npm install lodash 


the package is installed to a folder node_modulesin the current directory.



After installation npmadds an o record lodashto the dependenciesfile section package.jsonin the current directory.



For a global installation, use the flag -g:



npm install -g lodash 


In a global installation, the package is installed not in the current directory, but in the global one.



But where exactly?



To determine this, you need to run the command npm root -g.



On macOS or Linux, this directory can be /usr/local/lib/node_modules. On Windows - C:\Users\YOU\AppData\Roaming\npm\node_modules. This directory may be different



when used nvmfor Node.js versioning.



How do I use installed packages?



How to use a node_modulespackage installed in a folder or globally.



Let's say you installed a lodashpopular JavaScript helper library with npm install lodash.



This command will install lodashto a local directory node_modules.



To use the program, you need to import the package using require:



const _ = require('lodash')


What if the package is executable (file)?



In this case, the executable file will be placed in the directory node_modules/.bin/.



This can be easily demonstrated using the cowsay library .



This package provides a command line program, when executed, the cow (and other animals) "speaks" something.



When installing a package via npm install cowsay, the package itself and several of its dependencies will be installed:







The folder .binis hidden and contains symbolic links to the binary data cowsay:







How to execute them?



You can of course type ./node_modules/.bin/cowsayand it should work, but npx included with npm (since 5.2) is the best option. You just donpx cowsayand npx will locate the file automatically: The





cow says "take me out of here."



Package.json manual



When working with JavaScript, when interacting with a JavaScript project, Node.js, or the front-end of an application, you will likely come across a package.json.



What it is? What should you know about him? And what can you do with it?



package.jsonIs a kind of project manifesto. He can do many things that are completely unrelated to each other. For example, it can be the main file for the settings of the tools used. It also stores the names and versions of all installed packages (this information is used npmand yarn).



File structure


Here's an example package.json:



{}


As you can see, it is empty. There package.jsonare no requirements for the content . The only requirement is its format (JSON), otherwise programs will not be able to access it.



If you're creating a Node.js package that you plan to distribute through npm, the situation changes dramatically and you need to add properties to help other people use the package. We'll look at this later.



Here's another example package.json:



"name": "test-project"


Here we have defined the name of the package or application located in the same directory as package.json.



Here's an example of a more complex package.jsonone borrowed from a Vue.js application:



{
  "name": "test-project",
  "version": "1.0.0",
  "description": "A Vue.js project",
  "main": "src/main.js",
  "private": true,
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "unit": "jest --config test/unit/jest.conf.js --coverage",
    "test": "npm run unit",
    "lint": "eslint --ext .js,.vue src test/unit",
    "build": "node build/build.js"
  },
  "dependencies": {
    "vue": "^2.5.2"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.2",
    "babel-core": "^6.22.1",
    "babel-eslint": "^8.2.1",
    "babel-helper-vue-jsx-merge-props": "^2.0.3",
    "babel-jest": "^21.0.2",
    "babel-loader": "^7.1.1",
    "babel-plugin-dynamic-import-node": "^1.2.0",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "babel-preset-env": "^1.3.2",
    "babel-preset-stage-2": "^6.22.0",
    "chalk": "^2.0.1",
    "copy-webpack-plugin": "^4.0.1",
    "css-loader": "^0.28.0",
    "eslint": "^4.15.0",
    "eslint-config-airbnb-base": "^11.3.0",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-import-resolver-webpack": "^0.8.3",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-vue": "^4.0.0",
    "extract-text-webpack-plugin": "^3.0.0",
    "file-loader": "^1.1.4",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "html-webpack-plugin": "^2.30.1",
    "jest": "^22.0.4",
    "jest-serializer-vue": "^0.3.0",
    "node-notifier": "^5.1.2",
    "optimize-css-assets-webpack-plugin": "^3.2.0",
    "ora": "^1.2.0",
    "portfinder": "^1.0.13",
    "postcss-import": "^11.0.0",
    "postcss-loader": "^2.0.8",
    "postcss-url": "^7.2.1",
    "rimraf": "^2.6.0",
    "semver": "^5.3.0",
    "shelljs": "^0.7.6",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "url-loader": "^0.5.8",
    "vue-jest": "^1.0.2",
    "vue-loader": "^13.3.0",
    "vue-style-loader": "^3.0.1",
    "vue-template-compiler": "^2.5.2",
    "webpack": "^3.6.0",
    "webpack-bundle-analyzer": "^2.9.0",
    "webpack-dev-server": "^2.9.1",
    "webpack-merge": "^4.1.0"
  },
  "engines": {
    "node": ">= 6.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]
}


There's a lot here:



  • name - application / package name
  • version - application / package version
  • description - a short description of the application / package
  • main - main file (entry point) of the application
  • private- the value trueprevents accidental publication of the application tonpm
  • scripts - a set of scripts (commands) that can be run (executed)
  • dependencies - project dependencies
  • devDependencies - project dependencies used only during development
  • engines - versions the application / package is running on
  • browserlist - supported browsers (and their versions)


All of these properties are used npm.



Properties


In this section, we will talk about some of the properties you can use. We'll use the term "package", but most of what has been said is also true for applications.



Most of the properties are needed to publish the package to npm, some to interact with the package.



Name (name)


Specifies the name of the package.



For example:



"name": "test-project"


The name should not exceed 214 characters, should not contain spaces, and may only consist of lowercase letters (lowercase), hyphens (-), and underscore (_).



This is because a npmURL is assigned to the package when it is published based on its name.



If the package is published on GitHub, it is good practice to link to the repository.



Author


Identifies the author of the package.



For example:



{
    "author": "Joe <joe@whatever.com> (https://whatever.com)"
}


or like this:



{
  "author": {
    "name": "Joe",
    "email": "joe@whatever.com",
    "url": "https://whatever.com"
  }
}


Collaborators


Specifies one or more contributors to the package. This property is an array of strings.



For example:



{
  "contributors": ["Joe <joe@whatever.com> (https://whatever.com)"]
}


or like this:



{
  "contributors": [
    {
      "name": "Joe",
      "email": "joe@whatever.com",
      "url": "https://whatever.com"
    }
  ]
}


Mistakes


Defines a link to an issue tracker, usually an issue tracker on GitHub.



For example:



{
  "bugs": "https://github.com/whatever/package/issues"
}


Homepage


Defines the address of the home page.



For example:



{
  "homepage": "https://whatever.com/package"
}


Version


Determines the current version of the package.



For example:



"version": "1.0.0"


This property follows the semantic versioning standard. This means that it must always consist of three numbers separated by dots x.x.x.



The first number is the major version, the second is the minor version, the third is the patch.



Each number has a specific meaning: an update to fix bugs is a patch, a release of backward compatible changes is a minor release, and a major release may mean changes that are incompatible with the previous version.



License


Specifies the license for the package.



For example:



"license": "MIT"


Keywords


This property is an array of keywords associated with the package.



For example:



"keywords": [
  "email",
  "machine learning",
  "ai"
]


They help people find packages.



Description


Defines a short description for the package.



For example:



"description": "A package to work with strings"


When publishing a package to a npmgiven property, it helps people understand what it is for.



Repository


Determines where the source code for the package is located.



For example:



"repository": "github:whatever/testing",


Pay attention to the prefix github. There are other similar services:



"repository": "gitlab:whatever/testing",


"repository": "bitbucket:whatever/testing",


You can also define a version control system:



"repository": {
  "type": "git",
  "url": "https://github.com/whatever/testing.git"
}


You can specify multiple version control systems:



"repository": {
  "type": "svn",
  "url": "..."
}


main


Defines the main file (entry point) for the package.



When importing a package into an application, it is in this file that the application will look for exported modules.



For example:



"main": "src/main.js"


private


Setting this property to a value trueprevents the package from being accidentally published to npm.



For example:



"private": true 


scripts


Defines a list of commands (scripts) that can be executed (run).



For example:



"scripts": {
  "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
  "start": "npm run dev",
  "unit": "jest --config test/unit/jest.conf.js --coverage",
  "test": "npm run unit",
  "lint": "eslint --ext .js,.vue src test/unit",
  "build": "node build/build.js"
}


These scripts are command line applications. You can run them with npm run XXXXor yarn run XXXX, where XXXXis the command name. For example: npm run dev.



You can use any name as the command name, the script will do whatever you specify in it.



Dependencies


Defines a list of package dependencies.



When installing a package using npm or yarn:



npm install <PACKAGENAME>
yarn add <PACKAGENAME>


the record for this package will be automatically added to the property in question.



For example:



"dependencies": {
  "vue": "^2.5.2"
}


devDependencies


Defines a list of dependencies for development purposes.



They differ from dependencies, since they are installed only on the developer's computer and do not go into production.



When installing a package using npm or yarn:



npm install --save-dev <PACKAGENAME>
yarn add --save-dev <PACKAGENAME>


the record about it is automatically added to the considered property.



For example:



"devDependencies": {
  "autoprefixer": "^7.1.2",
  "babel-core": "^6.22.1"
}


engines


Determines which versions of Node.js or other tools the package / application is running on.



For example:



"engines": {
  "node": ">= 6.0.0",
  "npm": ">= 3.0.0",
  "yarn": "^0.13.0"
}  


browserlist


Defines a list of supported browsers (and their versions). This information is used by Babel, Autoprefixer and other tools to create polyfills and ensure compatibility with specified browsers.



For example:



"browserslist": [
  "> 1%",
  "last 2 versions",
  "not ie <= 8"
]    


This setting means that you want to support the two latest versions of all browsers that more than 1% of people use according to CanIUse statistics , with the exception of IE8 and older versions.



Special properties


package.jsoncan contain special properties for tools like Babel, ESLint, etc.



Each of these tools has its own properties, for example eslintConfig, babeland so on. For details on special properties, see the corresponding documentation.



Package versions


In the examples above, you've probably noticed entries like this: ~3.0.0, ^0.13.0. What do they mean? And what other version specifiers can I use?



These specifiers are used to define update conditions.



The rules are as follows:



  • ~- write ~0.13.0means that only patch updates are allowed, i.e. release is 0.13.1valid, but release is 0.14.0not
  • ^- write ^0.13.0means patch and minor updates are allowed
  • *- record *means that any updates are allowed
  • > - any new versions are allowed
  • >= - similar or newer versions are allowed
  • <= - similar or older versions are acceptable
  • < - any old versions are allowed


Here are a couple more rules:



  • no leading character - only the specified version is allowed
  • latest - only the latest version is allowed


These characters can be combined in various ways, for example: 1.0.0 || >=1.1.0 <1.2.0.



Thank you for attention.



To be continued…



All Articles