npm / yarn

Лекция 12

Semver

Семантическое версионирование

Semver

  • semver.org
  • Dependency hell
  • Набор правил
  • Об изменениях сообщается через версию MAJOR.MINOR.PATCH / X.Y.Z

Semver - Правила

  • Объявить публичный API (код или документация)
  • X, Y, Z - целые неотрицательные числа
  • Нельзя изменять уже опубликованные версии
  • Любые изменения - новая версия

Semver - MAJOR

  • cделаны обратно несовместимые изменения API
  • 0 - начальная разработка / все может измениться

Semver - MAJOR

  • ДОЛЖНА быть увеличена, если в публичном API представлены обратно несовместимые изменения
  • МОЖЕТ включать изменения, характерные для уровня минорных версий и патчей
  • Когда увеличивается мажорная версия, минорная и патч-версия ДОЛЖНЫ быть обнулены

Semver - MINOR

  • добавляете новый и изменяете старый функционал, не нарушая обратной совместимости
  • ДОЛЖНА быть увеличена, если в публичном API представлен новый обратно совместимый функционал
  • ДОЛЖНА быть увеличена, если какой-либо функционал публичного API помечен как устаревший

Semver - MINOR

  • МОЖЕТ быть увеличена в случае реализации нового функционала или существенного усовершенствования в приватном коде
  • Патч-версия ДОЛЖНА быть обнулена, когда увеличивается минорная версия

Semver - PATCH

  • делаете обратно совместимые исправления
  • ДОЛЖНА быть увеличена только если содержит обратно совместимые баг-фиксы

Semver - Additional

  • Предрелиз - 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7
  • Метаданные - 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85
  • Приоритет определяется по первому отличию при сравнении каждого из идентификаторов слева направо
  • 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1

npm

Node package manager

npm

npm - package

  • a) папка с программой и package.json
  • b) gzip архив (a)
  • c) ссылка (b)
  • d) name@version в реестре имеющий (c)
  • e) name@tag указывающий на (d)
  • f) name@latest указывающий на (d)
  • g) ссылка на git-репозиторий с (a)

npm - install


// локальная установка
> npm install package_name

// глобальная
> npm install -g package_name

// сокращение
> npm i package_name
    

npm - package.json


{
  "name": "my-awesome-package",
  "version": "1.0.0"
}
    

npm - package.json


// lowercase
// без пробелов
// одно слово
// можно - и _
"name"

// X.Y.Z
"version"
    

npm - package.json


description
keywords
homepage
bugs: { url, email }
license
author | contributors: { name, email, url }
private
    

npm - package.json


files # файлы для публикации
main # главный файл
bin # для создания symlink
man # ссылка на документацию
repository # ссылка на VCS репозиторий
scripts # список скриптов
    

npm - package.json


"engines" : { "node" : ">=0.10.3 <0.12" }
"os" : [ "darwin", "linux" ]
"cpu" : [ "x64", "ia32" ]
    

npm - package.json


// создание
// name, version, main, scripts, keywords
// author, license, repository
npm init

> npm set init.author.email "wombat@npmjs.com"
> npm set init.author.name "ag_dubs"
> npm set init.license "MIT"
    

npm - package.json


// ~/.npm-init.js
module.exports = {
  customField: 'Custom Field',
  otherCustomField: 'This field is really cool'
}

// or
module.exports
  = prompt("what's your favorite ice cream?",
    "I LIKE THEM ALL");
    

npm - dependencies


{
  "dependencies": {
    "my_dep": "^1.0.0"
  },
  "devDependencies": {
    "my_test_framework": "^3.1.0"
  },
  "optionalDependencies": {
    "my_optional_util": "^4.2.4"
  },
  "peerDependencies": {
    "react": "^16.0.1"
  },
  // npm pack
  "bundledDependencies": [
    "renderized", "super-streams"
  ]
}
    

npm - deps


> npm install package_name --save

> npm install package_name --save-dev

> npm install

> npm install --production
    

npm - deps


> npm outdated

> npm update

> npm update package

> npm update -g

> npm outdated -g --depth=0
    

npm - deps

npm - uninstall


> npm uninstall package --save

> npm uninstall package --save-dev

> npm uninstall package -g
    

npm - publish


> npm adduser

> npm login

> npm publish

// README.md, .gitignore, .npmignore
// https://npmjs.com/package/package_name
    

npm - publish

npm - version


> npm view bluebird version

> npm version 1.0.2

