Як опублікувати npm конкретну папку, але як кореневий пакет


85

У мене є проект, який включає ковтне завдання для створення та упаковки джерел та випуску в каталог із назвою dist. Моя мета - опублікувати його як пакет npm, але лише мою папку dist. Документація npm говорить, що я можу використовувати filesтег для вказівки файлів для експорту. Це працює. Але, документація також говорить, що:

Якщо ви назвете папку в масиві, вона також буде включати файли всередині цієї папки

Результатом є пакет npm, який node_modules виглядає так:

згенерований пакет npm

Але я хотів би бачити всі мої файли в корені пакета (без цієї distпапки). Мій index.jsфайл знаходиться всередині distпапки, але повинен бути в кореневій папці. Я намагався встановити тег filesяк, /dist/**/*але це не спрацювало.

Як я можу цього досягти?

Відповіді:


43

У мене таке ж бажання, але я думаю, що неможливо досягти цього лише за допомогою інструментів npm . Інший скрипт / інструмент може бути використаний для організації вашого пакету.

Альтернативне рішення

В даний час я копіюю свою package.jsonв distпапку, а потім запускаю npm packвсередині distпапки. Я думаю, що це по суті забезпечує бажане розташування нашого пакету.

Ось відповідне прочитання щодо цього дизайну npm: Чому немає Directories.lib у Node .

Цікаво також зазначити, що jspm ПОВНО поважає directories.libопцію package.jsonта переставляє файли при вирішенні пакету npm. Це все сталося для мене, тому що я хочу створити загальну бібліотеку, яку можна використовувати jspm або npm / webpack.


1
(Why no Directories.lib ...) - мертва ланка
Шанімаль

1
Чому жоден Directories.lib у Node не каже: якщо ви робите це не по-нашому, ви повинні відчувати біль. Все це створює потребу в інструментах для вирішення цієї проблеми.
Брайан Такіта

6
Я вважаю, що ця відповідь застаріла. Як зазначено у відповідях нижче, використання npm pack, package.json filesі mainполя, і .npmignoreнадає розробнику все необхідне для створення пакету з певного, що встановлюється каталогу.
Джефтопія,

1
Зробив кілька сценаріїв для впорядкування / застосування шаблону "опублікувати піддиректорію"
мінімізувати

2
Чи може хтось опублікувати рішення, як його можна досягти за допомогою npmignore, файлів та основної властивості в package.json. Я хочу перенести весь файл у корінь і не мати папки dist
Ангад

16

У мене проблема, схожа на оригінальний плакат (@robsonrosa). У моєму випадку я використовую машинопис, який компілюється в distкаталог. Хоча я міг зробити компіляцію TypeScript в кореневому каталозі, я вважаю, що найкращим рішенням є створення окремого package.jsonфайлу в каталозі dist.
Це схоже на пропозицію @scvnc копіювати, package.jsonале з поворотом:

Як частину процесу упаковки ви повинні створити package.jsonпакунок, який базується на, але відрізняється від основного package.jsonфайлу в кореневому каталозі

Обґрунтування:

  • Кореневий package.jsonфайл - це файл розробки. Він може містити сценарії або залежності від розробки, які не приносять користі користувачеві пакету, але можуть створювати для вас проблеми з безпекою. Ваша процедура упаковки може містити код, який вилучає цю інформацію з виробництва package.json.
  • Можливо, ви захочете розгорнути свій пакет в різних середовищах, які можуть вимагати різних файлів пакунків (наприклад, ви можете мати різні версії або залежності).

--- РЕДАКТУВАТИ ---

Мене попросили рішення в коментарях. Отже, ось деякий код, який я використовую. Це слід розглядати як приклад: воно не має бути загальним і стосується моїх проектів.

Моє налаштування:

package.json         - main package.json with dev dependencies and useful scripts.
.npmignore           - files to ignore; copied to 'dist' directory as part of the setup.
/src                 - directory where my typescript code resides.
/src/SetupPackage.ts - bit of code used to setup the package.
/dist                - destination directory for the compiled javascript files.

Я хочу упакувати лише distкаталог, і каталог повинен бути кореневим каталогом пакета.

