Що таке npm? Підручник з диспетчера пакетів вузлів для початківців

Ця стаття повинна послужити важливим посібником для улюбленого посібника Node.js: npm.

Node.js штурмує світ з 2009 року. Сотні тисяч систем були побудовані за допомогою Node.js, що спонукає спільноту розробників стверджувати, що "JavaScript їсть програмне забезпечення".

Одним з головних факторів успіху Node є npm - його популярний менеджер пакетів, який дозволяє розробникам JavaScript обмінюватися корисними пакетами, такими як lodash і moment, швидко і легко.

На момент написання цього допису npm сприяв публікації понад 1,3 мільйона пакетів із швидкістю завантаження понад 16 мільярдів на тиждень! Ці цифри є фантастичними для будь-якого програмного інструменту. Тож давайте поговоримо про те, що саме таке npm.

Що таке NPM?

NPM - або "Node Package Manager" - це менеджер пакунків за замовчуванням для середовища виконання Node.js.

Він також відомий як "Мутанти гарбуза ніндзя", "Некомерційні виробники піци" та безліч інших випадкових імен, які ви можете вивчити та, напевно, внести свій внесок у розширення npm.

NPM складається з двох основних частин:

  • інструмент CLI (інтерфейс командного рядка) для публікації та завантаження пакетів, і
  • Інтернет-сховище, яке розміщує пакунки JavaScript

Для більш наочного пояснення ми можемо розглядати сховище npmjs.com як центр виконання, який приймає пакети товарів від продавців (автори пакунків npm) і розподіляє ці товари серед покупців (користувачі пакета npm).

Щоб полегшити цей процес, у центрі реалізації npmjs.com працює армія працьовитих вомбатів (npm CLI), які будуть призначені як особисті асистенти кожному окремому клієнту npmjs.com Отже, залежності доставляються розробникам JavaScript наступним чином:

і процес публікації пакету для ваших партнерів JS буде приблизно таким:

Давайте розглянемо, як ця армія вомбатів допомагає розробникам, які хочуть використовувати пакети JavaScript у своїх проектах. Ми також побачимо, як вони допомагають майстрам з відкритим кодом вивести свої круті бібліотеки у світ.

package.json

Кожен проект у JavaScript - будь то Node.js або браузерна програма - може бути визначений як пакет npm із власною інформацією про пакет та своєю package.jsonроботою для опису проекту.

Ми можемо розглядати package.jsonштамповані ярлики на тих добрих коробках, які наша армія вомбатів доставляє.

package.jsonбуде сформовано під час npm initзапуску для ініціалізації проекту JavaScript / Node.js з цими основними метаданими, наданими розробниками:

  • name: назва вашої бібліотеки / проекту JavaScript
  • version: версія вашого проекту. Часто для розробки додатків цим полем часто нехтують, оскільки немає очевидної потреби у версії бібліотек відкритого джерела. Але все-таки він може стати в нагоді як джерело версії розгортання.
  • description: опис проекту
  • license: ліцензія проекту

npm скрипти

package.jsonтакож підтримує scriptsвластивість, яку можна визначити для запуску інструментів командного рядка, встановлених у локальному контексті проекту. Наприклад, scriptsчастина проекту npm може виглядати приблизно так:

{ "scripts": { "build": "tsc", "format": "prettier --write **/*.ts", "format-check": "prettier --check **/*.ts", "lint": "eslint src/**/*.ts", "pack": "ncc build", "test": "jest", "all": "npm run build && npm run format && npm run lint && npm run pack && npm test" } } 

з eslint, prettier, ncc, jestне обов'язково встановлені як глобальні виконувані файли, а також локальними для проекту всередині node_modules/.bin/.

