как указать локальные модули как зависимости пакета npm

269

У меня есть приложение, которое имеет обычный набор зависимостей от сторонних модулей (например, 'express'), указанный в файле package.json под зависимостями. Например

"express"     : "3.1.1"

Я хотел бы структурировать свой собственный код по модульному принципу и установить пакет local.json для набора локальных (то есть в файловой системе, в которой я сейчас работаю) модулей. Я знаю, что могу установить локальный модуль, запустив:

npm install path/to/mymodule

Однако я не знаю, как это сделать через структуру зависимостей package.json. Использование --saveопции в этой команде просто помещает "mymodule": "0.0.0"в мой package.json (не ссылается на путь к файлу). Если я затем удаляю установленную версию из node_modules и пытаюсь переустановить ее из package.json, он завершается неудачно (потому что он ищет «mymodule» в центральном реестре и не смотрит локально).

Я уверен, что это способ сообщить "dependencies": {}структуре, что я хочу, чтобы она была установлена ​​по пути файловой системы, но не знаю как.

У кого-нибудь еще была эта проблема? Спасибо.

Сэм Адамс
источник
1
Действительно хороший вопрос. Грустно осознавать, что нет функции, эквивалентной package.jsonтому, что мы имеем в Gemfileс.
Ярл
3
возможный дубликат локальной зависимости в package.json
Келли

Ответы:

408

npm install сейчас поддерживает это

npm install --save ../path/to/mymodule

Для этого для работы mymoduleнеобходимо настроить как свой модуль package.json. См. Создание модулей NodeJS .

Начиная с npm 2.0, локальные зависимости поддерживаются изначально. Смотрите ответ danilopopeye на аналогичный вопрос . Я скопировал его ответ здесь, так как этот вопрос занимает очень высокое место в результатах веб-поиска.

Эта функция была реализована в версии 2.0.0 npm. Например:

{
  "name": "baz",
  "dependencies": {
    "bar": "file:../foo/bar"
  }
}

Любой из следующих путей также допустим:

../foo/bar
~/foo/bar
./foo/bar
/foo/bar

синхронизация обновлений

Поскольку npm installкопии mymoduleв node_modules, изменения в mymoduleисходном коде не будут автоматически видны зависимым проектом.

Есть два способа обновить зависимый проект с

  • Обновите версию mymoduleи затем используйтеnpm update : Как вы можете видеть выше, package.jsonзапись «зависимости» не содержит спецификатора версии, как вы могли бы увидеть для обычных зависимостей. Вместо этого, для локальных зависимостей, npm updateпросто пытается убедиться, что установлена последняя версия, как определено в mymodules package.json. Посмотрите ответ Крискелли на эту конкретную проблему .

  • Переустановите с помощью npm install. Это установит все, что находится в mymoduleисходном пути, даже если он более старый или имеет альтернативную ветку, что угодно.

Рэнди Дев
источник
2
Это сработало для меня. (Я просто сделал местный относительный путь, как"mymodule":"file:mymoduledir"
Дон Rhummy
72
npm install --save ../my-local-repo
Иван
15
И как это использовать в проекте? Я пытаюсь назвать это как import { HelloWorld } from "my-test-lib";, но я получаю ошибку " Не могу найти модуль". Пожалуйста, взгляните на stackoverflow.com/questions/46818083/…
Виталий Василенко
6
@LucioMollinedo Вы можете поделиться синтаксисом того, как вы импортировали локальный модуль? Как и в случае с Виталлием, я получаю сообщение об ошибке «Не удается выполнить модуль»import { HelloWorld } from "my-test-lib";
Стэн Джеймс,
7
Это не работает так же, как ссылка на пакет, поскольку зависимости не будут установлены в проект
Glass Cannon
44

Смотрите: Локальная зависимость в package.json

Похоже, ответ npm link: https://docs.npmjs.com/cli/link

jasoncrawford
источник
5
на самом деле ссылка npm создаст только символические ссылки и не изменит package.json для добавления локальной зависимости
Себастьен Х.
1
Но если это не так, symlinkкак родительский проект узнает, что нужно перестроить, как только закончится построение зависимости?
Джейми Хатбер
11

Я не смог найти аккуратный путь в конце, поэтому я пошел для создания каталога с именем, local_modulesа затем добавил этот bashscript в package.json в scripts-> preinstall

#!/bin/sh
for i in $(find ./local_modules -type d -maxdepth 1) ; do
    packageJson="${i}/package.json"
    if [ -f "${packageJson}" ]; then
        echo "installing ${i}..."
        npm install "${i}"
    fi
done
Сэм Адамс
источник
5

После долгих попыток с npm linkкомандой (предлагаемое решение для разработки локальных модулей без публикации их в реестре или сохранения отдельной копии в папке node_modules) я создал небольшой модуль npm, чтобы помочь с этой проблемой.

Исправление требует двух простых шагов .

Первый:

npm install lib-manager --save-dev

Во-вторых, добавьте это к себе package.json:

{  
  "name": "yourModuleName",  
  // ...
  "scripts": {
    "postinstall": "./node_modules/.bin/local-link"
  }
}

Более подробная информация на https://www.npmjs.com/package/lib-manager . Надеюсь, это кому-нибудь поможет.

Анураг Датта
источник
0

Если допустимо просто опубликовать ваши модули, предварительно установленные в node_modules вместе с другими вашими файлами, вы можете сделать это следующим образом:

// ./node_modules/foo/package.json
{ 
  "name":"foo",
  "version":"0.0.1",
  "main":"index.js"
}

// ./package.json
...
"dependencies": {
  "foo":"0.0.1",
  "bar":"*"
}

// ./app.js
var foo = require('foo');

Вы также можете сохранить свой модуль в git и указать вашему родительскому package.json установить зависимость от git: https://npmjs.org/doc/json.html#Git-URLs-as-Dependencies

Платон
источник
5
К сожалению, это может включать в себя node_modules, в которых мои локальные модули и сторонние модули / модули установлены из реестра (например, connect) в одном каталоге. Помимо того, что сбивать с толку с точки зрения Git / VCS (то есть придется игнорировать все в node_modules, кроме тех, которые я создал), это также плохая практика (те, которые я написал и не опубликовал, должны храниться отдельно от тех, которые другие написали и опубликовали ).
Сэм Адамс
Когда я добавляю локальный модуль, то делаю изменения, которые не видны моему основному приложению. Почему это так?
Марк Тайерс