Як поділитися кодом між програмами node.js?


79

У мене є кілька додатків у вузлі, які всі мають кілька модулів, які я написав. Ці модулі недоступні через npm. Я хотів би мати можливість вільно ділитися між програмами, але я не хочу копіювати каталоги навколо і не покладатися на Git. І я не дуже люблю використовувати для цього символьні посилання.

Я хотів би влаштувати каталоги приблизно так:

app1
 server.js
 node_modules
  (public modules from npm needed for app1)
 lib
  (my own modules specific to app1)

app2
 server.js
 node_modules
  (public modules from npm needed for app2)
 lib
  (my own modules specific to app2)

shared_lib
 (my own modules that are used in both app1 and app2)

Проблема, яку я бачу, полягає в тому, що модулі в shared_lib, схоже, заплутані щодо того, де знайти модулі, які будуть в каталозі node_modules будь-якої програми, в якій вони працюють. Принаймні, я думаю, що проблема в цьому.

Отже .... який хороший спосіб зробити це, уникаючи дублікатів файлів? (зауважте, що мене не хвилюють дублікати речей у node_modules, оскільки це не мій код, я не перевіряю їх у Git тощо)

Відповіді:


23

У мене це працює, маючи папки node_modules на різних рівнях - тоді вузол автоматично переходить вгору, поки не знайде модуль.

Зверніть увагу, що вам не потрібно публікувати в npm, щоб мати модуль усередині node_modules - просто використовуйте:

"private": true

Усередині кожного вашого приватного файлу package.json - для вашого проекту я мав би таке:

app1
 server.js
 node_modules
  (public modules from npm needed for app1)
  (private modules locally needed for app1)

app2
 server.js
 node_modules
  (public modules from npm needed for app2)
  (private modules locally needed for app2)

node_modules
  (public modules from npm needed for app1 & app2)
  (private modules locally for app1 & app2)

Справа в тому, що node.js вже має механізм боротьби з цим, і це чудово. Просто поєднайте його з фокусом "приватний, а не на NPM", і ви вже готові.

Коротше a:

require('somemodule')

Від програми A або B буде каскадувати вгору, поки не знайде модуль - незалежно від того, живе він нижче або вище. Дійсно - це дозволяє вам гаряче міняти місце розташування, не змінюючи жодного з вимог (...) .

документація модуля node.js


8
Коли я спробував це, будь-які модулі, необхідні для спільних модулів, не могли бути вирішені. У вашій структурі схоже на те, що найвища папка node_modules має як приватний (перевірений у контролі джерела), так і загальнодоступний (npm install'd - не зареєстрований) модулі. Я звичайно не перевіряю загальнодоступні модулі у контролі джерел - як ви це обійшли?
Адам С

48

Документація npm рекомендує використовувати npm-link для створення власних пакетів Node.js локально, а потім зробити їх доступними для інших програм Node.js. Це простий чотириетапний процес.

Типовою процедурою буде спочатку створення пакету з наступною структурою:

  hello
  | index.js
  | package.json

Типовою реалізацією цих файлів буде:

index.js

  exports.world = function() {
     return('Hello World');
  }

package.json

  {
    "name": "hello",
    "version": "0.0.1",
    "private": true,
    "main": "index.js",
    "dependencies": {
    },
    "engines": {
    "node": "v0.6.x"
    }
  }

"private: true" гарантує, що npm відмовиться публікувати пакет. Це спосіб запобігти випадковій публікації приватних пакетів.

Далі перейдіть до кореневої папки вашого пакета Node.js і запустіть, npm linkщоб зв’язати пакет глобально, щоб його можна було використовувати в інших програмах.

Використовувати цей пакет в іншому додатку, наприклад, "hello-world", з наступною структурою каталогів:

 hello-world
 | app.js

Перейдіть до папки hello-world і запустіть:

 npm link hello

Тепер ви можете використовувати його як будь-який інший пакет npm приблизно так:

app.js

  var http = require('http');
  var hello = require('hello');

  var server = http.createServer(function(req, res) {
     res.writeHead(200);
     res.end(hello.world());
  });
  server.listen(8080);

6
Як це працює при розгортанні в середовищі PaaS, такому як Heroku або Nodejitsu?
Адам С

Посилання npm не працюватиме в середовищі PaaS. Heroku вшановує вузлові модулі, які вставляються разом із вашим кодом. Тож це може бути варіант.
almypal

1
Це те, чого я не отримую - якщо ви розгортаєте Heroku з git, ви не перевіряєте свої node_modules. Крім того, це означатиме, що ви скопіювали ваш спільний код у папку node_modules перед реєстрацією. Що здається громіздким і помилкою схильний Або мені чогось не вистачає? Дякую!
Адам С

Це здається єдиним виходом. Параметр посилання npm доступний лише у випадку, якщо у вас є доступ до віддаленого терміналу через ssh ... як у AWS або Rackspace
almypal

1
Я думаю, ви можете використовувати веб-пакет, щоб упакувати все це для цієї мети
Георгій Олейніков

4

Просто використовуйте правильний шлях у своєму дзвінку, який потрібно

Наприклад, в server.js це буде:

var moduleName = require ('../ shared_lib / moduleName / module.js');

Важливо знати, що як тільки ваш шлях має префікс '/', '../' або './', шлях відносно файлу, що викликає.

Для отримання додаткової інформації про завантаження модулів вузлів відвідайте: http://nodejs.org/docs/latest/api/modules.html


8
Але якщо я це роблю, і тоді цей модуль намагається вимагати модуль, який надходить з npm, він плутається і видає помилки.
грабувати

2
без відповіді? це тому, що ви намагалися створити щось складніше, ніж демонстрацію за допомогою Node
Toolkit

4

Так, ви можете посилатися на shared_lib з app1, але тоді у вас виникає проблема, якщо ви хочете упакувати та розгорнути app1 в якомусь іншому середовищі, наприклад, веб-сервері на AWS.

У цьому випадку вам краще встановити свої модулі в shared_lib в app1 та app2, використовуючи "npm install shared_lib / module". Він також встановить усі залежності модулів shared_lib в app1 та app2 та матиме справу з конфліктами / дублікатами.

Дивіться це: Як встановити приватний модуль NPM без власного реєстру?


2

Якщо ви перевірите документи node.js , то побачите, що Node.js розуміє файлpackage.json формат файлу, принаймні в курсорі.

В основному, якщо у вас є каталог з іменем foo, і в цьому каталозі знаходиться package.jsonфайл із парою ключ-значення:, "main": "myCode.js"тоді, якщо ви спробуєте, require("foo")і він знайде цей каталог із package.jsonфайлом усередині, він потім буде використовувати foo/myCode.jsдляfoo модуля.

Отже, якщо ви маєте структуру каталогів, якщо кожна спільна бібліотека має власний каталог із таким простим package.jsonфайлом всередині, то ваші програми можуть отримати спільні бібліотеки, виконавши:

var lib1 = require('../shared_lib/lib1');
var lib2 = require('../shared_lib/lib2');

І це повинно працювати для обох цих додатків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.