Нещодавнє введення npx дозволяє нам запускати ці node_modulesкоманди з масштабом проекту, як глобально встановлену програму, за допомогою префікса npx ...(тобто npx prettier --write **/*.ts).

залежності проти devDependencies

Ці два мають форму об’єктів ключ-значення з іменами бібліотек npm як ключем та їх семантично відформатованими версіями як значенням. Це приклад із шаблону ActionScript від Github:

{ "dependencies": { "@actions/core": "^1.2.3", "@actions/github": "^2.1.1" }, "devDependencies": { "@types/jest": "^25.1.4", "@types/node": "^13.9.0", "@typescript-eslint/parser": "^2.22.0", "@zeit/ncc": "^0.21.1", "eslint": "^6.8.0", "eslint-plugin-github": "^3.4.1", "eslint-plugin-jest": "^23.8.2", "jest": "^25.1.0", "jest-circus": "^25.1.0", "js-yaml": "^3.13.1", "prettier": "^1.19.1", "ts-jest": "^25.2.1", "typescript": "^3.8.3" } } 

Ці залежності встановлюються за допомогою npm installкоманди з --saveта --save-devпрапорів. Вони призначені для використання у виробничих та розробницьких середовищах відповідно. У наступному розділі ми детальніше розглянемо встановлення цих пакетів.

Тим часом важливо розуміти можливі ознаки, що major.minor.patchстоять перед семантичними версіями (якщо припустити, що ви прочитали модель semver):

  • ^: останній незначний випуск. Наприклад, ^1.0.4специфікація може встановити версію, 1.3.0якщо це остання незначна версія 1основної серії.
  • ~: останній випуск патчу. Так само, як і ^для незначних версій, ~1.0.4специфікація може встановити версію, 1.0.7якщо це остання другорядна версія 1.0меншої серії.

Усі ці точні версії пакунків будуть задокументовані у сформований package-lock.jsonфайл.

package-lock.json

Цей файл описує точні версії залежностей, що використовуються у проекті npm JavaScript. Якщо package.jsonє загальним описовим ярликом, package-lock.jsonце таблиця інгредієнтів.

І так само, як те, як ми зазвичай не читаємо таблицю інгредієнтів продукту (якщо вам не нудно або вам потрібно це знати), package-lock.jsonне передбачається для читання поетапно розробниками (якщо ми не хочемо вирішити це " працює в моїй машині "випуски).

package-lock.jsonзазвичай генерується npm installкомандою, а також читається нашим інструментом NPM CLI для забезпечення відтворення середовищ збірки для проекту за допомогою npm ci.

Як ефективно керувати вомбатами NPM як "покупцем"

Як випливає з 1,3 мільйона опублікованих пакетів проти 16 мільярдів завантажень, згаданих раніше, більшість користувачів npm використовують npm у цьому напрямку. Тож добре знати, як володіти цим потужним інструментом.

npm встановити

Це найчастіше використовувана команда, оскільки ми сьогодні розробляємо програми JavaScript / Node.js.

За замовчуванням npm install встановить останню версію пакета зі ^знаком версії. У npm installконтексті проекту npm буде завантажувати пакети в node_modulesпапку проекту відповідно до package.jsonспецифікацій, оновлюючи версію пакета (і, в свою чергу, регенеруючи package-lock.json), де це можливо, на основі ^та ~відповідності версій.

Ви можете вказати глобальний прапор, -gякщо ви хочете встановити пакет у глобальному контексті, який ви можете використовувати де завгодно на вашій машині (це загальноприйнято для пакетів інструментального рядка, таких як live-server).

npm зробив встановлення пакетів JavaScript настільки простим, що ця команда часто використовується неправильно. Це призводить до того, що npm є прикладом багатьох жартів програмістів, таких як:

Тут --productionна допомогу приходить прапор! У попередньому розділі ми обговорили dependenciesі devDependenciesпризначили для використання у виробництві та середовищі розробки / тестування відповідно. Цей --productionпрапор - це спосіб різниці в node_modules.

By attaching this flag to the npm install command, we will only install packages from dependencies, thus drastically reducing the size of our node_modules to whatever is absolutely necessary for our applications to be up and running.

Just like how as boy and girl scouts we didn't bring lemon squeezers to our lemonade booth, we shouldn't bring devDependencies to production!

npm ci

So if npm install --production is optimal for a production environment, must there be a command that's optimal for my local development, testing setup?

The answer is npm ci.

Just like how if package-lock.json doesn't already exist in the project it's generated whenever npm install is called, npm ci consumes this file to download the exact version of each individual package that the project depends on.

This is how we can make sure that the our project's context stays exactly the same across different machines, whether it's our laptops used for development or CI (Continuous Integration) build environments like Github Actions.

npm audit

With the humongous number of packages that have been published and can easily be installed, npm packages are susceptible to bad authors with malicious intentions like these.

Realising that there was an issue in the ecosystem, the npm.js organisation came up with the idea of npm audit. They maintain a list of security loopholes that developers can audit their dependencies against using the npm audit command.

npm audit gives developers information about the vulnerabilities and whether there're versions with remediations to upgrade to. For example,

If the remediations are available in the next non-breaking version upgrades, npm audit fix can be used to upgrade the affected dependencies' versions automatically.

How to effectively command NPM wombats as "seller"

We have gone through how to wield the NPM CLI tool as a consumer, but what about effectively using it as an author (and potentially becoming a JavaScript open source wizard ?)?

npm publish

Sending a package to our npmjs.com fulfillment centre is super easy as we only need to run npm publish. The tricky part, which is not specific to npm package authors, is determining the version of the package.

The rule of thumb according to semver.org:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards compatible manner, and
  3. PATCH version when you make backwards compatible bug fixes.

It's even more important to follow the above rule when publishing your packages to ensure that you're not breaking anyone's code as the default version matching in npm is ^ (aka the next minor version).

❤️ npm ❤️ JavaScript ❤️ Node.js ❤️

That's all we need to know to start wielding npm effectively and command our lovely army of wombats!