Npm run dev windows

Last Updated :
13 Aug, 2024

When working with Node.js and JavaScript projects, especially those involving frontend frameworks like React, Vue, or Next.js, you often encounter the command npm run dev. This command is pivotal for developers as it initiates the development server, enabling live reloading, hot module replacement, and other essential features for efficient development. In this article, we will see what npm run dev does, how it works, and why it is crucial for your development workflow.

Table of Content

  • What is npm run dev ?
  • package.json File
  • Setting up npm run dev
  • Running npm run dev
  • Why npm run dev ?
  • Conclusion

What is npm run dev ?

npm run dev is a script defined in the package.json file of a project. It is typically used to start a development server that watches for file changes and automatically reloads the application. This provides a seamless and efficient development experience.

package.json File

The package.json file is a crucial component of any Node.js project. It contains metadata about the project, including its dependencies, scripts, version, author, and more. The scripts section of this file defines various commands that can be run using npm run <script-name>.

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "A sample project",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "next dev",
    "build": "next build",
    "test": "jest"
  },
  "author": "Your Name",
  "license": "MIT",
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
  "devDependencies": {
    "jest": "latest"
  }
}

Note: In the above syntax example, the scripts section defines several commands. The dev script runs next dev, which starts the Next.js development server.

Setting up npm run dev

To set up ‘npm run dev‘ in your project follow these steps as:

  • Initialize Your Project: Create a new Node.js project by running ‘npm init’ command to genertate ‘package.json’ file.
npm init -y
  • Install Dependencies: Depending on your needs install required dependencies. For example, if you’re using Webpack, you would install it along with Webpack Dev Server or you can install express also..
npm install webpack webpack-cli webpack-dev-server --save-dev
  • Define the Script: Add ‘dev’ script to ‘scripts’ section of your ‘package.json’ file.
"scripts": {
    "dev": "webpack serve --mode development"
}
  • Run the Script: Run script using «npm run dev»
npm run dev

Running npm run dev

To run npm run dev, open your terminal, navigate to the project directory, and execute the command. The below is the example for nextJS app.

npm run dev
Screenshot-2024-05-22-114051

Why npm run dev ?

  • Automates Workflow: It can run multiple tasks such as compiling SCSS to CSS, transpiling ES6 to ES5, and bundling JavaScript files automatically.
  • Live Reloading: The npm run dev script starts a development server that watches for changes in the codebase. When a change is detected, the server reloads the application automatically, saving developers time from manual refreshes.
  • Improved Productivity: By automating setup and development tasks, developers can focus more on writing code rather than managing the environment.

Conclusion

npm run dev is an essential command in the workflow of modern JavaScript and Node.js development. It starts the development server, enabling features like live-reloading and hot module replacement, which significantly enhance the development experience. By understanding how to utilize and customize this command, developers can create a more efficient and streamlined development process.

Utilizing the ‘npm run dev’ command is essential for setting up and running development environments effectively at IOFLOOD. As we utilize various in-house bare metal cloud servers for development, we’ve found that using ‘npm run dev’ is crucial for automating tasks related to startup, code compiling, and live reloading. To assist our customers and other developers with similar questions, we’ve formulated today’s article, complete with examples and tips.

This guide will walk you through using ‘npm run dev’ effectively, enhancing your development workflow in Node.js projects. By mastering this command, you’ll unlock a more efficient and streamlined development experience, allowing you to focus on crafting your application’s logic rather than wrestling with setup and configuration.

Let’s explore how ‘npm run dev’ simplifies the setup and management of development environments, allowing you to focus on building and testing your software projects

TL;DR: What Does ‘npm run dev’ Do?

npm run dev executes the dev script defined in your project’s package.json file, typically starting a development server with live reloading. This command is a cornerstone for Node.js developers, streamlining the process of testing and debugging applications in real-time.

Here’s a basic example:

"scripts": {
  "dev": "node server.js"
}

# Output:
# Server running at http://localhost:3000

In this example, when you run npm run dev in your terminal, it executes the dev script specified in your project’s package.json file. This script starts a Node.js server using node server.js. It’s a straightforward way to kickstart your development environment without manually starting your server each time.

Dive deeper into this guide for more insights on setting up and leveraging ‘npm run dev’ for your projects, including advanced configurations and troubleshooting tips.

Table of Contents

  • Script Setup: ‘npm run dev’
  • Automation Tips for ‘npm run dev’
  • Exploring Beyond ‘npm run dev’
  • Overcoming ‘npm run dev’ Hurdles
  • Npm and package.json Essentials
  • ‘npm run dev’ in Complex Projects
  • Wrapping Up: Mastering ‘npm run dev’

Script Setup: ‘npm run dev’

Understanding npm Scripts

In the heart of every Node.js project lies a package.json file, a manifest that holds various metadata relevant to the project. Among its many uses, it defines scripts that can automate tasks, such as starting a development server. For beginners, setting up a ‘dev’ script is your first step towards automating your development workflow.

To define a ‘dev’ script in your package.json, you simply add an entry under the scripts section. This script usually starts your project’s development server. Here’s how you can set it up:

"scripts": {
  "dev": "node app.js"
}

In this example, running npm run dev in your terminal will execute the node app.js command, starting your Node.js application. Here’s what you might see as output:

# Output:
# Listening on http://localhost:3000

This output indicates that your server is up and running, and you can now view your application by navigating to http://localhost:3000 in your browser. The beauty of using npm run dev lies in its simplicity. With just a single command, you’ve started your development server, bypassing the need to manually execute node app.js every time you want to run your application.

Pros and Cons for Beginners

Pros:
Easy Setup: Just a few lines in package.json and you’re ready to go.
Quick Start: Jump straight into development without fiddling with commands.

Cons:
Limited Customization: At this level, there’s minimal room for tweaking how your development environment behaves. For more advanced features like live reloading, you’ll need to explore further.

Mastering the npm run dev command is a significant first step in optimizing your development process. It not only saves time but also introduces you to the world of npm scripts, an essential tool for any Node.js developer.

Automation Tips for ‘npm run dev’

Automatic Server Restarts

After mastering the basic use of npm run dev, it’s time to enhance your development workflow. A common pain point in development is having to manually restart your server after making changes to your code. This is where Nodemon comes into play. Nodemon is a utility that monitors for any changes in your source and automatically restarts your server, saving you a significant amount of time and effort.

To integrate Nodemon into your workflow, you first need to install it as a development dependency:

npm install --save-dev nodemon

Next, update your ‘dev’ script in package.json to use Nodemon instead of node:

"scripts": {
  "dev": "nodemon app.js"
}

Running npm run dev now utilizes Nodemon. Here’s what you might encounter as output when making a change:

# Output:
# [nodemon] starting `node app.js`
# [nodemon] restarting due to changes...
# [nodemon] starting `node app.js`