Файл SetupPackage.tsу моєму srcкаталозі буде скомпільовано SetupPackage.jsв distкаталог за допомогою typecript:

import fs from "fs";

// DO NOT DELETE THIS FILE
// This file is used by build system to build a clean npm package with the compiled js files in the root of the package.
// It will not be included in the npm package.

function main() {
    const source = fs.readFileSync(__dirname + "/../package.json").toString('utf-8');
    const sourceObj = JSON.parse(source);
    sourceObj.scripts = {};
    sourceObj.devDependencies = {};
    if (sourceObj.main.startsWith("dist/")) {
        sourceObj.main = sourceObj.main.slice(5);
    }
    fs.writeFileSync(__dirname + "/package.json", Buffer.from(JSON.stringify(sourceObj, null, 2), "utf-8") );
    fs.writeFileSync(__dirname + "/version.txt", Buffer.from(sourceObj.version, "utf-8") );

    fs.copyFileSync(__dirname + "/../.npmignore", __dirname + "/.npmignore");
}

main();

Цей файл:

  • Копіює root, package.jsonале видаляє скрипти та залежності від розробника, які не потрібні в пакеті. Він також фіксує основну точку входу в пакет.
  • Записує версію пакета package.jsonу файл, який називається version.txt.
  • Копіює .npmignoreпакет з кореня.

Вміст .npmignore:

*.map
*.spec.*
SetupPackage.*
version.txt

Тобто модульні тести (файли специфікацій) і файли карт машинопису ігноруються, а також SetupPackage.jsфайл і version.txtфайл, який він створює. Це залишає чистий пакет.

Нарешті, основний package.jsonфайл має такі сценарії для використання системою складання (передбачається, що shвін використовується як оболонка).

"scripts": {
    "compile": "tsc",
    "clean": "rm -rf dist",
    "prebuildpackage": "npm run clean && npm run compile && node dist/SetupPackage.js",
    "buildpackage": "cd dist && npm pack"
  },

Для побудови пакету система збірки клонує репо, робить, npm installа потім запускає, npm run buildpackageщо в свою чергу:

  • Видаляє distкаталог, забезпечуючи чисту компіляцію.
  • Компілює код машинопису в javascript.
  • Виконує SetupPackage.jsфайл, який готується distдо упаковки.
  • cds до distкаталогу і будує там пакет.

Я використовую version.txtфайл як простий спосіб отримати версію в package.json і позначити мій репо. Існує незліченна кількість інших способів зробити це, або, можливо, ви захочете автоматично збільшити версію. Видаліть це з, SetupPackage.tsі .npmignoreякщо це вам не корисно.


Ця відповідь виглядає як найкраща, але чи є у вас готове рішення, окрім теорії?
yumaa

3
@yumaa Я відредагував свою відповідь на конкретному прикладі. Сподіваюся, це корисно.
Елі Альгранті,

13

Якщо у вашому проекті є git, ви можете використовувати невеликий хак. Додайте наступні сценарії до package.json

    "prepublishOnly": "npm run build && cp -r ./lib/* . && rm -rf ./lib",
    "postpublish": "git clean -fd",

тепер, коли ви запускаєте publishкоманду npm include prepublishOnly. Він створює файли та зберігає їх у libпапці (сценарій збірки залежить від вашого проекту). Наступна команда копіює файли в кореневу папку та видаляє lib. Після публікації postpublishсценарій повертає проект у попередній стан.


1
Я фанат цього рішення!
DanMad

6

Я настійно рекомендую вам використовувати .npmignoreзамість того, щоб переміщати або копіювати речі, особливо якщо ви використовуєте CI для розгортання, і просто додайте туди файли, які ви не хочете публікувати.

https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package

Приклад:

#tests
test
coverage

#build tools
.travis.yml
.jenkins.yml
.codeclimate.yml

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

Оновлення:

Якщо ви хочете розділити свій код на різні пакунки npm, використовуючи одне і те ж репо, я нещодавно наткнувся на цей проект: Lerna і виглядає дуже добре.

Можливо, варто поглянути