> npm version [major | minor | patch]
    

npm - version


"bluebird": "3.4.7"
    

npm - version


// все что выше в пределах major
"bluebird": "^3.4.5"

+:
3.4.5
3.4.6
3.4.7

-:
4.0.0
    

npm - version


// все что выше в пределах minor
"bluebird": "~3.3.1"

+:
3.3.1
3.3.2
3.3.3

-:
3.4.0
    

npm - version


"bluebird": ">3.3.1"
"bluebird": ">=3.3.1"
"bluebird": "<3.3.1"
"bluebird": "3.3.1 - 3.3.3"
    

npm - version

npm - scope

  • это namespace для модулей
  • @scope/project-name
  • npm publish --access=public

{
  "dependencies": {
    "@username/project-name": "^1.0.0"
  }
}
    

npm - tags


> npm publish --tag beta
    

> npm install bluebird@beta
    

> npm dist-tag add bluebird@4.0.0-0 beta
    

> npm dist-tag rm bluebird beta
    

> npm dist-tag ls bluebird
    

npm - deprecate


> npm deprecate <pkg>[@<version>] <message>
    

> npm deprecate my-thing@"< 0.2.3"
      "critical bug fixed in v0.2.3"
    

npm - link


> npm link (in package dir)
> npm link [<@scope>/]<pkg>[@<version>]
    

> cd ~/projects/node-redis
> npm link
> cd ~/projects/node-bloggy
> npm link redis
    

npm - pack


> npm pack [[<@scope>/]<pkg>...]
    

npm - prune


> npm prune [[<@scope>/]<pkg>...] [--production]
    

npm - dedupe

Добавили D

Добавили E

B v1.0 уже есть наверху

Обновили A

Обновили E

B v1.0 заменился на B v2.0, потому что не было зависимостей кроме E


> npm dedupe
    

npm - shrinkwrap


{
  "name": "A",
  "version": "0.1.0",
  "dependencies": {
    "B": "<0.1.0"
  }
}
    

npm - shrinkwrap


{
  "name": "B",
  "version": "0.0.1",
  "dependencies": {
    "C": "<0.1.0"
  }
}
    

npm - shrinkwrap


{
  "name": "C",
  "version": "0.0.1"
}
    

npm - shrinkwrap


npm install A

A@0.1.0
`-- B@0.0.1
    `-- C@0.0.1

если есть B@0.0.2

A@0.1.0
`-- B@0.0.2
    `-- C@0.0.1
    

npm - shrinkwrap


npm-shrinkwrap.json
{
  "name": "A",
  "version": "0.1.0",
  "dependencies": {
    "B": {
      "version": "0.0.1",
      "from": "B@^0.0.1",
      "resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
      "dependencies": {
        "C": {
          "version": "0.0.1",
          "from": "org/C#v0.0.1",
          "resolved": "..."
        }
      }
    }
  }
}
    

npm - package-lock.json


# генерируется автоматически
# тот же формат что и у npm-shrinkwrap.json
# приватный, хранится в VCS
# единное дерево зависимостей
# история дерева зависимостей
    

npm - unpublish


npm unpublish [<@scope>/]pkg[@version]
    

npm


.npmingore
.npmrc
    

Yarn

Yarn

  • Ultra Fast / кэш + паралельность + offline-mod
  • Mega Secure / контрольные суммы пакетов
  • Super Reliable / lock-файлы для версий
  • yarnpkg.com

Yarn

Yarn


> yarn init
    

> yarn add [package]
> yarn add [package]@[version]
> yarn add [package]@[tag]
    

> yarn remove [package]
    

> yarn install
> yarn install --force
> yarn install --production
    

Yarn - Workspaces


package.json (workspace root):
{
  "private": true,
  "workspaces": ["workspace-a", "workspace-b"]
}
    

Yarn - Workspaces


workspace-a/package.json:
{
  "name": "workspace-a",
  "version": "1.0.0",

  "dependencies": {
    "cross-env": "5.0.5"
  }
}
    

Yarn - Workspaces


workspace-a/package.json:
{
  "name": "workspace-b",
  "version": "1.0.0",

  "dependencies": {
    "cross-env": "5.0.5",
    "workspace-a": "1.0.0"
  }
}
    

Yarn - Workspaces


> yarn install

/package.json
/yarn.lock

/node_modules
/node_modules/cross-env
/node_modules/workspace-a -> /workspace-a

/workspace-a/package.json
/workspace-b/package.json