This output indicates that Nodemon is actively monitoring your project. Upon detecting a file change, it automatically restarts your server, ensuring that your latest changes are always in effect without the need for manual intervention.

Environment Variables Made Easy

Another aspect of advancing your ‘npm run dev’ setup involves the use of environment variables for configuring your development environment. Environment variables allow you to manage application settings outside of your code, such as database connection strings or API keys, enhancing security and flexibility.

To set up environment variables, you can use a package like dotenv:

npm install dotenv

Then, create a .env file in your project root and define your variables:

PORT=3000
DB_STRING=mongodb://localhost/devdb

In your application, you can access these variables using process.env:

require('dotenv').config();
console.log(process.env.PORT); // Output: 3000

Pros and Cons

Pros:
Increased Efficiency: Automatic restarts with Nodemon save time.
Convenience: Environment variables streamline configuration management.

Cons:
Additional Setup: Integrating Nodemon and environment variables requires initial setup effort.

By incorporating these advanced techniques into your ‘npm run dev’ command, you not only improve your development efficiency but also take a significant step towards a more professional and scalable Node.js project setup.

Exploring Beyond ‘npm run dev’

Embrace Docker for Consistent Environments

As your projects grow in complexity, you might seek more robust solutions to manage your development environments. Docker emerges as a powerful ally, enabling you to containerize your applications and their dependencies. This ensures that your application runs consistently across all environments.

To leverage Docker in your workflow, start by creating a Dockerfile in your project root:

FROM node:14
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "run", "dev"]

This Dockerfile sets up a Node.js environment, copies your project files, installs dependencies, and specifies npm run dev as the default command. To build and run your Docker container, execute:

docker build -t my-node-app .
docker run -p 3000:3000 my-node-app

# Output:
# > node app.js
# Listening on http://localhost:3000

This setup encapsulates your development environment within a Docker container, ensuring that it remains consistent regardless of where it’s deployed. It’s an excellent step towards achieving development-production parity.

Integrate Task Runners for Automation

Task runners like Gulp or Webpack can further automate and enhance your development process. These tools can compile your code, minify assets, and even refresh your browser automatically upon file changes, integrating seamlessly with npm run dev.

For example, integrating Webpack might involve adding a new script in your package.json:

"scripts": {
  "dev": "webpack serve --mode development"
}

This command uses Webpack to bundle your application and serve it in development mode, offering features like hot module replacement.

Pros and Cons of Alternative Approaches

Pros:
Consistency: Docker ensures your environment is the same everywhere.
Automation: Task runners like Gulp and Webpack streamline repetitive tasks.

Cons:
Complexity: Setting up Docker and integrating task runners can introduce additional complexity.
Learning Curve: There’s a learning curve involved in mastering these tools.

By exploring these alternative approaches, you can tailor your development environment to your project’s specific needs, ensuring efficiency and consistency across all stages of development.

Overcoming ‘npm run dev’ Hurdles

Tackling ‘Script Not Found’

One of the most common issues developers encounter with ‘npm run dev’ is the dreaded ‘script not found’ error. This typically occurs when the ‘dev’ script is missing or incorrectly defined in your package.json. To resolve this, ensure your ‘dev’ script is properly set up:

"scripts": {
  "dev": "nodemon app.js"
}

After adding or correcting the ‘dev’ script, running npm run dev should successfully start your development server. If the problem persists, double-check for typos or syntax errors in your package.json.

Resolving Environment Variable Issues

Environment variables are crucial for configuring your application without hard-coding sensitive information. If npm run dev isn’t recognizing your environment variables, ensure you’ve loaded them correctly using dotenv or a similar package:

require('dotenv').config();
console.log(process.env.MY_VARIABLE); // Replace MY_VARIABLE with your actual variable name

# Output:
# Your variable value

This code block demonstrates how to load and access environment variables. If you don’t see the expected output, verify that your .env file is in the root directory of your project and that it’s correctly formatted.

Avoiding Port Conflicts

Port conflicts occur when another process is using the port your application is trying to bind to. This is common when running multiple projects simultaneously. To avoid this, you can configure your application to use a different port if the default one is unavailable:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3001; // Fallback to 3001 if process.env.PORT is unavailable

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

# Output:
# Server running on http://localhost:3001

In this example, we use a fallback port (3001) if the preferred port is not available. This simple strategy can help mitigate port conflicts, ensuring your development server runs smoothly.

Best Practices and Optimization

  • Keep your package.json clean and organized: Regularly review your scripts and dependencies to avoid errors.
  • Use environment variables wisely: Store sensitive information in environment variables and keep your .env file out of version control.
  • Handle port conflicts gracefully: Implement fallback strategies to ensure your application always has a port to run on.

By addressing these common issues and adhering to best practices, you can optimize your development process and minimize disruptions when using ‘npm run dev’.

Npm and package.json Essentials

The Heart of Node.js Projects

Understanding npm (Node Package Manager) is crucial for every Node.js developer. It’s not just a tool for installing packages; it’s the backbone of managing project dependencies, scripts, and more. The package.json file, often considered the heart of a Node.js project, plays a pivotal role in this ecosystem.

At its core, package.json serves multiple purposes:

  • Dependency Management: It lists all the project dependencies, ensuring consistency across environments.
  • Script Automation: It allows the definition of scripts for common tasks, such as starting the development server.

Here’s a minimal package.json example:

