13 npm tricks to save time

Original author: Bret Cameron
  • Transfer
Every day, millions of developers, when creating their JavaScript applications, turn to npm (or to Yarn). Executing commands like npm initor npx create-react-appbecame the usual way to start working on almost any JavaScript project. It can be a server, client, or even a desktop application.

But the npm utility is not only capable of initializing projects or installing packages. The author of the material, the translation of which we publish today, wants to talk about 13 npm tricks that will allow you to squeeze out everything that is possible from this system. Here we will consider techniques of various sizes - from the use of shortcuts to customizing behavior npm init.



Many programmers use npm daily. This means that in the long run, even a small time saving can change something for the better. This material is primarily intended for beginner developers and mid-level developers. However, even if you are a professional, the author of the material hopes that you can find here a couple of interesting things that you have not encountered before.

If you are completely unfamiliar with npm - know that we are interested in is installed with Node.js . If you are working on Windows, it is recommended that you install Git Bash in order to reproduce some of what is being discussed here .

1. Brief options for recording basic commands


Let's start with the basics. If you spend a little time studying the shortened versions of the most common npm commands, you will save yourself a lot of time in the future.

  • Install packages. Normal version: npm install. Short version: npm i.
  • Running tests. Normal version: npm test. Short version: npm t.
  • Help call. Normal version: npm --help. Short version: npm -h.
  • Global setting flag. Normal version: --global. Short version: -g.
  • Package installation flag as a development dependency. Normal version: --save-dev. Short version: -D.
  • Accepts the npm initdefault settings. Normal option: npm init --yesor npm init --force. Shortcut: npm init -yor npm init -f.

Now, you do not need to use the --saveor flag to save packages -S. Packages are saved by default. And in order to install the package without saving it, you can use the flag --no-save.

▍Short recording options for less common commands


Here are a few more useful abbreviations, which, however, are not used as widely as those that we just reviewed.

  • Saving a package as an optional dependency. Normal version: --save-optional. Short version: -O.
  • Saving information about the exact version of the package. Normal version: --save-exact. Short version: -E.

Using the command npm installwith the key --save-bundle, or -B, leads to the fact that package.json, in the section bundledDependencies, entries about installed packages appear. These packages will be packaged with the project upon publication. To create a tarball file containing the project files and packages listed in bundledDependencies, you can use the command npm pack.

▍ Abbreviation for the root directory


Typically, the dot ( .) symbol is used to represent the root directory of the application, or (depending on the context) to represent the entry point to the application. In npm, this is what is set as the value of the property mainin the file package.json:

{
  "main": "index.js"
}

This shortcut can be used, for example, with commands like npx create-react-app. So, instead of running this command in the form npx create-react-app my-app(which will lead to the creation of a new folder my-app), you can run this command like this: npx create-react-app .(pay attention to the point that comes after the command). This will allow you to create a React application template project in the folder in which you are at the moment the command is run.

2. Setting default values ​​for npm init


By constantly running the command npm initto create a new project, you will most likely find that you are entering the same data again and again in response to system questions. For example - it is likely that you are the author of most of the projects you create. In order to save time on entering the same data, you can set your own default values ​​for the corresponding fields:

npm config set init.author.name  "Joe Bloggs"
npm config set init.author.email "joebloggs@gmail.com"
npm config set init.author.url   "joebloggs.com"
npm config set init.license      "MIT"

In order to verify the correctness of adding such information to the system, enter the command npm config edit. This will open the configuration file in the system editor. If you want to edit the global npm parameters, use the command npm config edit -g.

In order to return to the default settings, you can use the following script. Its first line deletes configuration data from the file, and the second one fills it with default values.

echo "" > $(npm config get userconfig)
npm config edit

The above script resets the default values ​​for the user. The following script resets global defaults:

echo "" > $(npm config get globalconfig)
npm config --global edit

3. Cross-platform scripts


Any code that is executed on the command line may encounter compatibility issues. This is especially true for incompatibilities between Windows-based and Unix-based systems (this includes Mac and Linux). This is not a problem if you and only you are working on a certain project. But in many cases, cross-platform scripting compatibility is important. For example, working independently of the operating system is a huge plus for any open source, training or demonstration project.

Fortunately, solving the script compatibility problem is not particularly difficult. We have several options at our disposal. However, here I would like to talk about one of them, about using which I got the best results. It's about the cross-env package. It needs to be set as a development dependency using the team npm i -D cross-env. Then you need to put cross-envin front of each environment variable. For example, it might look like this:

{
  "scripts": {
    "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}

I found that the package cross-envis the most convenient tool for achieving cross-platform scripting compatibility. But it will be useful for you to take a look at the following two popular tools that can help in solving this problem:

  • Rimraf package . It, for running cross-platform scripts, can be installed globally.
  • ShellJS package . This is a portable Node.js implementation of the Unix command shell.

4. Parallel script execution


In order to organize the sequential execution of commands in the Linux shell, a construct is used &&. What about running parallel scripts? To achieve this, you can choose the appropriate npm package. The most popular packages of this kind are concurrently and npm-run-all . Here we demonstrate the use of the concurrently package.

To start the selected package must be installed as a dependency of development: npm i -D concurrently. Then package.jsonyou can use the following construction:

{
  "start": "concurrently \"command1 arg\" \"command2 arg\""
}

5. Running scripts located in various directories


Sometimes you have to deal with applications that have several files package.jsonlocated in different directories. It would be convenient, for example, to run scripts declared in them, being in the root directory of the project. This is much better than having to travel to different folders whenever you need to run a script. In order to do this, you can use the following two approaches.

To get started, you can use the command cdto organize the automatic transition to the desired directory. It may look something like this:

cd folder && npm start && cd ..

But this problem can be solved in a more interesting way. It consists in using a flag --prefixwith which you can specify the path:

npm start --prefix path/to/your/folder

The following is an example of applying this solution from a real application. Here we need to perform npm startfor the client and server parts of the project. Their code, respectively, is in the folders clientand server.

"start": "concurrently \"(npm start --prefix client)\" \"(npm start --prefix server)\"",

6. Delaying the launch of the script until a resource is available


When developing full-stack applications, the need often arises to run both the client and server parts of the application. The wait-on package allows you to synchronize the execution of certain processes. In our case, it is necessary that before starting the client part of the application, a certain port should be available.

For example, there is a dev script that is used in an Electron application whose interface is written using React. The script, using concurrently, in parallel launches the presentation layer of the application and the Electron window. But using wait-onit is possible to make the Electron window open only when the React presentation layer is ready for use and accessible at the address http://localhost:3000. Here's what the usage looks like wait-on:

"dev": "concurrently \"cross-env BROWSER=none npm run start\" \"wait-on http://localhost:3000 && electron .\"",

In addition, the standard behavior of React projects is to automatically open a browser window. If using React with Electron, this is not necessary. This can be disabled using an environment variable BROWSER=none, before which, for the sake of cross-platform compatibility of the solution, there is a command cross-env.

7. Listing and working with available scripts


In order to list the scripts available in package.json, just go to the root directory of the project and execute the command in the terminal npm run.

But there is an even more convenient way to list scripts. When using it, the desired script can be immediately selected from the list and run. In order to use this method of working with scripts, we need to globally install the module ntl(Npm Task List):

npm i -g ntl

Then in the project folder you need to run the command ntl. It will display a list of available scripts and give you the opportunity to select the script that you want to run. Here is how it looks.


Using the ntl command

This feature can be very useful if you do not know exactly what scripts are in the project. It is also good in cases where the programmer wants to replace the input of a long command to run a script with the input of a short command and the quick pressing of a few more keys on the keyboard.

8. Running pre-scripts and post-scripts


You may be familiar with scripts prebuildand postbuildthat allow you to run some code before and after running the script build. Such pre- and post-scripts can be defined for any other script. Including those whose descriptions are added to p ackage.jsonby the programmer himself.

This not only allows you to make the code cleaner, but also helps to run pre- and post-scripts in isolation.

9. Application version control


Instead of manually changing the version of the application, the programmer can use special commands npm. In order to increase the corresponding part of the application version number, you can use the command npm versionfollowed by major, minoror patch:

// 1.0.0
npm version patch
// 1.0.1
npm version minor
// 1.1.0
npm version major
// 2.0.0

Depending on how often you update your application, you can save time by automatically increasing the version number each time you deploy a new version of the application. For example, like this:

{
  "predeploy": "npm version patch"
}

10. Editing package.json from the command line


The package.json file is a regular json file, so it can be edited directly from the command line using the json utility . This opens up new possibilities in those situations where you need to change package.json, allowing you to create your own abbreviated versions of commands. Install the package jsonglobally:

npm install -g json

Then the utility jsoncan be used to quickly edit the file using the key -I. For example, in order to add a new script foowith a value to a file bar, you can use the following command:

json -I -f package.json -e 'this.scripts.foo="bar"'

In the next section, you will see a more practical example of using the utility json.

11. Automation of setup and repository opening


If package.jsonthere is an entry in your file , "repository"this means that you can open the repository page in the browser used by default in the system. To do this, use the command npm repo.

If your project is already connected to the remote repository and you have the command line utility installed git, this means that you can find out the address of your repository using the following command:

git config --get remote.origin.url

But that is not all. If, in accordance with the previous tip, you installed the utility json, then you can use the following script to automatically add the correct information about the repository to package.json:

json -I -f package.json -e "this.repository=\"$(git config --get remote.origin.url)\""

12. Creating your own script to control the npm init command


Now let's talk about solving a larger task. Namely, we are going to develop our own script that controls the work of the team npm init, which accepts the URL of the GitHub repository and automatically sends the first commit to it. Here we talk about how to create such scripts. And in the next section, which will present our last tip, we will talk about working with git.

You npm initcan customize the command behavior using a file .npm-init.js. Create such a file in the home directory of the current user (on Windows this is usual , but on Mac - ). After that, execute the following command that tells npm where exactly this file is located:C:/Users//Users/

npm config set init-module ~\.npm-init.js

Before we deal with c integration git, let's look at a simple example of a file .npm-init.jsthat reproduces the questions that the system asks the user when using the command npm initwithout additional settings:

module.exports = {
  name: prompt('package name', basename || package.name),
  version: prompt('version', '0.0.0'),
  decription: prompt('description', ''),  
  main: prompt('entry point', 'index.js'),
  repository: prompt('git repository', ''),
  keywords: prompt(function (s) { return s.split(/\s+/) }),
  author: prompt('author', 'Joe Bloggs  (joebloggs.com)'),
  license: prompt('license', 'ISC')
}

Each question is based on the following template:

nameInPackage: prompt('nameInPrompt', 'defaultValue')

In order to indicate a certain value and not ask the user a question, simply remove the method prompt.

If you want to return to the default settings npm init, simply delete the file .npm-init.js.

13. Sending the first commit to the GitHub repository using npm init


In order to execute commands gitin a file, .npm-init.jswe need to find a way to work with the command line. You can use the module for this child_process. We connect it at the top of the file, and since we only need a function execSync, we import only it using the destructuring:

const { execSync } = require('child_process');

In addition, we will create a helper function that displays the results of our function in the console:

function run(func) {
  console.log(execSync(func).toString())
}

And finally, let's create the appropriate prompt block to handle the URL of the GitHub repository. If the URL is at the disposal of the script, we will create a file README.mdand send the first commit to the repository.

So, one of the elements of the module.exportsfile object .npm-init.jsshould be the following code:

repository: prompt('github repository url', '', function (url) {
  if (url) {
    run('touch README.md');
    run('git init');
    run('git add README.md');
    run('git commit -m "first commit"');
    run(`git remote add origin ${url}`);
    run('git push -u origin master');
  return url;
})

Here is how the full code of the file should look after this addition .npm-init.js:

const { execSync } = require('child_process');
function run(func) {
  console.log(execSync(func).toString())
}
module.exports = {
  name: prompt('package name', basename || package.name),
  version: prompt('version', '0.0.0'),
  decription: prompt('description', ''),
  main: prompt('entry point', 'index.js'),
  keywords: prompt(function (s) { return s.split(/\s+/) }),
  author: prompt('author', 'Joe Bloggs  (joebloggs.com)'),
  license: prompt('license', 'ISC'),
  repository: prompt('github repository url', '', function (url) {
    if (url) {
      run('touch README.md');
      run('git init');
      run('git add README.md');
      run('git commit -m "first commit"');
      run(`git remote add origin ${url}`);
      run('git push -u origin master');
    return url;
  }),
}

Here's what the file the package.jsonsystem creates using this looks like .npm-init.js:

{
  "name": "Custom npm init",
  "version": "0.0.0",
  "decription": "A test project, to demonstrate a custom npm init script.",
  "main": "index.js",
  "keywords": [],
  "author": "Joe Bloggs  (joebloggs.com)",
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/JoeBloggs/custom.git"
  },
  "bugs": {
    "url": "https://github.com/JoeBloggs/custom/issues"
  },
  "homepage": "https://github.com/JoeBloggs/custom#readme"
}

By setting up the process of initializing new projects, you can go further. For example, to make sure that when creating a project, a new repository for it would be created.

Summary


I hope this material has helped you see what you can achieve with npm. I would like to believe that you have found something here that will allow you to work more productively - whether we are talking about using shortened versions of commands, about scripts from package.json, or about customizing npm initaccording to your needs.

Dear readers! Do you automate work with npm?


Also popular now: