dependencies? devDependencies? peerDependencies?
npm install? npm i? npm ci?
--save? --save-dev? --save-prod? -g?
package.json? package-lock.json? .npmrc?
"module": "^1.0.0"?
"module": "~1.0.0"?
"module": "1.0.0"?
Что из этого можно править руками?
Что из этого в Гит?
Какой командой в итоге билдить?
Актуально для: node -v — v20.5.0 и npm -v — 10.2.3
Что предлагает Svelte на старте?
(После npm create svelte@latest my-app)
- В
package-lock.jsonтолькоdevDependencies(без prod-dependencies):
И все эти зависимости «из коробки» НЕ строгие, т.е. с ^:
```
"devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/kit": "^1.20.4",
"svelte": "^4.0.5",
"vite": "^4.4.2"
},
```
-
.npmrc(NPM Run Command) с единственной строкойengine-strict=true.
P.S. package-lock.json нет вообще (и не надо).
Что рекомендуют разработчики Svelte?
Определиться с адаптером, вместо adapter-auto.
It's recommended to install the appropriate adapter to your devDependencies once you've settled on a target environment, since this will add the adapter to your lockfile and slightly improve install times on CI.
https://kit.svelte.dev/docs/adapter-auto
Мы люди простые, — возьмём универсальный adapter-node.
Итак,
Как установить новый модуль?
https://docs.npmjs.com/cli/v10/commands/npm-install
По умолчанию, npm install @sveltejs/adapter-node — запишет в prod-dependencies.
Потом, можно перекинуть в devDependencies путём:
npm install @sveltejs/adapter-auto --save-dev.
Но, снова вернуть в «prod» той же командой:
npm install @sveltejs/adapter-auto уже не получится.
Чтобы форсануть обратно в «prod»:
npm install @sveltejs/adapter-auto --save-prod
-
npm install @sveltejs/adapter-auto --save— такого просто нет (как минимум в npm v10) - Но нода не ругается на несуществующие параметры.
- Более того, ей без разницы —
что так:
npm install module-name --param, что так:npm install --param module-name. - А вообще можно и просто
npm i module-name. - Можно и
npm i module_name -g, если модуль нужен не для проекта, а как консольная утилита для чего-нибудь.
Но это не то, что нам нужно.
Мы знаем, чем оборачивается «НЕ строгая версия».
Как установить строгую версию?
Есть 4 способа:
-
npm config set save-exact trueСомнительно, т.к. делает запись где-то глобально, и только на локальной машине.
P.S.
Создаётся на самом деле 2-е переменные вnpm config list:
save-exact = true
save-prefix = ""Если вернуть обратно (
npm config set save-exact true), будет:
save-exact = false
save-prefix = "^" -
npm install @sveltejs/adapter-auto --save-exactДелает свою работу, но нам нужна защита от дурака, на всю команду.
Добавить в
.npmrc>>save-exact=true.
Т.е., теперь, когда мы делаем npm i module-name он автоматически будет устанавливать строгую версию, без ^.
(Тут, никаких save-prefix = "" не надо, это была внутренняя штука для глобального конфига.)
- Можно руками постирать все
^, но — тогда у нас окажутся устаревшие пакеты :D.
То, что было вначале пришло в devDependencies — не совсем свежее.
Но, пока мы ещё ничего не установили, у нас нет ни node_modules/, ни package-lock.json — нам ничего не мешает действительно всё прописать руками.
Итого:
- Идём по П.3. — добавляем в
.npmrc>>save-exact=true. - Для всего, что видим в
devDependencies— заного поочерёдно делаемnpm i module-name. (Они перелетят изdevDependenciesв prod-dependencies. Пока, тут это нам и нужно.) - Ну и наконец-то устанавливаем наш
adapter-auto:
npm i @sveltejs/adapter-auto.
P.S. Устанавливая один модуль — установятся все dependencies, как если бы мы делали всё это одним npm i.
А @sveltejs/adapter-auto можно удалить, чтоб не мешался.
Как удалить модуль?
https://docs.npmjs.com/cli/v10/commands/npm-uninstall
-
npm uninstall @sveltejs/adapter-auto— удалит в каких бы*Dependenciesони не находились.Раньше нужно было дописывать
--save-devи т.д., иначе удалится изnode_modules/, но не изpackage.jsonи т.д.
Сейчас этого нет. Только если прописать в.npmrc>>save=false, тогда нужно будет--save.
Но не вижу во всём этом смысла для общих случаев. -
Можно удалить строку
"@sveltejs/adapter-auto": "^2.0.0",руками.При этом удалить
node_modules/иpackage-lock.json.
И сделатьnpm iвсего проекта заново.
Но, так делать не стоит, когда всё уже в бою.
Это может навредить и серверной сборке, и коллегам, но об этом позже.
Как не захламить prod-dependencies?
Понятно, что в процессе разработки мы пробуем много разных модулей, которые чаще всего не пойдут на прод.
И, не хотелось бы, чтобы всё ложилось в prod-dependencies.
Тут выясняется, что возможен ещё какой-то peerDependencies,
где вообще — у каждого разработчика появляется свой личный блок с модулями:
npm i node_module --save-peer (--save-peer не задокументирован, но работает. https://stackoverflow.com/a/74549787/4117781)
Пропустил я эту команду, и получил что-то новое — звёздочку! в devDependencies:
"devDependencies": {
"@sveltejs/adapter-auto": "*",
},
"peerDependencies": {
"@sveltejs/adapter-auto": "2.1.1"
}
Испугался, и решил не использовать.
Давайте лучше дружно хламить devDependencies, но уж лучше без этого.
Там ещё как-то должен был прописаться мой личный скоуп, на основе имени компа, но и этого автоматически не произошло.
Валим из этой идеи короче :D
Как минимум в этой статье.
Не будем тянуть.
Чтобы все модули по-умолчанию сваливались в devDependencies:
.npmrc >> save-dev=true
Теперь, чтобы вогнать что-то в prod-dependencies нужно будет npm i module-name --save-prod.
Такое делается не каждый день. Но — это ответственно.
Потому, вероятно — это должен делать кто-то один из команды.
Зачем нужен package-lock.json?
У модулей, которые у нас в зависимостях, — есть свои зависимости.
Каждая мажорная версия (1.0.0 —> 2.0.0) по конвенции допускает нарушение обратной совместимости.
https://docs.npmjs.com/about-semantic-versioning
Зафиксируем:
^1.0.0 — тут разработчик модуля говорит, что версия зависимости сойдёт вплоть до 2.0.0.
~1.0.0 — тут разработчик модуля говорит, что версия зависимости сойдёт вплоть до 1.1.0.
И — наши зависимости, зависимости модулей — могут между собой пересекаться.
А сама конечная зависимость — может быть только одна.
И, делая npm i — каждый новый раз — нода может выкачивать из своих репозиториев чутка разные набор зависимостей, более оптимальные на текущий момент, удовлетворяя при этом всем настройкам выше — и в наших зависимостях, и в зависимостях зависимостей.
Поэтому, несмотря на то, что package-lock.json такой страшный — к сожалению, его лучше всё же класть в git.
Чтобы не попасть в ситуацию, когда набор зависимостей на локале и на проде разный, а ты не можешь понять в чём ошибка.
А ошибка может быть в любой даже минорной версии с баг-фиксом в любой из зависимостей.
Хотя, это и бывает редко. Но бьёт больно.
Чтобы package-lock.json так не раздражал в git-e, парни предлагают:
.gitattributes —> package-lock.json binary
https://stackoverflow.com/a/50982431/4117781
Итого в .npmrc
https://docs.npmjs.com/cli/v10/configuring-npm/npmrc
engine-strict=true <— добрая рекомендация от Svelte
save-exact=true
save-dev=true
Что ещё интересного в package.json?
1. "private": true,
Consider also setting "private": true to prevent accidental publication.
https://docs.npmjs.com/cli/v10/configuring-npm/package-json
Не знаю как это возможно, но, если «accidental», то убирать не будем.
2. "type": module,
Это то, что позволяет нам делать модные import a from '/b.js, вместо старых a = require('b') и т.д.
3. Авторская рекомендация
Т.к. у нас кроме ноды есть строгое API со всякими проверками на всякие хосты, порты и заголовки,
стоит гарантировать на каком хосте/порте будет открываться dev-версия.
Заменить:
"dev": "vite dev",
На:
"dev": "vite dev --host 127.0.0.1 --port 3000",
А ещё добавить:
"host": "vite dev --host --port 3000",
чтобы просто npm run host, и проект можно посмотреть хоть на телефоне (если подключен к тому же wi-fi)
Во имя науки
- Можно руками закинуть модуль и в «prod» и в «dev». И даже ничего не сломается, но — не знаю зачем.
При попытке обновить/форсировать установку ещё раз — одна из записей сотрётся, в зависимости от куда
--save-xи т.д. -
optionalDependencies— когда допускаем, что модуль может не установиться, а он нам и не очень-то и нужен. -
bundleDependencies— когда пилим свой модуль. - Постоянно встречаются упоминания
npm-shrinkwrap.json— Это «freeze»package-lock.jsonдля тех случаев когда это внезапно нужно:- Ноддерживает старые версии ноды (когда
package-lock.jsonтолько с v5), - Необходим для публикации в качестве npm-модуля,
- А также, если встряли с версиями зависимостей. Тут
npm-shrinkwrap.jsonпозволит управлять версиями вручную (https://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/). В общем, не думая об этом — мы ничего не упускаем. Просто будем знать на всякий случай.
- Ноддерживает старые версии ноды (когда
Как делать install на проде?
Принято делать вот так:
npm ci --[ТОЛЬКО PROD-DEPENDENCIES]
- [ТОЛЬКО PROD-DEPENDENCIES]
Можно встретить много рекомендаций, обещающих один и тот же результат:
--omit=dev, --include=prod, --only=prod, --production
По всей видимости это из-за долгой эволюции ноды.
Для последней 10-й версии в документации есть только --include=prod (https://docs.npmjs.com/cli/v10/commands/npm-ci).
Но, так — у меня устанавливаются всё — и «prod» и «dev».
В итоге, делаю так:
npm ci --omit=dev
Множественное «опущение» делается так:
npm ci --omit=dev --omit=peer
Собственно, это то, что выкачивает node_modules/ на основе package-lock.json, в обход package.json, гарантируя то, что на проде будет так, как было на локале.
Иии, внииимаааниииеее...
Спасибо, за внимание.
Top comments (0)