{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

In this example, npm start would execute node app.js, starting the application. The dependencies section ensures that anyone working on the project uses the same version of Express.

Scripts: Beyond ‘npm run dev’

The scripts section of package.json is where npm run dev comes into play. It’s a custom script, typically used to start a development server with features like hot reloading or debugging tools enabled. This is different from the start script, which is often used in production environments.

"scripts": {
  "dev": "nodemon app.js",
  "start": "node app.js"
}

This setup illustrates the distinction between development (dev) and production (start) environments. Using nodemon for the dev script automates the process of restarting the server upon file changes, enhancing development efficiency.

Development vs. Production Environments

The difference between development and production environments is crucial. Development environments are configured for ease of use and debugging, often with additional tools like live reloading. Production environments, on the other hand, are optimized for performance and stability.

Understanding and utilizing the appropriate scripts and configurations for each environment is essential for a smooth workflow. This ensures that developers can work efficiently in the development phase, while the application runs optimally in production.

By grasping these fundamentals, developers can leverage npm and package.json to streamline their development process, making npm run dev a powerful command in their development arsenal.

‘npm run dev’ in Complex Projects

Integrating Front-End Build Tools

As projects grow in complexity, integrating front-end build tools like Webpack or Parcel with npm run dev becomes essential. These tools offer a plethora of features such as module bundling, asset optimization, and hot module replacement, significantly enhancing the development experience.

Consider a scenario where you integrate Webpack with your npm run dev setup. Your package.json might include a script like this:

"scripts": {
  "dev": "webpack-dev-server --mode development"
}

This command starts the Webpack development server in development mode, providing features like live reloading and hot module replacement out of the box. Here’s a simplified output you might see:

# Output:
# Project is running at http://localhost:8080/
# webpack output is served from /dist/

This setup not only streamlines your development process but also ensures that your front-end assets are efficiently managed and served.

Related Commands and Functions

Besides npm run dev, several related commands and functions can enhance your workflow. For instance, npm run build is commonly used in conjunction with npm run dev for preparing the application for production by compiling and minifying assets.

"scripts": {
  "build": "webpack --mode production"
}

Executing npm run build compiles your application with Webpack in production mode, optimizing your assets for performance. This command is crucial for preparing your application for deployment.

Further Resources for ‘npm run dev’ Mastery

To deepen your understanding and mastery of npm run dev and its ecosystem, here are three invaluable resources:

  • Visit Node.js Documentation to explore the fundamentals and advanced topics in Node.js.
  • Explore Webpack Concepts for a comprehensive understanding of Webpack and how it can be integrated with Node.js projects.

  • Learn about Parcel, a fast, zero-configuration web application bundler, and how to use it in your Node.js projects.

These resources provide a wealth of information that can help you leverage npm run dev more effectively in your projects, ensuring a robust and efficient development workflow.

Wrapping Up: Mastering ‘npm run dev’

In this comprehensive guide, we’ve explored the vital command ‘npm run dev’, a cornerstone in the development of Node.js projects. This command initiates your development environment, setting the stage for efficient and streamlined workflow.

We began with the basics, understanding the role of package.json and how to set up a simple ‘dev’ script to start our Node.js server. This foundational knowledge is crucial for anyone stepping into the world of Node.js development.

Moving forward, we delved into more advanced usage, integrating tools like Nodemon for automatic server restarts and employing environment variables for more dynamic configurations. These intermediate steps not only make the development process more efficient but also introduce best practices for managing application settings.

Exploring alternative approaches, we discussed the integration of Docker and the use of task runners like Gulp and Webpack. These expert-level configurations offer a glimpse into the possibilities for scaling and optimizing Node.js projects, ensuring consistency across environments and automating repetitive tasks.

Approach Efficiency Complexity
Basic ‘npm run dev’ High Low
Nodemon Integration Higher Moderate
Docker & Task Runners Highest High

Whether you’re just starting out with ‘npm run dev’ or looking to enhance your current setup, we hope this guide has provided you with valuable insights and practical knowledge. The command ‘npm run dev’ is more than just a way to start your development server; it’s a gateway to optimizing your development workflow and embracing the full potential of Node.js.

With the right setup and understanding, ‘npm run dev’ can significantly reduce development time and increase productivity. Embrace these techniques, and you’ll find yourself navigating the Node.js ecosystem with greater ease and confidence. Happy coding!

When working with JavaScript projects, especially those involving frameworks like React, Vue, or Node.js, the command npm run dev is often your go-to for starting the project in development mode. This command enables developers to see their changes in real time, making the development process faster and more efficient. Let’s dive into what npm run dev does, how to set it up, and why it’s essential for modern development workflows.

What is npm run dev?

At its core, npm run dev is an npm (Node Package Manager) command that runs the development script specified in the package.json file of a project. This command kicks off a series of processes optimized for development, including auto-reloading the project on code changes, handling errors in real-time, and often setting up development-only configurations like local servers and testing utilities.

In most cases, running npm run dev will:

  1. Start a development server for frontend projects, allowing you to preview the project in a browser.
  2. Enable hot-reloading so that any changes to the code are immediately reflected without a full page reload.
  3. Provide detailed error reporting, helping developers identify and fix issues quickly.

Setting Up npm run dev

The command itself is quite simple to execute. Here’s how to set up and run npm run dev in your project.

  1. Install Node.js and npm: First, make sure Node.js and npm are installed. You can download them from Node.js’ official website.
  2. Initialize Your Project: If you’re starting from scratch, initialize a new project using:npm init -y
  3. Define a Development Script: Open your package.json file and locate the scripts section. Here, you’ll see predefined scripts like test and possibly start. Add a new script for development:”scripts”: { “dev”: “node yourDevScript.js” }
  4. Run the Command: Simply open your terminal, navigate to your project directory, and run:npm run dev

This command will execute the script defined in the dev field of package.json.

Common Scenarios with npm run dev

In many projects, especially those involving frontend frameworks like Vue, React, or Svelte, the command npm run dev does more than simply start a server. Here’s what npm run dev typically handles in various frameworks:

  • React (using Vite or Create React App): Starts a local development server with hot module replacement, allowing for immediate reflection of code changes in the browser.
  • Vue.js: Starts a development server using tools like Vite or Vue CLI, which auto-updates the browser when you save changes.
  • Next.js: Starts a Node.js server in development mode, giving developers access to features like API routes, SSR (Server Side Rendering), and hot reloading.
  • Express (Node.js backend): Initializes the server with tools like nodemon, which restarts the server on each file save.

Why npm run dev is Essential for Development

Running a project in development mode is all about efficiency, speed, and reliability during the coding process. Here are the key reasons why npm run dev is crucial:

  1. Immediate Feedback: Hot reloading means you see changes as you make them, which is invaluable for frontend development.
  2. Debugging and Error Handling: Development servers provide detailed error logs, making it easier to identify and fix issues on the fly.
  3. Environment-Specific Configurations: The development environment often includes configurations and tools (like debugging libraries) that aren’t used in production. This keeps development and production environments distinct, reducing the risk of deployment issues.
  4. Increased Productivity: By eliminating the need to manually refresh or restart servers, npm run dev lets developers focus on coding, testing, and refining.

Common Errors and Troubleshooting Tips for npm run dev

While npm run dev is straightforward, you may encounter errors, especially when dependencies are misconfigured or missing. Here are some common errors and solutions:

  • Error: dev script not found
    This error indicates that the dev script is missing from package.json. Check the scripts section in your package.json and ensure you have something like “dev”: “yourDevCommand” defined.
  • Module Not Found
    If you encounter a “Module not found” error, a dependency may be missing. Run npm install to ensure all required packages are installed.
  • Permission Denied
    If you get a “permission denied” error, it could be due to file permission settings. Try running the command with sudo (on Unix-based systems) or adjust the file permissions.
  • Port Already in Use
    Sometimes, the port required by the dev server is already in use. Specify a different port in your package.json script, such as:”scripts”: { “dev”: “PORT=3001 node yourDevScript.js” }

Going Beyond: Customizing Your Dev Setup

One of the best aspects of npm run dev is its flexibility. You can customize your development script to include other tools and configurations. For example:

  • Using Nodemon for Node.js Apps: Nodemon automatically restarts your server when changes are detected, making it ideal for backend development.”scripts”: { “dev”: “nodemon app.js” }
  • Setting Environment Variables: If you need specific environment variables, set them directly in the script.”scripts”: { “dev”: “NODE_ENV=development node app.js” }

Final Thoughts

The npm run dev command is more than a way to start your app; it’s a productivity booster, an error-catcher, and a vital tool for every developer’s workflow. By taking advantage of npm run dev and customizing it to suit your project’s needs, you can streamline the development process and focus on what matters most — building great applications.

If you’re looking to set up an efficient, scalable development environment, or need assistance with your JavaScript projects, expert help is invaluable. Companies like Itexus specialize in building innovative, customer-centered solutions for businesses in dynamic sectors. With our tailored development and strategic consulting, we can help organizations turn these solutions into scalable, profitable actions, enhancing both their service and reputation.

Ready to optimize your development environment? Reach out to Itexus to unlock your project’s full potential!

Ian Macartney's avatar

improved npm run dev

npm run dev is the standard for «run my website locally,» but how does it work? How can we expand its functionality? In this post we’ll look at:

  • How to configure what npm run dev does.
  • How to decompose complex commands into granular units.
  • How to run multiple commands in parallel.
  • How to run pre-requisites without losing normal Ctrl-C behavior.
  • How to add seed data (if none exists) when starting up a Convex backend.

As a motivating example, here are some npm run scripts defined in the convex-helpers example app. We’ll cover what each piece does

What does npm run dev do?

npm run dev sets up a local development server, enabling real-time code changes and instant feedback. This command simplifies the development process by automatically reloading the application whenever you make changes to the code.

How and where they’re defined

npm run executes commands that are defined in your package.json in your project’s workspace. These commands are often pre-configured when you start your repo from a command like npm create vite@latest with commands for:

  • dev: Run a development environment. This often includes auto-reloading the UI when files change. For Vite this is vite and Next.js is next dev.
  • build: Build the website for deployment. This will generally compile and bundle all your html, css, and javascript. For Vite this is vite build and Next.js is next build.
  • test: Run tests — if you’re using Jest, it’s just "test": "jest" or vitest for Vitest.

Here’s a basic example from Next.js:

Here you can run npm run dev or npm run lint etc.

You can learn more about npm run in the docs.

Why use package.json scripts?

It’s a fair question why one would put commands that are already so simple into package json scripts. Why not just call jest or vite or next build? There’s a few good reasons:

  1. You can save the default parameters for npm run commands so you don’t have to remember or document the «standard» way of starting something. We’ll see below how you can configure it to chain commands and run others in parallel.
  2. It allows you to easily run commands that are installed by npm but not globally accessible from your shell (terminal).1 When you install things like npm install -D vitest, it installs vitest into node_modules/.bin.2 You can’t run vitest directly in your shell,3 but you can have a config like: "scripts": { "test": "vitest" } and npm run test will run vitest.
  3. It always runs with the root of the package folder as the «current directory» even if you’re in a subdirectory. So you can define a script like "foo": "./myscript.sh" and it will always look for myscript.sh in the package root (in the same directory as package.json). Note: you can access the current directory where it was called via the INIT_CWD environment variable.
  4. You can reference variables in the package.json easily when the script is run from npm run. For instance, you can access the «version» of your package with the npm_package_version environment variable, like process.env.npm_package_version in js or $npm_package_version in a script.
  5. If you have multiple workspaces (many directories with their own package.json configured into a parent package.json with a «workspaces» config), you can run the same command in all workspaces with npm test --workspaces or one with npm run lint --workspace apps/web.

Does npm run dev work with yarn / pnpm / bun?

Yes! Even if you install your dependencies with another package manager, you can still run your package scripts with npm.

You don’t have to remember that npm run dev maps to yarn dev (or yarn run dev). The same goes for npx: npx convex dev works regardless of what package manager you used to install things.

Running multiple commands in parallel with npm run all or concurrently

There are a couple packages you can use to execute npm commands concurrently:4

  1. npm-run-all
  2. concurrently

Here’s an example of npm-run-all:

This defines three npm run scripts.

  1. npm run dev:backend runs convex dev.
  2. npm run dev:frontend runs vite.
  3. npm run dev runs both convex dev and vite in parallel via npm-run-all.

Both outputs are streamed out, and doing Ctrl-C will interrupt both scripts. With npm run all, you can easily run both the Convex backend and frontend services with one command.

Here’s an example of using concurrently to run the same project:

This set of package json scripts run multiple npm run commands in parallel similar to npm run all but uses the concurrently package which provides additional features like better handling of command outputs and more control over execution control.

Enhancing npm run dev with predev and postbuild

You can specify commands to run before (pre) or after (post) another command (say, X) by naming your command preX or postX. In the example:

This will run convex dev --until-success, before the «dev» command of npm-run-all --parallel dev:backend dev:frontend.

Chaining with «&&»

For those used to shell scripting, you can run two commands in sequence if the previous one succeeds with commandA && commandB. This works on both Windows and Unix (Mac / Linux).

However, there’s a couple advantages to just using pre-scripts:

  1. You can run either command with npm run dev --ignore-scripts to not do the «predev» script, or npm run predev to explicitly only do the «predev» step.
  2. The Ctrl-C behavior is more predictable in my experience. In different shell environments, doing Ctrl-C (which sends an interrupt signal to the current process) would sometimes kill the first script but still run the second script. After many attempts we decided to switch to «predev» as the pattern.

Run interactive steps first

The first time you run Convex by using npx convex dev (or npm run dev with the above scripts), it will ask you to log in if you aren’t already, and ask you to set up your project if one isn’t already set up. This is great, but interactive commands that update the output text don’t work well when the output is being streamed by multiple commands at once. This is the motivation for running npx convex dev --until-success before npx convex dev.

  • convex dev syncs your functions and schema whenever it doesn’t match what you have deployed, watching for file changes.
  • The --until-success flag syncs your functions and schema only until it succeeds once, telling you what to fix if something is wrong and retrying automatically until it succeeds or you Ctrl-C it.
  • By running npx convex dev --until-success, we can go through the login, project configuration, and an initial sync, all before trying to start up the frontend and backend.
  • The initial sync is especially helpful if it catches issues like missing environment variables which need to be set before your app can function.
  • This way the frontend doesn’t start until the backend is ready to handle requests with the version of functions it expects.

Seeding data on startup

If you change your «predev» command for Convex to include --run it will run a server-side function before your frontend has started.

The --run init command will run a function that is the default export in convex/init.ts. You could also run --run myFolder/myModule:myFunction. See docs on naming here.

See the Convex documentation on query names. See this post on seeding data for more details. In essence, you can define an internalMutation that checks if the database is empty and, if so, inserts a collection of records for testing or setup purposes.

tsc?

If you use TypeScript, you can run a type check / compile your typescript files with a bare tsc. If your tsconfig.json is configured to emit types, it will write out the types. If not, it will just validate the types. This is great to do as part of the build, so you don’t build anything that has type errors. This is why the above example did:

Passing arguments to npm run commands

If you want to pass arguments to a command, for instance passing arguments to your testing command to specify what test to run, you can pass them after a -- to separate the command from the argument. Technically you don’t need -- if your arguments are positional instead of --prefixed, but it doesn’t hurt to always do it in case you forget which to do it for.

Handling common npm script errors

When working with npm run commands, you might encounter various errors. Here are some common issues and how to handle them:

  • Command Not Found: Ensure the command is installed locally in your node_modules and correctly referenced in your package.json scripts.
  • Permission Denied: This often occurs on Unix-based systems. You might need to adjust file permissions or use sudo cautiously.
  • Syntax Errors: Double-check your package.json for any syntax errors, such as missing commas or incorrect script names.

Integrating npm run scripts with CI/CD pipelines

Integrating npm run scripts with CI/CD pipelines can automate your development workflow, ensuring consistent builds and deployments. Most CI/CD tools like GitHub Actions, GitLab CI, and Jenkins support running npm scripts as part of their pipeline configuration.

For example, in a GitHub Actions workflow:

This yaml file makes sure that every push to your repository triggers the CI pipeline, running your tests and building your project automatically.

Summary

We looked at some ways of using package.json scripts to simplify our workflows. Who knew how much power could rest behind a simple npm run dev? Looking at our original example:

  • dev runs the frontend and backend in parallel, after predev.
  • build does type checking via tsc before building the static site.
  • dev:backend continuously deploys the backend functions to your development environment as you edit files.
  • dev:frontend runs a local frontend server that auto-reloads as you edit files.
  • predev runs before dev and does an initial deployment, handling login, configuration, and an initial sync as necessary.
  • test uses Vitest to run tests. Note: npm test is shorthand for npm run test along with other commands, but they’re special cases. npm run test is the habit I suggest.

Footnotes

  1. The way your shell finds which command to run when you type npm is to check the shell’s PATH environment variable (on unix machines anyways). You can see your own with echo "$PATH". It checks all the places specified in $PATH and uses the first one. ↩

  2. Technically you can override & specify where npm installs binaries. ↩

  3. If you really want to, you can run npm exec vitest, npx vitest for short, ./npm_modules/.bin/vitest directly, or add .npm_modules/.bin to your PATH. ↩

  4. Some people use a bare & to run one task in the background, but that is not supported on Windows, and interrupting one command won’t necessarily kill the other. ↩

Build in minutes, scale forever.

Convex is the backend platform with everything you need to build your full-stack AI project. Cloud functions, a database, file storage, scheduling, workflow, vector search, and realtime updates fit together seamlessly.

Get started

Сегодня мы публикуем четвёртую часть перевода руководства по Node.js. В этом материале мы начнём разговор об npm а также рассмотрим особенности файлов package.json и package-lock.json.

[Советуем почитать] Другие части цикла

Часть 1: Общие сведения и начало работы
Часть 2: JavaScript, V8, некоторые приёмы разработки
Часть 3: Хостинг, REPL, работа с консолью, модули
Часть 4: npm, файлы package.json и package-lock.json
Часть 5: npm и npx
Часть 6: цикл событий, стек вызовов, таймеры
Часть 7: асинхронное программирование
Часть 8: Руководство по Node.js, часть 8: протоколы HTTP и WebSocket
Часть 9: Руководство по Node.js, часть 9: работа с файловой системой
Часть 10: Руководство по Node.js, часть 10: стандартные модули, потоки, базы данных, NODE_ENV
Полная PDF-версия руководства по Node.js

Основы npm

Npm (node package manager) — это менеджер пакетов Node.js. В первой части этого материала мы уже упоминали о том, что сейчас в npm имеется более полумиллиона пакетов, что делает его самым большим в мире репозиторием кода, написанного на одном языке. Это позволяет говорить о том, что в npm можно найти пакеты, предназначенные для решения практически любых задач.

Изначально npm создавался как система управления пакетами для Node.js, но в наши дни он используется и при разработке фронтенд-проектов на JavaScript. Для взаимодействия с реестром npm используется одноимённая команда, которая даёт разработчику огромное количество возможностей.

▍Загрузка пакетов

С помощью команды npm можно загружать пакеты из реестра. Ниже мы рассмотрим примеры её использования.

▍Установка всех зависимостей проекта

Если в проекте имеется файл package.json, то установить все зависимости этого проекта можно такой командой:

npm install

Эта команда загрузит всё, что нужно проекту, и поместит эти материалы в папку node_modules, создав её в том случае, если она не существует в директории проекта.

▍Установка отдельного пакета

Отдельный можно установить следующей командой:

npm install <package-name>

Часто можно видеть, как эту команду используют не в таком вот простом виде, а с некоторыми флагами. Рассмотрим их:

  • Флаг --save позволяет установить пакет и добавить запись о нём в раздел dependencies файла package.json, который описывает зависимости проекта. Эти зависимости используются проектом для реализации его основного функционала, они устанавливаются в ходе его развёртывания на сервере (после выхода npm 5 записи об устанавливаемых пакетах в разделе зависимостей делаются автоматически, и без использования этого флага).
  • Флаг --save-dev позволяет установить пакет и добавить запись о нём в раздел, содержащий перечень зависимостей разработки (то есть — пакетов, которые нужны в ходе разработки проекта, вроде библиотек для тестирования, но не требуются для его работы) файла package.json, который называется devDependencies.

▍Обновление пакетов

Для обновления пакетов служит следующая команда:

npm update

Получив эту команду, npm проверит все пакеты на наличие их новых версий, и, если найдёт их новые версии, соответствующие ограничениям на версии пакетов, заданным в package.json, установит их.

Обновить можно и отдельный пакет:

npm update <package-name>

▍Загрузка пакетов определённых версий

В дополнение к стандартной загрузке пакетов, npm поддерживает и загрузку их определённых версий. В частности, можно заметить, что некоторые библиотеки совместимы лишь с некими крупными релизами других библиотек, то есть, если бы зависимости таких библиотек устанавливались бы без учёта версий, это могло бы нарушить их работу. Возможность установить определённую версию некоего пакета полезна и в ситуациях, когда, например, вам вполне подходит самый свежий релиз этого пакета, но оказывается, что в нём имеется ошибка. Ожидая выхода исправленной версии пакета, можно воспользоваться и его более старым но стабильным релизом.

Возможность задавать конкретные версии необходимых проекту библиотек полезна в командной разработке, когда все члены команды пользуются в точности одними и теми же библиотеками. Переход на их новые версии так же осуществляется централизованно, путём внесения изменений в файл проекта package.json.

Во всех этих случаях возможность указания версий пакетов, необходимых проекту, чрезвычайно полезна. Npm следует стандарту семантического версионирования (semver).

▍Запуск скриптов

Файл package.json поддерживает возможность описания команд (скриптов), запускать которые можно с помощью такой конструкции:

npm <task-name>

Например, вот как выглядят перечень скриптов, имеющийся в соответствующем разделе файла:

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

Весьма распространено использование этой возможности для запуска 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",
  }
}

