web-dev-qa-db-ja.com

ES6で記述されたモジュールをNPMに公開する方法は?

ES6でモジュールを書き直そうと考えたときに、モジュールをNPMに公開しようとしていました。それは、将来を保証し、ES6を学習するためです。 Babelを使用してES5にトランスパイルし、テストを実行しました。しかし、私はどのように進むべきかわかりません:

  1. トランスパイルし、結果の/ outフォルダーをNPMに公開しますか?
  2. 結果フォルダーをGithubリポジトリに含めますか?
  3. または、Github用のES6コード+ gulpスクリプト、およびNPM用の変換結果+テストを含む2つのリポジトリを維持しますか?

要するに、ES6で記述されたモジュールをNPMに公開するために、元のコードを閲覧/フォークできるようにするために、どのような手順を踏む必要がありますか?

117

これまでに見てきたパターンは、es6ファイルをsrcディレクトリに保存し、npmのlibディレクトリへの事前公開で作成します。

.gitignoreに似ていますが、srcの代わりにlibを無視する.npmignoreファイルが必要になります。

66

ホセの答えが好きです。いくつかのモジュールが既にそのパターンに従っていることに気付きました。 Babel6で簡単に実装する方法は次のとおりです。 babel-cliをローカルにインストールして、グローバルなbabelバージョンを変更してもビルドが壊れないようにします。

。npmignore

/src/

。gitignore

/lib/
/node_modules/

バベルのインストール

npm install --save-dev babel-core babel-cli babel-preset-es2015

package.json

{
  "main": "lib/index.js",
  "scripts": {
    "prepublish": "node_modules/babel-cli/bin/babel.js src --out-dir lib"
  },
  "babel": {
    "presets": ["es2015"]
  }
}
63

TL; DR-しないでください、2019年10月まで。Node.js モジュールチーム には 質問

[2019年10月]まで、Node.jsでの使用を目的としたESモジュールパッケージを公開しないでください。

2019年5月更新

この質問が行われた2015年以降、モジュールのJavaScriptサポートは大幅に成熟しており、2019年10月に公式に安定することが期待されています。他のすべての回答は現在廃止されているか、過度に複雑です。これが現在の状況とベストプラクティスです。

ES6サポート

ES6の99%(別名2015)はNode バージョン6以降 でサポートされています。 Nodeの現在のバージョンは12です。すべての常緑ブラウザは、ES6機能の大部分をサポートしています。 ECMAScriptは現在 バージョン2019 であり、バージョン管理スキームは現在、年を使用することを支持しています。

ブラウザのESモジュール(別名ECMAScriptモジュール)

すべての常緑ブラウザサポートimport- 2017年からES6モジュールを実行しています。 ダイナミックインポートサポート Chrome(OperaやSamsung Internetなどの+フォーク)およびSafari。 Firefoxのサポートは、次のバージョンである67で予定されています。

モジュールをロードするためにneed Webpack/rollup/Parcelなどがなくなりました。これらは他の目的にも使用できますが、コードをロードするために必要なわけではありません。 ESモジュールコードを指すURLを直接インポートできます。

NodeのESモジュール

ESモジュール(import/exportを含む.mjsファイル)は、Node v8.5.0以降、--experimental-modulesフラグでnodeを呼び出すことでサポートされています。 2019年4月にリリースされたNode v12は、実験モジュールのサポートを書き直しました。最も目に見える変更は、インポート時にデフォルトでファイル拡張子を指定する必要があることです。

// lib.mjs 

export const hello = 'Hello world!';

// index.mjs:

import { hello } from './lib.mjs';
console.log(hello);

必須の.mjs拡張に注意してください。として実行:

node --experimental-modules index.mjs

Node 12リリースは、モジュールチーム 要求 開発者が公開しない場合ESモジュールパッケージ node.jsで使用するためのものrequire('pkg')import 'pkg'の両方を介してパッケージを使用するためのソリューションが見つかるまで。ブラウザ用のネイティブESモジュールを引き続き公開できます。

ネイティブESモジュールのエコシステムサポート

2019年5月現在、ESモジュールのエコシステムサポートは未完成です。たとえば、 JestAva などのテストフレームワークは--experimental-modulesをサポートしません。トランスパイラーを使用する必要があり、名前付きインポート(import { symbol })構文(ほとんどのnpmパッケージではまだ動作しない)とデフォルトのインポート構文(import Package from 'package')のどちらを使用するかを決定する必要があります。これは動作しますが、 Babelが解析するときではありません for TypeScriptで作成されたパッケージ (graphql-tools、node-influx、faastなど)ただし、両方で動作する回避策があります--experimental-modulesを使用し、BabelがコードをトランスコンパイルしてJest/Ava/Mochaなどでテストできるようにする場合:

import * as ApolloServerM from 'apollo-server'; const ApolloServer = ApolloServerM.default || ApolloServerM;

おそらくugいですが、この方法では、import/exportで独自のESモジュールコードを記述し、トランスパイラーなしでnode --experimental-modulesで実行できます。まだESMに対応していない依存関係がある場合は、上記のようにインポートすると、Babelを介してテストフレームワークやその他のツールを使用できるようになります。


質問に対する以前の回答-Nodeがrequire/importの問題を解決するまでこれを行わないでください。できれば2019年10月頃です。

下位互換性を備えたES6モジュールのnpmへの公開

ESモジュールをnpmjs.orgに公開して、Babelや他のトランスパイラーなしで直接インポートできるようにするには、package.jsonmainフィールドを.mjsファイルにポイントしますが、拡張機能:

{
  "name": "mjs-example",
  "main": "index"
}

それが唯一の変更です。拡張機能を省略すると、Nodeは--experimental-modulesを使用して実行された場合に最初にmjsファイルを探します。そうしないと、.jsファイルにフォールバックするため、古いNodeバージョンをサポートするための既存の transpilation process は以前と同じように機能します— Babelが.mjsを指すようにしてくださいファイル。

Node <8.5.0との後方互換性を備えたネイティブESモジュールのソース NPMに公開したものです。 Babelなどを使用せずに、今すぐ使用できます。

モジュールをインストールします。

npm install local-iso-dt
# or, yarn add local-iso-dt

テストファイルを作成しますtest.mjs

import { localISOdt } from 'local-iso-dt/index.mjs';
console.log(localISOdt(), 'Starting job...');

--experimental-modulesフラグを指定してノード(v8.5.0 +)を実行します。

node --experimental-modules test.mjs

TypeScript

TypeScriptで開発する場合、ES6コードを生成し、ES6モジュールを使用できます。

tsc index.js --target es6 --modules es2015

次に、*.js出力を.mjsに名前変更する必要があります。これは、既知の issue すぐに修正されるので、tsc.mjsファイルを直接出力できます。 。

24
Dan Dascalescu

@Joseは正しい。 ES6/ES2015をNPMに公開することには何の問題もありませんが、特にパッケージを使用している人がWebpackを使用している場合、特にパフォーマンス上の理由でbabelでの前処理中にnode_modulesフォルダーを無視するため、問題が発生する可能性があります.

したがって、gulpgrunt、または単にNode.jsを使用して、ES5であるlibフォルダーを作成します。

これがbuild-lib.jsにある./tools/スクリプトです(ここにはgulpgruntもありません):

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)と同じです。

16
André Pena

これを非常に単純な小さなオープンソースNodeモジュールで実際に見たい場合は、 nth-day (私が始めた-他の貢献者も)を見てください。 package.jsonファイルと、これを行う場所と方法につながる事前公開ステップを確認します。そのモジュールのクローンを作成すると、ローカルで実行し、それをテンプレートとして使用できます。

5
Guy

package.jsonのメインキーは、パッケージが公開された後のエントリポイントを決定します。したがって、必要な場所にBabelの出力を配置し、mainキーに正しいパスを記述するだけで済みます。

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

Npmパッケージの公開方法に関するよく書かれた記事を次に示します。

https://codeburst.io/publish-your-own-npm-package-ff918698d45

参照用に使用できるサンプルリポジトリを次に示します。

https://github.com/flexdinesh/npm-module-boilerplate

3
Dinesh Pandiyan

NPMパッケージの2つの基準は、require( 'package' )のみで使用可能であり、ソフトウェアのように動作することです。

これらの2つの要件を満たせば、何でもできます。モジュールがES6で作成されている場合でも、エンドユーザーがそれを知る必要がない場合は、最大のサポートを得るために今のところそれを変換します。

ただし、 koa のように、モジュールにES6機能を使用するユーザーとの互換性が必要な場合は、おそらく2つのパッケージソリューションの方が良いでしょう。

取り除く

  1. require( 'your-package' )を機能させるために必要なコードだけを公開してください。
  2. ES5と6の間がユーザーにとって重要でない限り、1つのパッケージのみを公開します。必要な場合はトランスパイルします。
3
JoshWillik

モジュールの構造に依存しているため、このソリューションは機能しない場合がありますが、モジュールが単一のファイル内に含まれ、依存関係がないimportを使用しない場合) )、次のパターンを使用すると、コードをそのままリリースでき、import(Browser ES6 Modules)およびrequire(Node CommonJS Modules)でインポートできます

おまけとして、SCRIPT HTML要素を使用してインポートするのが適切です。

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

my-module.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!'

BROWSER ...にインポートした場合.

    import {myModule} from './my-module.js';
    myModule.helloWorld();
    // outputs 'Hello World!'

または、HTMLスクリプト要素 ...を使用して含まれている場合でも.

<script src="./main.js"></script>
<script>
     myModule.helloWorld();
    // outputs 'Hello World!'
</script>
0
colxi

ホセとマリウスのアプローチに従って(2019年にバベルの最新バージョンを更新):最新のJavaScriptファイルをsrcディレクトリに保持し、npmのprepublishスクリプトを使用してビルドし、libディレクトリに出力します。

。npmignore

/src

。gitignore

/lib
/node_modules

バベルをインストール(私の場合はバージョン7.5.5)

$ npm install @babel/core @babel/cli @babel/preset-env --save-dev

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
...
> [email protected] 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);
0
Yuci