Я собирался опубликовать модуль в NPM, когда подумал о том, чтобы переписать его на ES6, чтобы сделать его перспективным и изучить ES6. Я использовал Babel для переноса на ES5 и запуска тестов. Но я не знаю, что делать дальше:
- Могу ли я транспилировать и публиковать полученную папку в NPM?
- Могу ли я включить папку результатов в репозиторий Github?
- Или я могу поддерживать 2 репозитория, один с кодом ES6 + скрипт gulp для Github, а другой с переданными результатами + тестами для NPM?
Вкратце: какие шаги мне нужно предпринять, чтобы опубликовать модуль, написанный на ES6, в NPM, при этом позволяя людям просматривать / разветвлять исходный код?
javascript
node.js
npm
ecmascript-6
babeljs
Путешественник Tech Guy
источник
источник
Ответы:
Шаблон, который я видел до сих пор, заключается в том, чтобы хранить файлы es6 в
src
каталоге и создавать свои материалы в предварительной публикации npm вlib
каталоге.Вам понадобится файл .npmignore, похожий на .gitignore, но игнорирующий
src
вместоlib
.источник
./node_modules/babel-cli/bin/babel.js -s inline -d lib -w src
. Это должно гарантировать, что установка не завершится ошибкой при развертывании в новых средах..npmignore
вы можете использоватьfiles
поле в package.json . Он позволяет вам точно указать файлы, которые вы хотите опубликовать, вместо того, чтобы искать случайные файлы, которые вы не хотите публиковать.Мне нравится ответ Хосе. Я уже заметил, что несколько модулей следуют этому шаблону. Вот как вы можете легко реализовать это с помощью Babel6. Я устанавливаю
babel-cli
локально, чтобы сборка не сломалась, если я когда-нибудь изменю свою глобальную версию babel..npmignore
.gitignore
/lib/ /node_modules/
Установить Babel
package.json
{ "main": "lib/index.js", "scripts": { "prepublish": "babel src --out-dir lib" }, "babel": { "presets": ["es2015"] } }
источник
scripts
былиnode_modules/.bin
добавлены любые команды в воле,$PATH
и, посколькуbabel-cli
устанавливает двоичный файлnode_modules/.bin/babel
, нет необходимости ссылаться на команду по пути.prepublish
это проблематично, потому что он может работать во время установки ( github.com/npm/npm/issues/3059 ), предпочитайте более идиоматическийversion
скриптовый перехватчик ( docs.npmjs.com/cli/version )prepublish
все еще существует. На данный момент я думаю, что вручную скомпилируйтеsrc
каталог, иnpm publish
это путь.prepublishOnly
перехватчик сценария (см. Docs.npmjs.com/misc/scripts#prepublish-and-prepare ). Обратите внимание, что в версии 5 npm это должно работать, как ожидалось, но пока (при условии, что вы используете npm v4 +) это должно работать.prepublish
запускается доpublish
(obv.), Который отправляет данные в npm (или куда вы настраиваете). Так что это для создания того, что входит в пакет NPM, даже если он не зарегистрирован.TL; DR - Не до ~ октября 2019 года Node.js модули Team не спросил :
Обновление за май 2019 г.
С 2015 года, когда был задан этот вопрос, поддержка модулей JavaScript значительно выросла и, надеюсь, станет официально стабильной в октябре 2019 года. Все остальные ответы теперь устарели или чрезмерно сложны. Вот текущая ситуация и лучшие практики.
Поддержка ES6
99% ES6 (также известный как 2015) поддерживаются Node с версии 6 . Текущая версия Node - 12. Все вечнозеленые браузеры поддерживают подавляющее большинство функций ES6. ECMAScript сейчас находится в версии 2019 , а схема управления версиями теперь поддерживает использование лет.
Модули ES (также известные как модули ECMAScript) в браузерах
Все вечнозеленые браузеры были поддерживать
import
-ную модули ES6 поскольку 2017. Динамические импорта будут поддерживаться с помощью Chrome (+ вилы , как Opera и Samsung Интернет) и Safari. Поддержка Firefox намечена на следующую версию, 67.Вам больше не нужно Webpack / rollup / Parcel и т. Д. Для загрузки модулей. Они могут быть полезны для других целей, но не требуются для загрузки вашего кода. Вы можете напрямую импортировать URL-адреса, указывающие на код модулей ES.
Модули ES в Node
Модули ES (
.mjs
файлы сimport
/export
) поддерживаются с Node v8.5.0 путем вызоваnode
с--experimental-modules
флагом. Node v12, выпущенный в апреле 2019 года, переписал поддержку экспериментальных модулей. Наиболее заметным изменением является то, что расширение файла необходимо указывать по умолчанию при импорте:// lib.mjs export const hello = 'Hello world!'; // index.mjs: import { hello } from './lib.mjs'; console.log(hello);
Обратите внимание на обязательные
.mjs
расширения повсюду. Беги как:В выпуске Node 12 команда Modules попросила разработчиков не публиковать пакеты модулей ES, предназначенные для использования Node.js, до тех пор, пока не будет найдено решение для использования пакетов через
require('pkg')
иimport 'pkg'
. Вы по-прежнему можете публиковать собственные модули ES, предназначенные для браузеров.Экосистемная поддержка собственных модулей ES
По состоянию на май 2019 года экосистемная поддержка модулей ES еще не развита. Например, такие тестовые среды, как Jest и Ava , не поддерживают
--experimental-modules
. Вам нужно использовать транспилятор, а затем выбрать между использованием именованногоimport { symbol }
синтаксиса import ( ) (который пока не работает с большинством пакетов npm) и синтаксиса импорта по умолчанию (import Package from 'package'
), который работает, но не тогда, когда Babel его анализирует для пакетов, созданных на TypeScript (graphql-tools, node-influenx, faast и т. д.). Однако существует обходной путь, который работает как с, так--experimental-modules
и если Babel транспилирует ваш код, чтобы вы могли протестировать его с помощью Jest / Ava / Mocha и т. д .:import * as ApolloServerM from 'apollo-server'; const ApolloServer = ApolloServerM.default || ApolloServerM;
Возможно, некрасиво, но таким образом вы можете написать свой собственный код модулей ES с
import
/export
и запускать егоnode --experimental-modules
без транспиляторов. Если у вас есть зависимости, которые еще не готовы к ESM, импортируйте их, как указано выше, и вы сможете использовать тестовые среды и другие инструменты через Babel.Предыдущий ответ на вопрос - помните, не делайте этого, пока Node не решит проблему require / import, надеюсь, примерно в октябре 2019 года.
Публикация модулей ES6 в npm с обратной совместимостью
Для того, чтобы опубликовать модуль ES в npmjs.org так , что он может быть импортирован непосредственно, без Бабеля и других transpilers, просто указать
main
поле вpackage.json
в.mjs
файл, но опустить расширение:{ "name": "mjs-example", "main": "index" }
Это единственное изменение. Если опустить расширение, Node будет сначала искать файл mjs при запуске с --experimental-modules. В противном случае он вернется к файлу .js, поэтому ваш существующий процесс транспиляции для поддержки более старых версий Node будет работать, как и раньше - просто убедитесь, что указали Babel на
.mjs
файл (ы).Вот исходный код для собственного модуля ES с обратной совместимостью для Node <8.5.0, который я опубликовал в NPM. Вы можете использовать его прямо сейчас, без Babel или чего-либо еще.
Установите модуль:
Создайте тестовый файл test.mjs :
import { localISOdt } from 'local-iso-dt/index.mjs'; console.log(localISOdt(), 'Starting job...');
Запустите узел (v8.5.0 +) с флагом --experimental-modules:
Машинопись
Если вы разрабатываете на TypeScript, вы можете сгенерировать код ES6 и использовать модули ES6:
Затем вам нужно переименовать
*.js
вывод в.mjs
известную проблему, которая, надеюсь, скоро будет исправлена, чтобыtsc
можно было.mjs
напрямую выводить файлы.источник
mjs
файлы. Node.js планирует развернуть официальную поддержку в октябре 2019 года, что является первым делом, на которое я бы серьезно вернулся.@ Хосе прав. Нет ничего плохого в публикации ES6 / ES2015 в NPM, но это может вызвать проблемы, особенно если человек, использующий ваш пакет, использует, например, Webpack, потому что обычно люди игнорируют
node_modules
папку во время предварительной обработки изbabel
соображений производительности.Таким образом, просто использовать
gulp
,grunt
или просто Node.js построитьlib
папку, ES5.Вот мой
build-lib.js
сценарий, который я храню./tools/
(нетgulp
илиgrunt
здесь):var rimraf = require('rimraf-promise'); var colors = require('colors'); var exec = require('child-process-promise').exec; console.log('building lib'.green); rimraf('./lib') .then(function (error) { let babelCli = 'babel --optional es7.objectRestSpread ./src --out-dir ./lib'; return exec(babelCli).fail(function (error) { console.log(colors.red(error)) }); }).then(() => console.log('lib built'.green));
И последний совет: вам нужно добавить в свой проект .npmignore . Если
npm publish
этот файл не найден, он будет использовать.gitignore
вместо него, что вызовет у вас проблемы, потому что обычно ваш.gitignore
файл будет исключать./lib
и включать./src
, что в точности противоположно тому, что вы хотите при публикации в NPM..npmignore
Файл имеет в основном один и тот же синтаксис.gitignore
(AFAIK).источник
.npmignore
вы можете использоватьfiles
поле в package.json . Он позволяет вам точно указать файлы, которые вы хотите опубликовать, вместо того, чтобы искать случайные файлы, которые вы не хотите публиковать..npmignore
, попробуйтеpackage.json
«ыfiles
вместо этого, см: github.com/c-hive/guides/blob/master/js/...Следуя подходу Хосе и Мариуса (с обновлением последней версии Babel в 2019 году): храните последние файлы JavaScript в каталоге src и выполняйте сборку с помощью npm
prepublish
сценария и выводите в каталог lib..npmignore
.gitignore
Установите Babel (в моем случае версия 7.5.5)
package.json
{ "name": "latest-js-to-npm", "version": "1.0.0", "description": "Keep the latest JavaScript files in a src directory and build with npm's prepublish script and output to the lib directory.", "main": "lib/index.js", "scripts": { "prepublish": "babel src -d lib" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/cli": "^7.5.5", "@babel/core": "^7.5.5", "@babel/preset-env": "^7.5.5" }, "babel": { "presets": [ "@babel/preset-env" ] } }
И у меня есть
src/index.js
функция стрелки:"use strict"; let NewOneWithParameters = (a, b) => { console.log(a + b); // 30 }; NewOneWithParameters(10, 20);
Вот репо на GitHub .
Теперь вы можете опубликовать пакет:
$ npm publish ... > latest-js-to-npm@1.0.0 prepublish . > babel src -d lib Successfully compiled 1 file with Babel. ...
Перед публикацией пакета в npm вы увидите, что
lib/index.js
он был сгенерирован и передан в es5:"use strict"; var NewOneWithParameters = function NewOneWithParameters(a, b) { console.log(a + b); // 30 }; NewOneWithParameters(10, 20);
[Обновление для сборщика накопительных пакетов]
На вопрос @kyw, как бы вы интегрировали пакет Rollup?
Сначала установите
rollup
иrollup-plugin-babel
Во-вторых, создайте
rollup.config.js
в корневом каталоге проектаimport babel from "rollup-plugin-babel"; export default { input: "./src/index.js", output: { file: "./lib/index.js", format: "cjs", name: "bundle" }, plugins: [ babel({ exclude: "node_modules/**" }) ] };
Наконец, обновите
prepublish
вpackage.json
{ ... "scripts": { "prepublish": "rollup -c" }, ... }
Теперь вы можете запустить
npm publish
, и перед публикацией пакета в npm вы увидите, что был сгенерирован lib / index.js, который переносится в es5:'use strict'; var NewOneWithParameters = function NewOneWithParameters(a, b) { console.log(a + b); // 30 }; NewOneWithParameters(10, 20);
Примечание: кстати, вам больше не нужно,
@babel/cli
если вы используете пакет Rollup. Вы можете безопасно удалить его:источник
Если вы хотите увидеть это в действии в очень простом небольшом модуле Node с открытым исходным кодом, взгляните на nth-day (который я начал, а также другие участники). Посмотрите файл package.json и этап предварительной публикации, который приведет вас к тому, где и как это сделать. Если вы клонируете этот модуль, вы можете запустить его локально и использовать в качестве шаблона для себя.
источник
Node.js 13.2.0+ поддерживает ESM без экспериментального флага, и есть несколько вариантов публикации гибридных (ESM и CommonJS) пакетов NPM (в зависимости от необходимого уровня обратной совместимости): https://2ality.com/2019 /10/hybrid-npm-packages.html
Я рекомендую использовать полную обратную совместимость, чтобы упростить использование вашего пакета. Это могло выглядеть так:
В гибридном пакете есть следующие файлы:
mypkg/package.json
{ "type": "module", "main": "./commonjs/entry.js", "exports": { "./esm": "./esm/entry.js" }, "module": "./esm/entry.js", ··· } mypkg/commonjs/package.json { "type": "commonjs" }
Импорт из CommonJS:
const {x} = require('mypkg');
Импорт из ESM:
import {x} from 'mypkg/esm';
Мы провели расследование поддержки ESM в 05.2019 и обнаружили, что многим библиотекам не хватает поддержки (отсюда и рекомендация по обратной совместимости):
.mjs
файловmocha@7.0.0-esm1
.mjs
файлами:источник
Два критерия NPM-пакета заключаются в том, что его можно использовать только с a
require( 'package' )
и делать что-то похожее на программное обеспечение.Если вы выполните эти два требования, вы сможете делать все, что захотите. Даже если модуль написан на ES6, если конечному пользователю это не нужно знать, я бы сейчас перенес его, чтобы получить максимальную поддержку.
Однако, если нравится Коа , ваш модуль требует совместимости с пользователями, использующими функции ES6, возможно, решение из двух пакетов будет лучшей идеей.
Вынос
require( 'your-package' )
работы.источник
require( 'package' )
работы. Я отредактирую свой ответ, чтобы прояснить это. Тем не менее, ответ Хосе намного лучше моего собственного.Главный ключ
package.json
определяет точку входа в пакет после его публикации. Таким образом, вы можете разместить свой вывод Babel где угодно, и просто нужно указать правильный путь вmain
ключе."main": "./lib/index.js",
Вот хорошо написанная статья о том, как опубликовать пакет npm
https://codeburst.io/publish-your-own-npm-package-ff918698d450
Вот образец репо, который вы можете использовать для справки
https://github.com/flexdinesh/npm-module-boilerplate
источник
import
возможность напрямую, без использования Babel или каких-либо других транспиляторов.В зависимости от анатомии вашего модуля это решение может не работать, но если ваш модуль содержится внутри одного файла и не имеет зависимостей (не использует импорт ), используя следующий шаблон, вы можете выпустить свой код как есть , и его можно будет импортировать с помощью импорта (модули браузера ES6) и при необходимости (модули Node CommonJS)
В качестве бонуса его можно будет импортировать с использованием HTML-элемента SCRIPT.
main.js :
(function(){ 'use strict'; const myModule = { helloWorld : function(){ console.log('Hello World!' )} }; // if running in NODE export module using NODEJS syntax if(typeof module !== 'undefined') module.exports = myModule ; // if running in Browser, set as a global variable. else window.myModule = myModule ; })()
мой-модуль.js :
// import main.js (it will declare your Object in the global scope) import './main.js'; // get a copy of your module object reference let _myModule = window.myModule; // delete the the reference from the global object delete window.myModule; // export it! export {_myModule as myModule};
package.json : `
{ "name" : "my-module", // set module name "main": "main.js", // set entry point /* ...other package.json stuff here */ }
Чтобы использовать свой модуль, теперь вы можете использовать обычный синтаксис ...
При импорте в NODE ...
let myModule = require('my-module'); myModule.helloWorld(); // outputs 'Hello World!'
При импорте в БРАУЗЕР ...
import {myModule} from './my-module.js'; myModule.helloWorld(); // outputs 'Hello World!'
Или даже при включении с использованием элемента сценария HTML ...
<script src="./main.js"></script> <script> myModule.helloWorld(); // outputs 'Hello World!' </script>
источник
Несколько дополнительных замечаний для всех, кто использует собственные модули прямо из github, не просматривая опубликованные модули:
( Широко используемый ) хук "предварительной публикации" ничего не делает для вас.
Лучшее, что можно сделать (если вы планируете полагаться на репозитории github, а не на опубликованные материалы):
src
из списка .npmignore (другими словами: разрешить). Если у вас его нет.npmignore
, помните:.gitignore
вместо этого в установленном месте будет использоваться копия , какls node_modules/yourProject
вы увидите.babel-cli
это зависимость в вашем модуле, а не только devDepenceny, поскольку вы действительно строите на потребляющей машине, известной как компьютер разработчиков приложений, который использует ваш модульвыполните сборку в ловушке установки, т.е.
"install": "babel src -d lib -s"
(ничего не стоит пробовать что-то "предустановленное", т.е. может отсутствовать babel-cli)
источник
npm pack
вывода, 3) проверять вывод сборки.