Такой подход даёт возможность заменить ввод длинных команд, чреватый ошибками, следующими простыми конструкциями:

$ npm watch
$ npm dev
$ npm prod

▍Куда npm устанавливает пакеты?

При установке пакетов с использованием npm (или yarn) доступны два варианта установки: локальная и глобальная.

По умолчанию, когда для установки пакета используют команду наподобие npm install lodash, пакет оказывается в папке node_modules, расположенной в папке проекта. Кроме того, если была выполнена вышеописанная команда, npm также добавит запись о библиотеке lodash в раздел dependencies файла package.json, который имеется в текущей директории.

Глобальная установка пакетов выполняется с использованием флага -g:

npm install -g lodash

Выполняя такую команду, npm не устанавливает пакет в локальную папку проекта. Вместо этого он копирует файлы пакета в некое глобальное расположение. Куда именно попадают эти файлы?

Для того чтобы это узнать, воспользуйтесь следующей командой:

npm root -g

В macOS или Linux файлы пакетов могут оказаться в директории /usr/local/lib/node_modules. В Windows это может быть нечто вроде C:\Users\YOU\AppData\Roaming\npm\node_modules.

Однако если вы используете для управления версиями Node.js nvm, путь к папке с глобальными пакетами может измениться.

Я, например, использую nvm, и вышеописанная команда сообщает мне о том, что глобальные пакеты устанавливаются по такому адресу: /Users/flavio/.nvm/versions/node/v8.9.0/lib/node_modules.

