[javascript] ES6로 작성된 모듈을 NPM에 게시하는 방법은 무엇입니까?

ES6에서 모듈을 다시 작성하고 미래를 보장하고 ES6을 배우기 위해 NPM에 모듈을 게시하려고했습니다. 나는 Babel을 사용하여 ES5로 변환하고 테스트를 실행했습니다. 그러나 진행 방법을 잘 모르겠습니다.

  1. 결과 / out 폴더를 변환하고 NPM에 게시합니까?
  2. Github 저장소에 결과 폴더를 포함합니까?
  3. 아니면 Github의 ES6 코드 + 꿀꺽 거리는 스크립트와 NPM에 대한 변환 된 결과 + 테스트가있는 2 개의 저장소를 유지합니까?

한마디로 : ES6로 작성된 모듈을 NPM에 게시하고 사람들이 원래 코드를 탐색 / 포크 할 수 있도록하려면 어떤 단계를 수행해야합니까?



답변

지금까지 본 패턴은 es6 파일을 src디렉토리 에 유지하고 npm의 사전 게시 디렉토리에 물건을 빌드하는 것입니다 lib.

.gitignore와 유사하지만 src대신 무시하는 .npmignore 파일이 필요합니다 lib.


답변

나는 José의 답변을 좋아한다. 여러 모듈이 이미 해당 패턴을 따르는 것으로 나타났습니다. 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": "babel src --out-dir lib"
  },
  "babel": {
    "presets": ["es2015"]
  }
}


답변

TL; DR -2019 년 10 월까지는하지 마십시오. Node.js 모듈 팀다음과 같이 요청했습니다 .

[2019 년 10 월]까지 Node.js에서 사용하도록 의도 된 ES 모듈 패키지를 게시하지 마십시오

2019 년 5 월 업데이트

이 질문이 제기 된 2015 년 이래 모듈에 대한 JavaScript 지원이 크게 발전했으며 2019 년 10 월 공식적으로 안정적으로 유지 될 것입니다. 다른 모든 답변은 이제 더 이상 사용되지 않거나 지나치게 복잡합니다. 현재 상황과 모범 사례는 다음과 같습니다.

ES6 지원

ES6 (일명 2015)의 99 %가 버전 6 이후 Node에서 지원되었습니다 . 현재 버전의 Node는 12입니다. 모든 Evergreen 브라우저는 대다수의 ES6 기능을 지원합니다. ECMAScript는 현재 2019 버전 이며 버전 체계는 이제 수년을 선호합니다.

브라우저의 ES 모듈 (일명 ECMAScript 모듈)

모든 상록 브라우저지원 import 2017 년부터 -ing ES6 모듈을 동적 수입이 되는 지원 크롬에서 사파리 (오페라와 삼성 인터넷과 같은 + 포크). Firefox 지원은 다음 버전 인 67로 예정되어 있습니다.

더 이상 모듈을로드하기 위해 Webpack / rollup / Parcel 등이 필요 하지 않습니다 . 그것들은 다른 목적으로 여전히 유용 할 수 있지만 코드를로드 할 필요는 없습니다. ES 모듈 코드를 가리키는 URL을 직접 가져올 수 있습니다.

노드의 ES 모듈

ES 모듈 ( /가있는 .mjs파일 )은 플래그 로 호출 하여 Node v8.5.0부터 지원되었습니다 . 2019 년 4 월에 릴리스 된 Node v12는 실험 모듈 지원을 다시 작성했습니다. 가장 눈에 띄는 변경 사항은 가져올 때 파일 확장자를 기본적으로 지정해야한다는 것입니다.importexportnode--experimental-modules

// 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 릴리스는 모듈 팀 개발자에게 와 를 통해 패키지를 사용하는 솔루션을 찾을 때까지 Node.js에서 사용할 ES 모듈 패키지를 게시하지 않도록 요청한 경우 입니다. 브라우저 용 네이티브 ES 모듈을 계속 게시 할 수 있습니다.require('pkg')import 'pkg'

기본 ES 모듈의 생태계 지원

2019 년 5 월 현재 ES 모듈에 대한 에코 시스템 지원이 미숙합니다. 예를 들어 JestAva 와 같은 테스트 프레임 워크 는을 지원하지 않습니다 --experimental-modules. 트랜스 파일러를 사용해야하고 이름이 지정된 import ( import { symbol }) 구문 (대부분의 npm 패키지에서는 아직 작동하지 않음)과 기본 import 구문 ( import Package from 'package') 중 작동하지만 Babel이 구문 분석 할 때는 사용하지 않아야합니다. 대한 패키지 타이프로 작성 (graphql-도구, 노드 유입, FAAST 등)을 모두 작동하는 해결 방법 그러나이 --experimental-modules와 바벨 코드를 transpiles 경우에 당신이 농담 / 아바 / 모카 등로를 테스트 할 수 있도록이 :

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

