Как npm опубликовать определенную папку, но как корень пакета


86

У меня есть проект, который включает задачу gulp для сборки и упаковки исходников и выпуска в каталог с именем dist. Моя цель - опубликовать его как пакет npm, но только мою папку dist. В документации npm сказано, что я могу использовать filesтег для указания файлов для экспорта. Оно работает. Но в документации также говорится, что:

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

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

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

Но я бы хотел видеть все свои файлы в корне пакета (без этой distпапки). Мой index.jsфайл находится внутри distпапки, но должен находиться в корневом каталоге. Я пытался установить тег filesкак, /dist/**/*но это не сработало.

Как я могу этого добиться?

Ответы:


44

У меня такое же желание, но я думаю, что невозможно добиться этого, используя только инструменты npm . Другой скрипт / инструмент можно использовать для упорядочивания вашего пакета.

Альтернативное решение

В настоящее время я копирую свой package.jsonфайл в distпапку, а затем работаю npm packвнутри distпапки. Думаю, это по сути обеспечивает желаемое расположение нашего пакета.

Вот несколько важных статей об этом дизайне npm: Почему нет Directories.lib в Node .

Также интересно отметить, что jspm ДЕЙСТВИТЕЛЬНО соблюдает этот directories.libпараметр package.jsonи переупорядочивает файлы при разрешении пакета npm. Все это произошло для меня, потому что я хочу создать общую библиотеку, которая может использоваться jspm или npm / webpack.


1
(Почему нет Directories.lib ...) - мертвая ссылка
Шанимал

1
Почему ни один Directories.lib в Node не говорит, что если вы не сделаете это по-нашему, вы должны почувствовать боль. Все это создает потребность в инструментах для решения этой проблемы.
Brian

6
Я считаю, что этот ответ устарел. Как npm packуказано в ответах ниже, при использовании package.json filesи mainfields .npmignoreразработчик получает все необходимое для создания пакета из определенного устанавливаемого каталога.
Джеффтопия

1
Сделал несколько скриптов для оптимизации / принудительного применения шаблона «
Publish

2
Может ли кто-нибудь опубликовать решение, как этого можно достичь, используя npmignore, files и main свойство в package.json. Я хочу переместить все файлы в корень и не иметь папку dist
Angad

16

У меня проблема, похожая на исходный плакат (@robsonrosa). В моем случае я использую typecript, который компилируется в distкаталог. Хотя я мог бы скомпилировать машинописный текст в корневой каталог, я думаю, что лучшим решением будет создать отдельный 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каталог с помощью машинописного текста:

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();

Этот файл:

  • Копирует корень, 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
Нам все равно придется выпускать наши встроенные файлы в корневой каталог пакета. Возможно допустимо для CI. Просмотрите сообщение из блога Исаака, на которое я require('mypackage/foo')require('mypackage/dist/foo')
указал,

Я не пытался здесь решить эту проблему. Если вы хотите разделить свой код, я недавно столкнулся с этим проектом: lernajs.io и выглядит действительно хорошо
Thram

Нашел еще один инструмент, на который стоит взглянуть :) github.com/philcockfield/msync
Thram

да, материальный интерфейс использует это, и я использовал это в моей последней компании, я нашел это нормально
ник

5

У меня это отлично работает.

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

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


^ Этот ответ недооценен. npm packплюс filesполе package.json (или .npmignore) прекрасно работает.
Джеффтопия

1

Вам нужно опубликовать 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"
  },

Таким образом, вы не будете публиковать корневую папку и автоматически создавать пакет и копировать package.json в distпапку в процессе публикации.


0

Вариант 1. Перейдите в папку и выполните команду npm publish. команда

вариант 2: запустить npm publish / path / directory


-1

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

package.json Укажите основной файл.

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

Некоторые дополнительные параметры машинописного текста:

  • Укажите rootDir. В этом каталоге будет весь исходный код и должен бытьindex файл (или какой-либо другой файл, который вы можете использовать в качестве основного вpackage.json ).
  • Укажите outDir. Здесь ваша команда tsc будет создавать

tsconfig.json

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

}

Разве это не то же самое, что изначально было у OP, за исключением изменения имени с dist на lib?
Bob9630 03

-3

Просто создайте .npmignoreфайл и добавьте в него следующее:

*.*
!dist/*

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