▍Использование и выполнение пакетов, установленных с помощью npm

Как использовать модули, установленные с помощью npm, локально или глобально, попадающие в папки node_modules? Предположим, вы установили популярную библиотеку lodash, содержащую множество вспомогательных функций, используемых в JavaScript-разработке:

npm install lodash

Такая команда установит библиотеку в локальную папку проекта node_modules.

Для того чтобы использовать её в своём коде, достаточно импортировать её с применением команды require:

const _ = require('lodash')

Как быть, если пакет представляет собой исполняемый файл?

В таком случае исполняемый файл попадёт в папку node_modules/.bin/ folder.

Посмотреть на то, как выглядит работа этого механизма можно, установив пакет cowsay. Он представляет собой шуточную программу, написанную для командной строки. Если передать этому пакету какой-нибудь текст, в консоли, в стиле ASCII-арта, будет выведено изображение коровы, которая «произносит» соответствующий текст. «Озвучивать» текст могут и другие существа.

Итак, после установки пакета с использованием команды npm install cowsay, он, вместе со своими зависимостями, попадёт в node_modules. А в скрытую папку .bin будут записаны символические ссылки на бинарные файлы cowsay.

Как их выполнять?

Конечно, можно, для вызова программы, ввести в терминале нечто вроде ./node_modules/.bin/cowsay, это рабочий подход, но гораздо лучше воспользоваться npx, средством для запуска исполняемых файлов npm-пакетов, включаемым в npm начиная с версии 5.2. А именно, в нашем случае понадобится такая команда:

