Необов’язкові залежності в npm?


23

У мене подібне питання до цього , але не зовсім те саме.

Я хотів би, щоб користувач мого додатка встановив його, незалежно від необхідності залежно від способу його використання. Так, наприклад, якщо вони хочуть зберігати MongoDB, тоді будуть встановлені лише бібліотеки, пов’язані з монго, але якщо вони захочуть зберігатись у Redis, тоді будуть встановлені лише бібліотеки, пов’язані з Redis. Я не хочу змушувати їх завантажувати та встановлювати бібліотеки, які вони не використовуватимуть.

Я знаю, що можу це зробити з метою розвитку devDependencies, але це йде далеко від цього. Як йдеться у відповіді на запитання вище, це більш тісно пов'язане setuptools extras_requireз leiningenпрофілями Python та Clojure . Що-небудь подібне в npm? Мені справді здається, що це devDependenciesмає бути devпрофілем більш універсального способу визначення залежностей.


Лише думка, але ви можете піти з декількома пакетами. MyPackage-Core MyPackage-Db-Mongo MyPackage-Db-Redisі т. д. ... набагато, як люди роблять модулі підключення, призначені для розширення кутових .
Майк

@Mike: Хм, спасибі, я подумаю. Я все ще думаю, що це обмеження package.json, яке було вирішено в інших менеджерів пакетів.
іммірік

1
Це чудове питання, але я думаю, що це поза темою, оскільки мова йде про використання якогось інструменту. Такі питання є тематичними лише в тому випадку, якщо вони висвітлюють, як інструмент інтегрується в якийсь процес розробки - зрештою, цей сайт стосується програмної інженерії. Детальну інформацію див. У нашому довідковому центрі . Будь ласка, прочитайте: Куди йде моє запитання щодо інструмента? Використання інструментів розробки, таких як NPM, буде на тему Stack Overflow.
амон

Відповіді:


9

Модуль залежності залежності може бути тим, що ви шукаєте, або все, що робить щось подібне до:

  • оголосити необов'язкові залежності package.json, які не встановлюються автоматично npm install, скажімоoptionalPeerDependencies
  • requireфункція користувальницького стилю, яка знає optionalPeerDependenciesі робить правильно, включаючи метання / попередження, коли нічого не знайдено, що б відповідало необхідному класу модулів (наприклад, не встановлено ні redis, ні mongo, ні mysqlтощо).
  • задокументувати сподівання, що споживачі цього модуля встановлять принаймні 1 з необов'язкових однорангових модулів

Одне з варіантів було б, якщо основна функціональність модуля працює без будь-яких необов'язкових залежностей (наприклад, шаблон плагіну), без помилок / попередження, коли нічого не знайдено, що б відповідало рівню рівнів.

Інший варіант - це перелік вище, в той час як облік виробництва та залежності від розвитку, тобто аналог для dependenciesта devDependencies.

Можливо, у поєднанні із запитом на вимогу потрібні такі, що додаткові модулі потрібні ліниво, наприклад:

exports = {
    Core : require('./core'),
    get redis(){ return require('./redis'); },
    get mongo(){ return require('./mongo'); }
}

Мені це вже не потрібно було, але я думаю, що це вирішує проблему, яку я мав. Спасибі!
іммірік

2
Так, я зрозумів, що це місяці, ти, мабуть, зрозумів це чи продовжив. Я знайшов ваше запитання, шукаючи відповіді сам, тому це було переважно для нащадків. Я не раз шукав, лише щоб знайти відповідь, написаний за кілька років до цього. Тож врахуйте цей освічений власний інтерес. Також оновлено відповідь, щоб загалом описати, що codependencyмодуль надає у випадку, якщо модуль випаровується з NPM і тому, що посилання без витягів є поганою формою SO.
інструментберез

9

Якщо ви хочете прості необов'язкові залежності, такі як плагіни, наприклад, якщо ви встановите foo, ви запустите його різнокольоровим, але якщо його не встановлено, у вас немає жодних проблем і побачите його сірим кольором, тоді ви можете використовувати optionalDependecies в package.json :

{
  "name": "watchit",
  "version": "1.2.3",
  "optionalDependencies": {
    "foo": "^2.0.0"
  }
}

І в коді:

try {
  var foo = require('foo')
  var fooVersion = require('foo/package.json').version
} catch (er) {
  foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
  foo = null
}

// .. then later in your program ..

if (foo) {
  foo.doFooThings()
}

Витягнуто з документації package.json .


1

Те, що я роблю, - це налаштувати інсталяційний скрипт у своєму пакеті.json всередині scripts, як-от так:

"install": "node ./my-tools/my-install.js",

Він буде працювати відразу після npm installфінішу. Я використовую його здебільшого для автоматичного генерування .envфайлу із замовчуванням.

my-install.jsСценарій може виконувати різні команди, створювати файли, задати для введення даних користувача, так що ви могли б сказати : «Хоче Redis або Монго?»:

const exec = require('child_process').exec;
const readline = require('readline');

// Insert "Ask question script" here
// using readline core module

if ( option == 'mongo' )
  exec('npm install mongoose');

if ( option == 'redis' )
  exec('npm install redis');

Це дуже швидка відповідь, перевірити читання для правильного читання вводу користувача та дочірній процес для запуску команд та обробки результатів тощо.

Також зауважте, що сценарій встановлення може бути будь-яким бажаним (python, bash тощо)


2
Прохання про введення користувачем призведе до виправлення автоматизованих збірок. Повторне npm installзапущення всередині скрипта встановлення також може викликати ненавмисну ​​поведінку. Я не рекомендую це рішення.
Фея Ламбда

1

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

Мій пакет є install-subsetі може бути встановлений у всьому світіnpm install -g install-subset

https://www.npmjs.com/package/install-subset

По-перше, ви створюєте білі списки та чорні списки для названих підмножин встановлення у вашому пакеті.json таким чином:

"subsets": {
    "build": {
        "whitelist": [
            "babel-cli",
            "dotenv"
        ]
    },
    "test": {
        "blacklist": [
            "eslint",
            "lint-rules",
            "prettier"
        ]
    }
}

Потім подзвоніть це, наприклад, install-subset test

Це тимчасово перепише ваш package.json, щоб не встановлювати ці пакунки у чорний список, а потім відновити його, що залежно від пакетів може заощадити багато часу та пропускної здатності.

Також працює з пряжею, є відкритим кодом, і питання / піар вітаються.

У багатьох випадках я використовую це на нашому сервері ci, щоб зменшити час збирання, а для нашого останнього проекту React Native було встановлено наш типовий свіжий інсталятор від 72 секунд до приблизно 20 секунд.

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