9
Нам все одно доведеться видавати наші вбудовані файли в кореневому каталозі пакета. Можливо, це допустимо для ДІ. Подивіться на допис із блогу Ісаака, на який я require('mypackage/foo')require('mypackage/dist/foo')
посилався,

Я не намагався вирішити цю проблему тут. Якщо ви хочете розділити свій код, я нещодавно наткнувся на цей проект: lernajs.io і виглядає дуже добре
Thram

Знайшов інший інструмент, на який варто подивитися :) github.com/philcockfield/msync
Thram

yeh material UI використовую це, і я використовував це в. моя остання компанія, я знайшов це нормально
нік

4

Для мене це чудово працює.

cd TMPDIR; npm pack/path/to/package.json

Tarball створить усередині каталогу TMPDIR.


^ Ця відповідь недооцінена. npm packплюс filesполе package.json (або .npmignore) працює чудово.
Джефтопія,

0

варіант 1: Перейдіть до папки та виконайте "npm публікація". команди

варіант 2: Запустити npm публікація / шлях / каталог


0

Потрібно опублікувати distпапку

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

  1. npm опублікуйте <folder> з репозиторію вашого пакета в реєстрі npm, а потім встановіть свій пакет в інший проект, як і інші пакети. У вашому випадку це було б npm publish dist.
  2. npm install <folder> в якомусь іншому проекті, якщо ви хочете використовувати свій пакет лише локально. У вашому випадку ви переходите до іншого проекту і біжитеnpm install relative/path/to/dist
  3. npm пов'язує вашу папку локально з вашим node_modulesв іншому проекті, якщо ви хочете, щоб зміни в оригінальному пакеті миттєво відображались в іншому проекті. У вашому випадку ви спочатку cd distзапускаєте, npm linkа потім переходите до іншого проекту і запускаєте npm link robsonrosa-ui-alert.

Обов’язкова умова : у будь-якому випадку вище, перед публікацією / встановленням / посиланням, ви повинні вставити у свою distпапку хоча б відповідний package.jsonфайл. У вашому випадку вам потрібно вказати ім'я пакета у файлі package.json як "name": "robsonrosa-ui-alert". Як правило, вам знадобляться також деякі інші файли, такі як README.md або LICENSE.

Приклад автоматизації

Ви можете автоматизувати процес публікації за допомогою prepareсценарію в поєднанні зі buildсценарієм. Крім того, ви можете захистити свій пакет від випадкової публікації кореневої папки пакета, "private": trueпомістивши поле в package.json, розташоване в кореневому каталозі вашого репозиторію пакета. Ось приклад:

  "private": true,
  "scripts": {
    "build": "rm -rf dist && gulp build && cat ./package.json | grep -v '\"private\":' > dist/package.json",
    "prepare": "npm run build"
  },

Таким чином, ви не опублікуєте кореневу папку і не отримаєте вбудований пакет, а пакет.json автоматично скопіюється до distпапки в процесі публікації.


-1

Ось ще один підхід, який, на мою думку, є найчистішим. Все це на основі конфігурації без необхідності переміщувати файли або вказувати шляхи у сценаріях збірки та упаковки:

package.json Вкажіть основний файл.

{
    "main": "lib/index.js",
}

Деякі додаткові параметри машинопису:

  • Вкажіть rootDir. У цьому каталозі буде весь вихідний код, і в ньому повинен бути indexфайл (або якийсь інший файл, який ви можете використовувати як основний в package.json).
  • Вкажіть outDir. Тут збиратиметься ваша команда tsc

tsconfig.json

{
    "compilerOptions": {
        "rootDir": "src",
        "outDir": "lib",
    },
    ...

}

Хіба це не те саме, що те, що спочатку було в ОП, крім зміни назви з dist на lib?
Bob9630

-3

Просто створіть .npmignoreфайл і додайте до нього наступне:

*.*
!dist/*

1
чи це робиться так, як вимагав ОП? Я не зміг змусити це працювати. Ідея полягала в тому, щоб опублікований пакет містив лише вміст каталогу каталог без включення самого каталогу. Це для того, щоб переконатися, що ми не включаємо нічого, що не є в каталозі dist, що вже можна зробити зі списку файлів package.json.
Bob9630
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.