Как разделить библиотеку и ее плагины среди пакетов npm?

#javascript #npm #webpack

#javascript #npm #webpack

Вопрос:

Я работаю над библиотекой JavaScript, и я хочу, чтобы будущие пользователи могли выбирать плагины, которые они хотят добавить в свой проект, среди основной библиотеки. У меня несколько проблем с модулями и webpack. Я пишу псевдокод, чтобы дать представление о том, как организован код.

Мой index.js для основной библиотеки выглядит следующим образом:

 import ClassA from "./classA";
import ClassB from "./classB";

export default class MyLib { 
    .....
}
export { ClassA, ClassB } 
  

Я могу легко вывести библиотеку с помощью webpack:

 output: {
     path: ...
     filename: 'mylib.min.js',
     library: "MyLib", 
     libraryTarget: "umd"
}
  

Чтобы иметь возможность выбирать, какие плагины добавлять, я создаю разные пакеты npm (по одному для каждого плагина), добавляю MyLib в качестве внешней зависимости, а затем выполняю:

 import {ClassA, ClassB} from "MyLib";


class PluginA extends ClassB {
   constructor() {
      this.test = new ClassA();
   }
}

  

Это работает отлично, но при «компиляции» PluginA webpack будет включать MyLib в конечный js-файл для PluginA. Если я захочу включить несколько плагинов, в конечном итоге в коде будет несколько копий основной библиотеки.

Моя конечная цель — организовать код таким образом, чтобы его можно было легко установить с помощью следующих команд npm, не дублируя код повсюду:

 npm install MyLib
npm install MyLib-PluginA
npm install MyLib-PluginB
  

Конечно, одним из очевидных решений было бы не использовать webpack для плагинов, но я бы хотел сохранить эту опцию в качестве последнего ресурса на случай, если больше ничего не сработает.

Спасибо!

Ответ №1:

Я бы не рекомендовал использовать webpack для создания ваших плагинов / библиотеки. Скорее, я бы позволил потребителю библиотеки выбирать свой собственный пакет. Вашим лучшим шагом для библиотеки должно быть просто преобразование (при необходимости) любого промежуточного кода, такого как JS с поддержкой babel или TypeScript, во что-то, что может быть безопасно require обработано node.

Кроме того, каждый плагин должен иметь MyLib как peerDependency вместо обычной зависимости. Это гарантирует, что MyLib это не будет вложено внутрь плагина node_modules и, таким образом, позволит избежать объединения дубликатов. Плагины могли бы дополнительно использоваться MyLib как devDependency для модульных тестов, но важно то, что это никогда не бывает обычным dependency .

Комментарии:

1. пока не уверен, стоит ли использовать просто babel вместо webpack, но предложение о peerDependecies очень важно! большое спасибо!

2. Это определенно правильный путь. В конце концов, когда вы устанавливаете зависимости вашего проекта, представьте, что некоторые из них использовали Webpack, другие — Rollup, некоторые — Parcel и т.д. Попытка настроить все это была бы кошмаром. Лучше всего просто предоставить свою библиотеку в стандартном формате (возможно, с использованием транспилятора, если вы хотите настроить таргетинг на более новую версию JS, чем стандартная) и позволить потребителю библиотек (т. Е. приложению конечного пользователя) решить, использовать Webpack или альтернативу. В конце концов, это то, что уже делает большинство других библиотек!

Ответ №2:

Покопавшись в документации webpack, я нашел решение, которое использует внешние компоненты webpack.

Из документации webpack:

Параметр конфигурации externals предоставляет способ исключения зависимостей из выходных пакетов.

Я только что добавил следующие строки в конфигурацию webpack для плагина:

 module.exports = {
    ...,
    externals: {
        mylib: { 
            commonjs: 'MyLib',
            commonjs2: 'MyLib',
            amd: 'MyLib',
            root: 'MyLib'
        }
    }
};
  

Документация Webpack:https://webpack.js.org/configuration/externals

Надеюсь, это поможет другим.