Установка локального модуля с помощью npm?
У меня есть загруженный репозиторий модуля, и я хочу установить его локально, а не глобально в другую директорию. Какой простой способ сделать это?
5 ответ(ов)
Вот что сработало для меня:
ШАГ 1: В модульном проекте
выполните npm pack
:
Это создаст файл <имя-пакета>-<версия>.tar.gz
.
ШАГ 2: Переместите файл в потребительский проект
:
Идеально, если вы создадите папку tmp
в корне вашего потребительского проекта
и поместите все такие файлы туда.
ШАГ 3: Укажите его в вашем package.json
:
"dependencies": {
"my-package": "file:./tmp/my-package-1.3.3.tar.gz"
}
ШАГ 4: Установите
пакеты:
Выполните команду npm install
, npm i
или yarn
.
Теперь ваш пакет будет доступен в папке node_modules
вашего потребительского проекта
.
Удачи!
Проблема, с которой вы столкнулись, заключается в том, что ни один из предложенных подходов (npm link
или зависимость в файле package.json
) не работает, если у локального модуля есть «peer dependencies», которые вы хотите установить только в рамках вашего проекта.
Рассмотрим пример:
Файл package.json
вашего локального модуля /local/mymodule/package.json
выглядит так:
{
"name": "mymodule",
"peerDependencies": {
"foo": "^2.5"
}
}
А файл package.json
вашего проекта /dev/myproject/package.json
выглядит следующим образом:
{
"dependencies": {
"mymodule": "file:/local/mymodule",
"foo": "^2.5"
}
}
В этом случае при установке npm настраивает node_modules/
вашего проекта myproject
следующим образом:
/dev/myproject/node_modules/
↳ foo/
↳ mymodule -> /local/mymodule
Когда Node загружает mymodule
и выполняет require('foo')
, он разрешает символическую ссылку mymodule
и ищет foo
только в /local/mymodule/node_modules/
(и его родительских каталогах), где, как вы правильно заметили, foo
отсутствует. Вместо этого нам нужно, чтобы Node искал в /dev/myproject/node_modules/
, так как именно там установлен foo
.
Таким образом, нам нужен способ сообщить Node, чтобы он не разрешал эту символическую ссылку при поиске foo
, или же необходимо найти способ заставить npm устанавливать копию mymodule
, когда используется синтаксис зависимости файла в package.json
. К сожалению, я пока не нашел решения для этой проблемы.
Отсутствует основное свойство?
Как отвечали предыдущие участники, вам нужно выполнить команду npm i --save ../местоположение-вашего-корневого-каталога-пакетов
. Однако в каталоге ../местоположение-вашего-корневого-каталога-пакетов
должно быть две вещи для успешного выполнения:
- Наличие файла
package.json
в указанном каталоге. - Свойство
main
в файлеpackage.json
должно быть установленным и рабочим, например:"main": "src/index.js"
, если основной файл для../местоположение-вашего-корневого-каталога-пакетов
— это../местоположение-вашего-корневого-каталога-пакетов/src/index.js
.
У меня возникло много проблем с решениями, упомянутыми ранее...
У меня есть локальный пакет, который я хочу всегда использовать, а не связываться с ним через npm link, потому что он не будет использоваться за пределами этого проекта (пока что) и не будет загружен в npm-репозиторий для широкого использования.
Мне также нужно, чтобы это работало как на Windows, так и на Unix, поэтому символические ссылки не подходят.
Указание на tar.gz файл (результат npm-пакета) работает для папки зависимого npm-пакета, однако это вызывает проблемы с кэшем npm, если вы хотите обновить пакет. Он не всегда загружает новую версию из связанного npm-пакета, когда вы обновляете его, даже если удалить node_modules и переустановить npm для основного проекта.
Итак... Вот что хорошо сработало для меня!
Фрагмент файла package.json основного проекта:
"name": "main-project-name",
"version": "0.0.0",
"scripts": {
"ng": "ng",
...
"preinstall": "cd ../some-npm-package-angular && npm install && npm run build"
},
"private": true,
"dependencies": {
...
"@com/some-npm-package-angular": "file:../some-npm-package-angular/dist",
...
}
Это достигает трех вещей:
- Избегает распространенной ошибки (по крайней мере в проектах на Angular) "index.ts is not part of the compilation." — так как указывает на собранную (dist) папку.
- Добавляет шаг preinstall для сборки связанного npm-клиентского пакета, чтобы убедиться, что папка dist нашего зависимого пакета собрана.
- Избегает проблем, связанных с тем, что локальная ссылка на tar.gz файл может кэшироваться npm и не обновляться в основном проекте без ненужной очистки/устранения неисправностей/перестройки/переустановки.
Надеюсь, это понятно и кому-то поможет.
Подход с tar.gz тоже вроде бы работает...
Установка через npm (путь к файлу) тоже вроде бы работает.
Всё это основано на сгенерированном клиенте из спецификации OpenAPI, которую мы хотели сохранить в отдельном месте (вместо копирования и вставки для отдельных файлов).
====== ОБНОВЛЕНИЕ: ======
С вышеуказанным решением есть дополнительные ошибки при обычном процессе разработки, поскольку схема версионирования npm с локальными файлами абсолютно ужасна. Если ваш зависимый пакет часто меняется, вся эта схема ломается, потому что npm будет кэшировать последнюю версию проекта, а затем выдаст ошибку, когда SHA-хэш больше не будет совпадать с сохраненным в вашем package-lock.json файле и другими проблемами.
В результате я рекомендую использовать подход с *.tgz и обновлять версию при каждом изменении. Это работает, выполняя три действия.
Первое:
Для вашего зависимого пакета используйте библиотеку npm "ng-packagr". Она автоматически добавляется в авто-сгенерированные клиентские пакеты, созданные генератором кода angular-typescript для OpenAPI 3.0.
В результате у проекта, на который я ссылаюсь, есть раздел "scripts" в package.json, который выглядит следующим образом:
"scripts": {
"build": "ng-packagr -p ng-package.json",
"package": "npm install && npm run build && cd dist && npm pack"
},
А проект, ссылающийся на этот другой проект, добавляет шаг pre-install, чтобы убедиться, что зависимый проект актуален и собран перед сборкой себя:
"scripts": {
"preinstall": "npm run clean && cd ../some-npm-package-angular && npm run package"
},
Второе:
Ссылайтесь на собранный tgz npm-пакет из вашего основного проекта!
"dependencies": {
"@com/some-npm-package-angular": "file:../some-npm-package-angular/dist/some-npm-package-angular-<packageVersion>.tgz",
...
}
Третье:
Обновляйте версию зависимого пакета каждый раз, когда вы обновляете зависимый пакет. Вам также нужно будет обновить версию в основном проекте.
Если вы этого не сделаете, NPM будет использовать кэшированную версию и выдаст ошибку, когда SHA-хэш не совпадает. NPM версионирует файлы на основе изменения имени файла. Он не проверяет сам пакет для обновленной версии в package.json, и команда NPM заявила, что они не намерены это исправлять, хотя люди продолжают поднимать этот вопрос: https://github.com/microsoft/WSL/issues/348.
На данный момент просто обновите:
"version": "1.0.0-build5",
В файле package.json зависимого пакета, а затем обновите вашу ссылку на него в основном проекте, чтобы указать на новое имя файла, например:
"dependencies": {
"@com/some-npm-package-angular": "file:../some-npm-package-angular/dist/some-npm-package-angular-1.0.0-build5.tgz",
...
}
Вы привыкнете к этому. Просто обновляйте два файла package.json — версию, а затем ссылку на новое имя файла.
Надеюсь, это поможет кому-то...
Я столкнулся с другим решением, чем указано выше, при установке пользовательского сборки пакета для CKEditor5.
Я загрузил пакет в корневую директорию приложения, после чего выполнены следующие действия:
npm add file:./ckeditor5
В моем файле package.json этот пакет указан как локальный файл:
"ckeditor5-custom-build": "file:ckeditor5",
Я думаю, что этот ответ может быть полезен по теме о том, как добавить локальный пакет.
Как вывести список установленных пакетов npm?
Как узнать версию установленного npm пакета?
В чем разница между --save и --save-dev?
Где npm устанавливает пакеты?
Почему "npm install" перезаписывает package-lock.json?