Для того, чтобы посмотреть на реальный «package.json» поставим модуль «express».
Этим модулем мы ещё будем пользоваться в будущем, а сейчас просто ставим этот внешний модуль и взглянем на его «package.json», как он выглядит
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
{ "name": "express", "description": "Fast, unopinionated, minimalist web framework", "version": "4.14.0", // npm i express@4.0 // версия = "MAJOR.MINOR.PATCH", см. http://semver.org "author": { "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" }, "contributors": [ { "name": "Aaron Heckmann", "email": "aaron.heckmann+github@gmail.com" }, { "name": "Ciaran Jessup", "email": "ciaranj@gmail.com" }, { "name": "Douglas Christopher Wilson", "email": "doug@somethingdoug.com" }, { "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }, { "name": "Jonathan Ong", "email": "me@jongleberry.com" }, { "name": "Roman Shtylman", "email": "shtylman+expressjs@gmail.com" }, { "name": "Young Jae Sim", "email": "hanul@hanul.me" } ], "license": "MIT", "repository": { "type": "git", "url": "https://github.com/expressjs/express" }, "homepage": "http://expressjs.com/", "keywords": [ "express", "framework", "sinatra", "web", "rest", "restful", "router", "app", "api" ], "dependencies": { "accepts": "~1.3.3", "array-flatten": "1.1.1", "content-disposition": "0.5.1", "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "~2.2.0", "depd": "~1.1.0", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", "finalhandler": "0.5.0", "fresh": "0.3.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.2", "qs": "6.2.0", "range-parser": "~1.2.0", "send": "0.14.1", "serve-static": "~1.11.1", "type-is": "~1.6.13", "utils-merge": "1.0.0", "vary": "~1.1.0" }, "devDependencies": { "after": "0.8.1", "body-parser": "~1.15.1", "cookie-parser": "~1.4.3", "ejs": "2.4.2", "istanbul": "0.4.3", "marked": "0.3.5", "method-override": "~2.3.6", "mocha": "2.5.3", "morgan": "~1.7.0", "should": "9.0.2", "supertest": "1.2.0", "connect-redis": "~2.4.1", "cookie-session": "~1.2.0", "express-session": "~1.13.0", "jade": "~1.11.0", "multiparty": "~4.1.2", "vhost": "~3.0.2" }, "engines": { "node": ">= 0.10.0" }, "files": [ "LICENSE", "History.md", "Readme.md", "index.js", "lib/" ], "scripts": { "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/", "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/", "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/", "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/" }, "gitHead": "9375a9afa9d7baa814b454c7a6818a7471aaef00", "bugs": { "url": "https://github.com/expressjs/express/issues" }, "_id": "express@4.14.0", "_shasum": "c1ee3f42cdc891fb3dc650a8922d51ec847d0d66", "_from": "express@latest", "_npmVersion": "1.4.28", "_npmUser": { "name": "dougwilson", "email": "doug@somethingdoug.com" }, "maintainers": [ { "name": "dougwilson", "email": "doug@somethingdoug.com" }, { "name": "hacksparrow", "email": "captain@hacksparrow.com" }, { "name": "jasnell", "email": "jasnell@gmail.com" }, { "name": "mikeal", "email": "mikeal.rogers@gmail.com" } ], "dist": { "shasum": "c1ee3f42cdc891fb3dc650a8922d51ec847d0d66", "tarball": "https://registry.npmjs.org/express/-/express-4.14.0.tgz" }, "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", "tmp": "tmp/express-4.14.0.tgz_1466095407850_0.17484632693231106" }, "directories": {}, "_resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz" } |
Здесь я позволил себе кратко прокомментировать некоторые строчки этого файла, на самом деле, конечно же, такой «package.json» работать не будет, потому что комментариев в json не может быть, это делает json не валидным. Мы кратко пройдемся по некоторым особенностям «package.json», пока что в общих чертах, в дальнейшем, когда мы будем делать конкретные вещи, то мы используем это для решения конкретных задач.
Итак поля(в скобочках будет номер строки):
(2) «name» — уже знаем
(3) «description» — описание, информационное поле, по нему осуществляется поиск при «npm search».
(4) «version» — версия имеет вид «MAJOR.MINOR.PATCH» и подчиняется спецификации semver. Что это значит? Это означает, что когда я делаю пакет, пока я его еще не опубликовал, или опубликовал, но не в законченном виде, я делаю первый номер ноль
1 |
"version": "0.14.0" |
Это означает, что какие бы(вторая и третья цифры) номера версий не были, я могу поменять в любой момент, что угодно. Ноль, это не стабильный пакет. Дальше, когда пакет стал стабильным, хотя бы
1 |
"version": "1.14.0" |
теперь каждый номер версии имеет конкретный смысл. Здесь последнее значение это патч — PATCH, если я вношу какие то незначительные изменения, скажем bug-fixing
1 |
"version": "1.14.9" |
Дальше, средний компонент это минорная версия. Минорная — MINOR версия обновляется при изменениях, которые добавляют новые возможности, но при этом не ломают то, что есть. Таким образом, если человек использует мой модуль, то при выпуске новой версии, например
1 |
"version": "1.15.0" |
он может обновиться и его текущий код не должен сломаться.
И наконец мажорная — MAJOR версия. Если я внес хоть какое то, минимальное изменение, которое ломает существующий код, например поменял порядок аргументов у функции, то я обязан изменить MAJOR версию
1 |
"version": "2.0.0" |
Вот такая, достаточно простая схема нумерации версий, у нее есть еще ряд нюансов и если захотите с ними подробней ознакомиться — http://semver.org/lang/ru/ Семантическое версионирование, используется повсеместно в Node.JS и не только.
Для его, чтобы поставить конкретную версию используют вот такой синтаксис
1 |
npm i express@3.0 |
Например 3.0 — это последняя версия ветки 3.0 например 3.0.15. Могу просто указать 3 — тогда это последняя версия этой ветки, если последняя была 3.8.6, то поставила бы ее. Обычно старую версию ставят либо из соображений совместимости, либо потому что у более новой какие то ошибки.
Иногда возникает другая задача, необходимо поставить самую, самую последнюю версию модуля, которая еще не была опубликована. Например, потому что в ней были исправлены важные ошибки или добавлены какие то возможности. Это очень просто, если модуль разрабатывается используя систему версионирования «Git». Например на GitHub. Достаточно получить Git Read-Only url
скопировать его и в консоли набираем
1 |
npm i https://github.com/expressjs/express.git |
получаем
Эффект то же. Еще один вариант, это прямо скачать архив с модулем и дать его аргументом в «npm i …» более подробно про «npm install» можно посмотреть в хелпе —
Откроется документация в браузере
как видите, перед нами список всего, что может получать эта команда. То есть «npm install» очень гибкая штука, она может ставить модуль от куда угодно.
следующие поля информационные, это
(6) «author» — про автора
(10) «contributors» — про тех кто принимал участие
(40) «license» — понятно,
(41) «repository» — это репозиторий где находятся исходники модуля, информационное поле, никакой существенной роли не играет
(45) «homepage» — говорит само за себя
(46) «keywords» — ключевые слова — информационное поле, которое используется «npm search» при поиске.
(57) «dependencies» — уже структурное поле, оно указывает те модули от которых зависит данный. Если мы обратим внимание на консоль, то там, когда ставился «express», выдало вот такой список
Это подмодули. Каждый модуль из этого списка будет ставиться в поддиректорию «node_modules». То есть видите, я поставил «express» в папку с проектом, и «NPM» сам создал себе папку «node_modules» куда и поставил «express». Внутри же папки «express» есть своя папка «node_modules» где и находятся подмодули «express».
Это очень классное свойство «NPM».
Свойство «dependencies», можно использовать, так же для упрощения установки модуля. Например я написал модуль и я хочу его кому нибудь передать. Не обязательно при помощи репозитория, или я его куда нибудь скопировал, я не обязан таскать за собой большую директорию «node_modules», я просто сделаю
1 2 3 4 5 6 7 8 |
{ "name": "my", "version": "0.0.1", "dependencies": { "express": "3" } } |
и дальше, кто угодно, кто получил директорию с «package.json» может зайти в консоль и набрать команду «npm i»
Как видите, «NPM» сначала выругался на мой «package.json», в связи с недостатком описания, но потом, все же, поставил «express» в директорию «node_modules», причем «express» именно версии 3.
Кроме «dependencies» есть еще «devDependencies»
(85) «devDependencies» — они не ставятся, если модуль подтягивается как зависимость. Иначе говоря, в той инсталляции которую я только что сделал, через «npm install» в «express» поставились только «dependencies». Модули «devDependencies», предполагается, что нужны для разработки и они будут ставиться в двух случаях. Первое — если стоит специальный флаг конфига, команда есть такая «npm config». И второе, если я зайду непосредственно в директорию «express» и уже в директории из консоли наберу «npm install»
(114) «scripts» — позволяет задавать команды которые автоматически выполняются при некоторых действиях с пакетом. Со списком таких команд можно ознакомиться введя в консоли «npm help scripts».
Так же бывает поле «main» — оно задает точку входа в пакет. Обычно, когда мы подключаем какой то модуль, например «require(«express»)», то подключается файл «index.js» в этой директории. Заданием поля «name» это можно поменять, например
1 |
"main": "lib/application" |
В таком случае при подключении «require(«express»)» будет подключаться не «index.js» которого может и не быть, а данный файл «application.js».
Ну и многие другие поля с которыми можно ознакомится в документации по «package.json» или, введя в консоли «npm help json», все в той же документации.