npx cowsay

Путь к пакету npx найдёт автоматически.

Файл package.json

Файл package.json является важнейшим элементов множества проектов, основанных на экосистеме Node.js. Если вы программировали на JavaScript, была ли это серверная или клиентская разработка, то вы, наверняка, уже встречались с этим файлом. Зачем он нужен? Что вам следует о нём знать и какие возможности он вам даёт?

Package.json представляет собой нечто вроде файла-манифеста для проекта. Он даёт в распоряжение разработчика множество разноплановых возможностей. Например, он представляет собой центральный репозиторий настроек для инструментальных средств, используемых в проекте. Кроме того, он является тем местом, куда npm и yarn записывают сведения об именах и версиях установленных пакетов.

▍Структура файла

Вот пример простейшего файла package.json:

{
}

Как видите, он пуст. Нет жёстких требований, касающихся того, что должно присутствовать в подобном файле для некоего приложения. Единственное требование к структуре файла заключается в том, что она должна следовать правилам формата JSON. В противном случае этот файл не сможет быть прочитан программами, которые попытаются получить доступ к его содержимому.

Если вы создаёте Node.js-пакет, который собираетесь распространять через npm, то всё радикальным образом меняется, и в вашем package.json должен быть набор свойств, которые помогут другим людям пользоваться пакетом. Подробнее мы поговорим об этом позже.

Вот ещё один пример package.json:

{
  "name": "test-project"
}

В нём задано свойство name, значением которого является имя приложения или пакета, материалы которого содержатся в той же папке, где находится этот файл.

Вот пример посложнее, который я взял из приложения-примера, написанного с использованием Vue.js:

{
  "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"
  ]
}

Как видите, тут прямо-таки немеряно всего интересного. А именно, здесь можно выделить следующие свойства:

  • name — задаёт имя приложения (пакета).
  • version — содержит сведения о текущей версии приложения.
  • description — краткое описание приложения.
  • main — задаёт точку входа в приложение.
  • private — если данное свойство установлено в true, это позволяет предотвратить случайную публикацию пакета в npm.
  • scripts — задаёт набор Node.js-скриптов, которые можно запускать.
  • dependencies — содержит список npm-пакетов, от которых зависит приложение.
  • devDependencies — содержит список npm-пакетов, используемых при разработке проекта, но не при его реальной работе.
  • engines — задаёт список версий Node.js, на которых работает приложение.
  • browserlist — используется для хранения списка браузеров (и их версий), которые должно поддерживать приложение.

Все эти свойства используются либо npm либо другими инструментальными средствами, применяемыми в течение жизненного цикла приложения.

▍Свойства, используемые в package.json

Поговорим о свойствах, которые можно использовать в package.json. Здесь мы будем использовать термин «пакет», но всё, что сказано о пакетах, справедливо и для локальных приложений, которые не планируется использовать в роли пакетов.

Большинство свойств, которые мы опишем, используются лишь для нужд репозитория npm, некоторые используются программами, которые взаимодействуют с кодом, вроде того же npm.

Свойство name

Свойство name задаёт имя пакета:

