하나의 NPM 패키지에서 여러 ES6 모듈을 내보내는 방법


16

하나의 파일에 대략 5 개의 서로 다른 ES6 클래스로 구성된 비교적 작은 NPM 패키지를 만들었습니다.

export default class MyClass {
    // ...
}

그런 다음 다음과 같은 패키지의 시작점을 설정했습니다.

export { default as MyClass } from './my-class.js';
export { default as MyOtherClass } from './my-other-class.js';

그런 다음 webpack과 babel을 통해 진입 점을 실행하여 변환되고 축소 된 index.js로 끝납니다.

패키지 설치 및 가져 오기는 정상적으로 작동하지만 클라이언트 코드에서 다음을 수행 할 때 :

import { MyClass } from 'my-package';

"MyClass"를 가져 오는 것이 아니라 모든 클래스의 모든 종속성을 포함하여 전체 파일을 가져옵니다 (일부 클래스에는 큰 종속성이 있음).

이미 번들 패키지의 일부를 가져 오려고 할 때 webpack이 어떻게 작동하는지 알았습니다. 그래서 node_modules/my-packagebabel을 통해 실행되도록 로컬 웹 팩 구성을 설정 한 다음 시도했습니다.

import { MyClass } from 'my-package/src/index.js';

그러나 이것조차도 index.js에서 내 보낸 모든 단일 클래스를 가져옵니다. 내가 원하는 방식으로 작동하는 유일한 것은 내가하는 경우입니다.

import MyClass from 'my-package/src/my-class.js';

그러나 나는 오히려 오히려 :

  1. node_modules 내부에서 babel을 실행하도록 webpack에 지시 할 필요가 없도록 변환되고 축소 된 파일을 가져올 수 있어야합니다.
  2. 각 파일의 경로를 입력하지 않고 시작점에서 직접 각 개별 클래스를 가져올 수 있습니다.

가장 좋은 방법은 무엇입니까? 다른 사람들은 어떻게 비슷한 설정을 달성합니까? GlideJS에 ESM 버전의 패키지가있어 예를 들어 babel을 실행하지 않고도 필요한 것만 가져올 수 있습니다.

문제의 패키지 : https://github.com/powerbuoy/sleek-ui

webpack.config.js

const path = require('path');

module.exports = {
    entry: {
        'sleek-ui': './src/js/sleek-ui.js'
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist'),
        library: 'sleek-ui', // NOTE: Before adding this and libraryTarget I got errors saying "MyClass() is not a constructor" for some reason...
        libraryTarget: 'umd'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                ]
            }
        ]
    }
};

package.json

  "name": "sleek-ui",
  "version": "1.0.0",
  "description": "Lightweight SASS and JS library for common UI elements",
  "main": "dist/sleek-ui.js",
  "sideEffects": false, // NOTE: Added this from Abhishek's article but it changed nothing for me :/
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode production"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/powerbuoy/sleek-ui.git"
  },
  "author": "Andreas Lagerkvist",
  "license": "GPL-2.0-or-later",
  "bugs": {
    "url": "https://github.com/powerbuoy/sleek-ui/issues"
  },
  "homepage": "https://github.com/powerbuoy/sleek-ui#readme",
  "devDependencies": {
    "@babel/core": "^7.8.6",
    "@babel/preset-env": "^7.8.6",
    "babel-loader": "^8.0.6",
    "webpack": "^4.42.0",
    "webpack-cli": "^3.3.11"
  },
  "dependencies": {
    "@glidejs/glide": "^3.4.1",
    "normalize.css": "^8.0.1"
  }
}

1
mainlib의 package.json에 (entry point) 속성 을 추가 했습니까 ? 빌드를 확인하십시오. 그리고 lib 패키지를 어떻게 묶고 있습니까?
Abhishek

package.json의 주요 속성은 package.json이 설명하는 모듈의 시작점 방향입니다. Node.js 애플리케이션에서 require 문을 통해 모듈을 호출하면 기본 특성에 이름이 지정된 파일에서 모듈을 내 보내면 Node.js 애플리케이션으로 리턴됩니다.
Abhishek

예, 주요 속성은 다른 모든 클래스를 내보내는 내 index.js를 가리 킵니다. webpack과 babel을 사용하여 main / index.js 파일을 묶고 있습니다. 질문에 모두 설명되어 있습니다.
powerbuoy

도움이 될 것입니다 -danielberndt.net/blog/2018/…
Abhishek

또한 빌드 구현에서 github.com/mui-org/material-ui/blob/master/packages/material-ui/… 를 사용할 수 import { MyClass } from 'my-package/src/MyClass';있습니다. 빌드 크기를 줄이려 면 더 좋습니다 . src 빌드 패키징을 제거하여 파일 경로를 줄일 수도 있습니다.
Abhishek

답변:


1

이미 번들 패키지의 일부를 가져 오려고 할 때 webpack이 어떻게 작동하는지 알았습니다.

예, 설정 방법은 index.js의 모든 클래스를 가져 와서 하나의 파일로 변환하는 것입니다 (가장 일반적인 ES5를 대상으로하는 경우). 즉, 해당 파일을 다른 파일로 가져 오면 해당 클래스와 함께 전체 파일이 제공됩니다.

적절한 트리 쉐이킹을 원하면 CommonJS (ES5) 번들로 변환하지 마십시오. ES6 모듈을 단독으로 또는 ES5 번들과 별도의 위치에 보관하는 것이 좋습니다. 이 문서는이를 완전히 이해하는 데 도움이되며 권장 지침을 제공합니다. 기본적으로 ES6 구문유지 하기 위해 preset-env를 사용하여 Babel 환경을 설정하는 것으로 요약합니다 (아직 사용하지 않는 경우 강력하게 권장합니다!) . ES5로 변환하지 않으려는 경우 관련 Babel 구성은 다음과 같습니다.

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "esmodules": true
        }
      }
    ]
  ]
}

이 기사에서는 각각 다른 모듈 구문을 사용하여 2 개의 번들을 설정하는 방법에 대해 자세히 설명합니다.

또한 주목할 가치가 있으며 기사에서 언급 한 바와 같이 package.json에서 ES 모듈 진입 점설정할 수 있습니다 . ES6 모듈을 찾을 수있는 위치를 Webpack / Babel에 알려 주면 사용 사례에 필요한 것일 수 있습니다. 기존의 지혜는 다음과 같이 말합니다.

{
  "main": "dist/sleek-ui.js",
  "module": "src/main.js"
}

그러나 노드 문서는 다음과 같습니다.

{
  "type": "module",
  "main": "dist/sleek-ui.js",
  "exports": {
    ".": "dist/sleek-ui.js",
    "./module": "src/main.js"
  }
}

내가 시간을 가지고 있다면 이것으로 놀아보고 어떤 것이 올바르게 작동하는지 볼 수 있지만 이것이 올바른 길을 설정하기에 충분해야합니다.


* ES5 대상 번들은 CommonJS 형식이며 ES5는 기본 모듈을 지원하지 않기 때문에 모든 관련 파일을 포함해야합니다. ES2015 / ES6에 나왔습니다.


추가를 시도했지만 targets.esmodules: true빌드 스크립트가 변경되었지만 결국 가져온 항목은 변경되지 않았습니다. 하나의 단일 클래스를 가져 오면 my-package여전히 모든 것을 가져옵니다. 또한 package.json(다른 변경과 함께) 변경을 시도했지만 아무것도 변경되지 않았습니다. 글쎄, type: module실제로 추가 하면 가져 오기를 사용하여 ES 모듈을로드해야합니다. /sleek-ui/webpack.config.js ES 모듈의 require ()는 지원되지 않습니다. 그래서 그 비트를 제거해야했습니다. 링크 된 기사를 살펴 보겠습니다.
powerbuoy

좋아, 그래서 기사는 실제로 modules: false(inside targets가 아닌) 설정하도록 말 했지만 작동하지 않았습니다 ... 소스 파일에서 직접 가져 와서이 내용을 기본적으로 사용할 수있을 때까지 node_modules를 통해 babel을 계속 실행한다고 생각합니다.
powerbuoy

@powerbuoy 소스 파일에서 가져 오기가 작동합니다. 어쩌면 내 게시물에서 명확하지 않았고 그 경우 편집 할 수 있지만와 같은 클래스 만 가져 오려고합니다 import MyClass from 'my-package/myClass';. 이것의 좋은 저장소 예는 lodash-es 입니다.
CaitlinWeb

-1

이것은 유효한 유스 케이스입니다. 궁극적 인 목표는이 작업을 수행하는 import { MyClass } from 'my-package'것이지만이 를 수행 하는 더 확실한 방법이 있습니다.

에 애그리 게이터 색인 파일을 만듭니다 my-package. 기본적으로 my-package/index.js다음과 같아야합니다.

import MyClass from './my-class.js'
import MyOtherClass from './my-other-class.js'

export { MyClass, MyOtherClass }

그럼 당신은 할 수 있습니다 import { MyClass } from 'my-package'. 쉬워요.

즐기세요!


이것은 내가 이미하고있는 일이며, 질문에서 매우 분명하다고 생각했습니다.
powerbuoy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.