아마도 추악하지만,이 방법으로 import/를 사용 하여 자체 ES 모듈 코드를 작성하고 코드 변환기없이 코드를 export실행할 수 node --experimental-modules있습니다. 아직 ESM을 지원하지 않는 종속성이있는 경우 위와 같이 가져 오면 Babel을 통해 테스트 프레임 워크 및 기타 툴링을 사용할 수 있습니다.


질문에 대한 이전 답변-Node가 2019 년 10 월 경에 require / import 문제를 해결할 때까지이 작업을 수행하지 마십시오.

이전 버전과의 호환성으로 ES6 모듈을 npm에 게시

이 바벨 또는 다른 transpilers하지 않고 직접 수입 할 수 있도록 npmjs.org에 ES 모듈을 게시하려면 포인트 main당신의 필드를 package.json받는 .mjs파일 만 확장자를 생략 :

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

그게 유일한 변화입니다. 확장을 생략하면 –experimental-modules와 함께 실행되는 경우 Node는 먼저 mjs 파일을 찾습니다. 그렇지 않으면 .js 파일로 대체 되므로 이전 노드 버전을 지원 하는 기존 변환 프로세스 가 이전과 같이 작동합니다. Babel이 .mjs파일 을 가리 키도록하십시오 .

다음은 NPM에 게시 한 Node <8.5.0과 호환되는 기본 ES 모듈소스입니다 . 바벨이나 다른 어떤 것도없이 바로 사용할 수 있습니다.

모듈을 설치하십시오 :

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. 알려진 문제 는 곧 해결 될 것이므로 파일을 직접 tsc출력 할 수 .mjs있습니다.


답변

@Jose가 맞습니다. ES6 / ES2015를 NPM에 게시하는 데 아무런 문제가 없지만 특히 패키지를 사용하는 사람이 Webpack을 사용하는 경우 문제가 발생할 수 있습니다. 예를 들어 일반적으로 사람들 은 성능상의 이유로 node_modules전처리하는 동안 폴더를 무시하기 babel때문입니다.

그래서, 그냥 사용 gulp, grunt구축 단순히 Node.js를하거나 libES5입니다 폴더에 있습니다.

여기에 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를).


답변

José와 Marius의 접근 방식에 따라 (2019 년 Babel의 최신 버전 업데이트) : 최신 JavaScript 파일을 src 디렉토리에 보관하고 npm의 prepublish스크립트를 사용하여 빌드 하고 lib 디렉토리로 출력하십시오.

.npmignore

/src

.gitignore

/lib
/node_modules

Babel 설치 (필자의 경우 버전 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
...
> 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-plugin-babel

npm install -D 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/**"
    })
  ]
};

마지막으로, 업데이트 prepublishpackage.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롤업 번 들러를 사용중인 경우 더 이상 필요하지 않습니다 . 안전하게 제거 할 수 있습니다.

npm uninstall @babel/cli


답변

매우 간단한 작은 오픈 소스 노드 모듈 에서이 작업을보고 싶다면 n 번째 날 (내가 시작한 다른 기여자)을 살펴보십시오 . package.json 파일과 prepublish 단계에서이를 수행하는 위치와 방법을 찾으십시오. 해당 모듈을 복제하면 로컬로 실행하여 템플릿을 템플릿으로 사용할 수 있습니다.


답변

Node.js 13.2.0+는 실험용 플래그없이 ESM을 지원하며 하이브리드 (ESM 및 CommonJS) NPM 패키지를 게시하는 몇 가지 옵션이 있습니다 (필요한 이전 버전과의 호환성 수준에 따라 다름) : https://2ality.com/2019 /10/hybrid-npm-packages.html

패키지를보다 쉽게 ​​사용할 수 있도록 이전 버전과 완전히 호환되는 것이 좋습니다. 이것은 다음과 같이 보일 수 있습니다 :

하이브리드 패키지에는 다음 파일이 있습니다.

mypkg/
  package.json
  esm/
    entry.js
  commonjs/
    package.json
    entry.js

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';

2019 년 5 월 ESM 지원에 대한 조사를 수행 한 결과 많은 라이브러리에 지원이 부족한 것으로 나타났습니다 (따라서 이전 버전과의 호환성 권장 사항).