"name": "test-project"

Имя должно быть короче 214 символов, не должно включать в себя пробелы, должно состоять только из прописных букв, дефисов (-) и символов подчёркивания (_).

Подобные ограничения существуют из-за того, что когда пакет публикуется в npm, его имя используется для формирования URL страницы пакета.

Если вы публиковали код пакета на GitHub, в общем доступе, то хорошим вариантом имени пакета является имя соответствующего GitHub-репозитория.

Свойство author

Свойство author содержит сведения об авторе пакета:

{
  "author": "Flavio Copes <flavio@flaviocopes.com> (https://flaviocopes.com)"
}

Оно может быть представлено и в таком формате:

{
  "author": {
    "name": "Flavio Copes",
    "email": "flavio@flaviocopes.com",
    "url": "https://flaviocopes.com"
  }
}

Свойство contributors

Свойство contributors содержит массив со сведениями о людях, внёсших вклад в проект:

{
  "contributors": [
    "Flavio Copes <flavio@flaviocopes.com> (https://flaviocopes.com)"
  ]
}

Это свойство может выглядеть и так:

{
  "contributors": [
    {
      "name": "Flavio Copes",
      "email": "flavio@flaviocopes.com",
      "url": "https://flaviocopes.com"
    }
  ]
}

Свойство bugs

В свойстве bugs содержится ссылка на баг-трекер проекта, весьма вероятно то, что такая ссылка будет вести на страницу системы отслеживания ошибок GitHub:

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

Свойство homepage

Свойство homepage позволяет задать домашнюю страницу пакета:

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

Свойство version

Свойство version содержит сведения о текущей версии пакета:

"version": "1.0.0"

При формировании значения этого свойства нужно следовать правилам семантического версионирования. Это означает, в частности, что номер версии всегда представлен тремя цифрами: x.x.x.

Первое число — это мажорная версия пакета, второе — минорная версия, третье — патч-версия.

Изменение этих чисел несёт в себе определённый смысл. Так, релиз пакета, в котором лишь исправляются ошибки, приводит к увеличению значения патч-версии. Если выходит релиз пакета, изменения, внесённые в который, отличаются обратной совместимостью с предыдущим релизом — то меняется минорная версия. В мажорных версиях пакетов могут присутствовать изменения, которые делают эти пакеты несовместимыми с пакетами предыдущих мажорных версий.

Свойство license

Свойство license содержит сведения о лицензии пакета:

"license": "MIT"

Свойство keywords

Свойство keywords содержит массив ключевых слов, имеющих отношение к функционалу пакета:

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

Правильный подбор ключевых слов помогает людям находить то, что им нужно, при поиске пакетов для решения неких задач, позволяет группировать пакеты и быстро оценивать их возможный функционал при просмотре сайта npm.

Свойство description

Свойство description содержит краткое описание пакета:

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

Это свойство особенно важно в том случае, если вы планируете публиковать пакет в npm, так как оно позволяет пользователям сайта npm понять предназначение пакета.

Свойство repository

Свойство repository указывает на то, где находится репозиторий пакета:

"repository": "github:flaviocopes/testing",

Обратите внимание, что у значения этого свойства имеется префикс github. Npm поддерживает префиксы и для некоторых других популярных сервисов подобного рода:

"repository": "gitlab:flaviocopes/testing",
"repository": "bitbucket:flaviocopes/testing",

Используемую при разработке пакета систему контроля версий можно задать и в явном виде:

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

Один и тот же пакет может использовать разные системы контроля версий:

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

Свойство main

Свойство main задаёт точку входа в пакет:

"main": "src/main.js"

Когда пакет импортируют в приложение, именно здесь будет осуществляться поиск того, что экспортирует соответствующий модуль.

Свойство private

Свойство private, установленное в true, позволяет предотвратить случайную публикацию пакета в npm:

"private": true

Свойство scripts

Свойство scripts задаёт список скриптов или утилит, которые можно запускать средствами npm:

"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"
}

Эти скрипты являются приложениями командной строки. Запускать их можно с помощью npm или yarn, выполняя, соответственно, команды вида npm run XXXX или yarn XXXX, где XXXX — имя скрипта. Например, выглядеть это может так:

npm run dev

Скрипты можно называть так, как вам хочется, делать они могут практически всё, чего может пожелать разработчик.

Свойство dependencies

Свойство dependencies содержит список npm-пакетов, установленных в виде зависимостей пакета:

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

При установке пакета с использованиеме npm или yarn используются команды такого вида:

npm install <PACKAGENAME>
yarn add <PACKAGENAME>

Эти пакеты автоматически добавляются в список зависимостей разрабатываемого пакета.

Свойство devDependencies

Свойство devDependencies содержит список npm-пакетов, установленных как зависимости разработки:

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

Этот список отличается от того, который хранится в свойстве dependencies, так как имеющиеся в нём пакеты устанавливаются лишь в системе разработчика пакета, при практическом использовании пакета они не применяются.

Пакеты попадают в этот список при их установке с помощью npm или yarn, выполняемой следующим образом:

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

Свойство engines

Свойство engines указывает, какие версии Node.js и других программных продуктов используются для обеспечения работы пакета:

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

Свойство browserlist

Свойство browserlist позволяет сообщить о том, какие браузеры (и их версии) собирается поддерживать разработчик пакета:

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

Этим свойством пользуются Babel, Autoprefixer и другие инструменты. Анализ этого списка позволяет им добавлять в пакет только те полифиллы и вспомогательные механизмы, которые нужны для перечисленных браузеров.

Показанное здесь в качестве примера значение свойства browserlist означает, что вы хотите поддерживать как минимум 2 мажорные версии всех браузеров с как минимум 1% использования (эти данные берутся с ресурса CanIUse.com), за исключением IE 8 и более старых версий этого браузера (подробнее об этом можно узнать на странице пакета browserlists).

▍Хранение в package.json настроек для различных программных инструментов

В package.json можно хранить настройки для различных вспомогательных инструментов вроде Babel или ESLint.

Каждому из таких инструментов соответствует особое свойство, наподобие eslintConfig или babel. Подробности об использовании подобных свойств можно найти в документации соответствующих проектов.

▍О версиях пакетов и семантическом версионировании

В вышеприведённых примерах вы могли видеть, что номера версий пакетов задаются не только в виде обычных чисел, разделённых точками, но и с использованием неких специальных символов. Например, в виде ~3.0.0 или ^0.13.0. Здесь использованы так называемые спецификаторы версий, которые определяют диапазон версий пакетов, подходящих для использования в нашем пакете.

