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

하나의 파일에 대략 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"
  }
}



답변

이미 번들 패키지의 일부를 가져 오려고 할 때 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에 나왔습니다.


답변

이것은 유효한 유스 케이스입니다. 궁극적 인 목표는이 작업을 수행하는 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'. 쉬워요.

즐기세요!


답변