Учитывая то, что при использовании семантического версионирования все номера версий пакетов состоят из последовательностей, представляющих собой три числа, о смысле которых мы говорили выше, опишем следующие правила использования спецификаторов версий:

  • ~: если вы задаёте версию в виде ~0.13.0 это означает, что вас интересуют лишь патч-релизы пакета. То есть, пакет 0.13.1 вам подойдёт, а 0.14.0 — нет.
  • ^: если номер версии задан в виде ^0.13.0, это означает, что вам подходят новые патч-версии и минорные версии пакета. То есть, вас устроят версии пакета 0.13.1, 0.14.0, и так далее.
  • *: воспользовавшись этим символом, вы сообщаете системе, что вас устроят любые свежие версии пакета, в том числе — его новые мажорные релизы.
  • >: подходят любые версии пакета, которые больше заданной.
  • >=: подходят любые версии пакета, которые равны или больше заданной.
  • <=: вас устроят пакеты, версии которых равны заданной или меньше её.
  • <: вас интересуют пакеты, версии которых меньше заданной.
  • =: вам нужна только заданная версия пакета.
  • -: используется для указания диапазона подходящих версий, например — 2.1.0 - 2.6.2.
  • ||: позволяет комбинировать наборы условий, касающихся пакетов. Например это может выглядеть как < 2.1 || > 2.6.

Есть и ещё некоторые правила:

  • отсутствие дополнительных символов: если используется номер версии пакета без дополнительных символов, это значит, что вашему пакету нужна только заданная версия пакета-зависимости и никакая другая.
  • latest: указывает на то, что вам требуется самая свежая версия некоего пакета.

Большинство вышеописанных спецификаторов можно комбинировать, например, задавая диапазоны подходящих версий пакетов-зависимостей. Скажем, конструкция вида 1.0.0 || >=1.1.0 <1.2.0 указывает на то, что планируется использовать либо версию пакета 1.0.0, либо версию, номер которой больше или равен 1.1.0, но меньше 1.2.0.

Файл package-lock.json

Файл package-lock.json используется с момента появления npm версии 5. Он создаётся автоматически при установке Node.js-пакетов. Что это за файл? Возможно, вы не знакомы с ним даже если знали о package.json, который существует гораздо дольше него.

Цель этого файла заключается в отслеживании точных версий установленных пакетов, что позволяет сделать разрабатываемый продукт стопроцентно воспроизводимым в его исходном виде даже в случае, если те, кто занимается поддержкой пакетов, их обновили.

Этот файл решает весьма специфическую проблему, которая не решается средствами package.json. В package.json можно указать, какие обновления некоего пакета вам подходят (патч-версии или минорные версии) с использованием вышеописанных спецификаторов версий.

В Git не коммитят папку node_modules, так как обычно она имеет огромные размеры. Когда вы пытаетесь воссоздать проект на другом компьютере, то использование команды npm install приведёт к тому, что, если, при использовании спецификатора ~ в применении к версии некоего пакета, вышел его патч-релиз, установлен будет не тот пакет, который использовался при разработке, а именно этот патч-релиз.

То же самое касается и спецификатора ^. Если же при указании версии пакета спецификаторы не использовались, то будет установлена именно его указанная версия и проблема, о которой идёт речь, окажется в такой ситуации неактуальной.

Итак, кто-то пытается инициализировать проект, пользуясь командой npm install. При выходе новых версий пакетов окажется, что этот проект отличается от исходного. Даже если, следуя правилам семантического версионирования, минорные релизы и патч-релизы не должны содержать в себе изменений, препятствующих обратной совместимости, все мы знаем, что ошибки способны проникать (и проникают) куда угодно.

Файл package-lock.json хранит в неизменном виде сведения о версии каждого установленного пакета и npm будет использовать именно эти версии пакетов при выполнении команды npm install.

Эта концепция не нова, менеджеры пакетов, применяемые в других языках программирования (вроде менеджера Composer в PHP) используют похожую систему многие годы.

Файл package-lock.json нужно отправить в Git-репозиторий, что позволит другим людям скачать его в том случае, если проект является общедоступным, или тогда, когда его разработкой занимается команда программистов, или если вы используете Git для развёртывания проекта.

Версии зависимостей будут обновлены в package-lock.json после выполнения команды npm update.

▍Пример файла package-lock.json

В этом примере продемонстрирована структура файла package-lock.json, который входит в состав пакет cowsay, устанавливаемого в пустой папке командой npm install cowsay:

{
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "ansi-regex": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.
0.0.tgz",
      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
    },
    "cowsay": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.3.1.tgz"
,
      "integrity": "sha512-3PVFe6FePVtPj1HTeLin9v8WyLl+VmM1l1H/5P+BTTDkM
Ajufp+0F9eLjzRnOHzVAYeIYFF5po5NjRrgefnRMQ==",
      "requires": {
        "get-stdin": "^5.0.1",
        "optimist": "~0.6.1",
        "string-width": "~2.1.1",
        "strip-eof": "^1.0.0"
      }
    },
    "get-stdin": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.
1.tgz",
      "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
    },
    "is-fullwidth-code-point": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/
is-fullwidth-code-point-2.0.0.tgz",
      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
    },
    "minimist": {
      "version": "0.0.10",
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10
.tgz",
      "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
    },
    "optimist": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
      "requires": {
        "minimist": "~0.0.1",
        "wordwrap": "~0.0.2"
      }
    },
    "string-width": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
      "requires": {
        "is-fullwidth-code-point": "^2.0.0",
        "strip-ansi": "^4.0.0"
      }
    },
    "strip-ansi": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
      "requires": {
        "ansi-regex": "^3.0.0"
      }
    },
    "strip-eof": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
    },
    "wordwrap": {
      "version": "0.0.3",
      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
      "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
    }
  }
}

Разберём этот файл. Мы устанавливаем пакет cowsay, который зависит от следующих пакетов:

  • get-stdin
  • optimist
  • string-width
  • strip-eof

Эти пакеты, в свою очередь, зависят от других пакетов, сведения о которых мы можем почерпнуть из свойств requires, которые имеются у некоторых из них:

  • ansi-regex
  • is-fullwidth-code-point
  • minimist
  • wordwrap
  • strip-eof

Они добавляются в файл в алфавитном порядке, у каждого есть поле version, есть поле resolved, указывающее на расположение пакета, и строковое свойство integrity, которое можно использовать для проверки целостности пакета.

Итоги

Сегодня мы начали разговор об npm и разобрались со структурой и назначением файлов package.json и package-lock.json. В следующий раз продолжим разбирать возможности npm и коснёмся использования npx.

Уважаемые читатели! Какой менеджер пакетов вы предпочитаете — npm или yarn?

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Пропали наушники в устройства воспроизведения windows 10
  • Активатор windows xp home edition sp3
  • Как отключить интернет проводной windows 10
  • Сброс пароля bios из под windows
  • Программа для поиска драйверов для windows 10 64 bit