Tek bir NPM paketinden birden fazla ES6 modülü nasıl verilir


16

Her biri bir dosyada bulunan kabaca 5 farklı ES6 sınıfından oluşan nispeten küçük bir NPM paketi inşa ettim, hepsi neredeyse şöyle görünüyor:

export default class MyClass {
    // ...
}

Daha sonra paketim için aşağıdaki gibi bir giriş noktası ayarladım:

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

Daha sonra webpack ve babil ile aktarılan ve küçültülmüş bir index.js ile biten giriş noktasını çalıştırdım

Paketin yüklenmesi ve içe aktarılması iyi çalışıyor, ancak istemci kodumdan aşağıdakileri yaptığımda:

import { MyClass } from 'my-package';

Sadece "Sınıfım" ı almakla kalmaz, her sınıfın tüm bağımlılıkları da dahil olmak üzere tüm dosyayı alır (bazı sınıflarımın büyük bağımlılıkları vardır).

Zaten paketlenmiş bir paketin parçalarını almaya çalıştığınızda web paketinin nasıl çalıştığını anladım? Bu yüzden yerel webpack yapılandırmamı babil node_modules/my-packageüzerinden çalışacak şekilde ayarladım ve denedim:

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

Ancak bu bile index.js tarafından dışa aktarılan her sınıfı içe aktarır. İstediğim gibi çalışıyor gibi görünen tek şey, eğer:

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

Ama daha doğrusu:

  1. Aktarılan ve küçültülmüş dosyayı içe aktarabilmek için node_modules içindeki babil'i çalıştırmak için webpack'e söylemem gerekmiyor
  2. Her dosyanın yolunu girmek yerine her bir sınıfı doğrudan giriş noktamdan içe aktarabilme

Buradaki en iyi uygulama nedir? Diğerleri benzer kurulumları nasıl gerçekleştirir? GlideJS'nin paketinin bir ESM sürümüne sahip olduğunu fark ettim.

Söz konusu paket: 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
main(Giriş noktası) niteliğini lib'nizin package.json dosyasına eklediniz mi ? Yapınızı kontrol edin. Ve lib paketinizi nasıl paketliyorsunuz?
Abhishek

Package.json öğesinin ana özelliği, package.json öğesinin tanımladığı modüle giriş noktasının yönüdür. Bir Node.js uygulamasında, modül bir deyim yoluyla çağrıldığında, modülün main özelliğinde adlandırılan dosyadan dışa aktarımı Node.js uygulamasına döndürülen dosya olur.
Abhishek

Evet, ana özellik tüm diğer sınıfları dışa aktardığım index.js adresime işaret ediyor. Main / index.js dosyasını webpack ve babel kullanarak bir araya getiriyorum. Her şey soruda açıklandı.
powerbuoy

bu size yardımcı olabilir - danielberndt.net/blog/2018/…
Abhishek

Ayrıca yapı uygulamalarında da yapabilirsiniz - github.com/mui-org/material-ui/blob/master/packages/material-ui/… Daha kısa yapı boyutuna sahip olmak için bunu yapmak daha iyidir import { MyClass } from 'my-package/src/MyClass';. Dosya yolunu kısaltmak için src derleme paketini de kaldırabilirsiniz.
Abhishek

Yanıtlar:


1

Zaten paketlenmiş bir paketin parçalarını almaya çalıştığınızda web paketinin nasıl çalıştığını anladım?

Evet, ayarladığınız yol, index.js'deki her sınıfı içe aktarmaktır ve daha sonra tek bir dosyaya aktarılır (en yaygın olan ES5'i hedefliyorsa *). Bu, o dosya başka bir dosyaya içe aktarıldığında, tüm bu sınıflarla birlikte tümüyle geldiğini gösterir.

Düzgün ağaç sallamak istiyorsanız, bunu bir CommonJS (ES5) paketine aktarmaktan kaçınmalısınız. Benim önerim ES6 modüllerini tek başına veya ES5 paketinden ayrı bir yerde tutmak. Bu makale bunu tam olarak anlamanıza yardımcı olmalıdır ve önerilen talimatları içermektedir. Esasen, ES6 sözdizimini korumak için preset-env (zaten kullanmıyorsanız şiddetle tavsiye edilir!) Kullanarak Babel ortamını ayarlamak için kaynar . ES5'e aktarmak istemiyorsanız, ilgili Babel yapılandırması şöyledir:

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

Makale, her biri farklı bir modül sözdizimi kullanan 2 paketin nasıl kurulacağını açıklar.

Ayrıca kayda değer ve makalede de bahsediliyor , ES modülü giriş noktasını package.json içinde ayarlayabilirsiniz . Bu, Webpack / Babel'e ES6 modüllerinin nerede bulunabileceğini söyler; bu, kullanım durumunuz için ihtiyacınız olan her şey olabilir. Geleneksel bilgelik yapmak diyor ki:

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

Ancak Düğüm dokümantasyonu şu şekildedir:

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

Eğer zamanım olsaydı bununla oynardım ve hangisinin doğru çalıştığını görürdüm, ama bu sizi doğru yola koymak için yeterli olmalı.


* ES5 hedefli paketler, ilişkili tüm dosyaları içermesi gereken CommonJS biçimindedir, çünkü ES5'in yerel modül desteği yoktur. Bu ES2015 / ES6'da geldi.


Eklemeyi denedim targets.esmodules: trueve bu inşa edilen komut dosyasında değişiklik yaparken, sonunda ne içe aktarıldığına dair hiçbir değişiklik yapmadı. Tek bir sınıftan içe aktarma my-packageyine de her şeyi alır. Ayrıca package.json(diğer değişiklik ile birlikte) değişiklikleri denedim ve bu da hiçbir şey değişmedi. Aslında, type: moduleES modülünü yüklemek için içe aktarma kullanılmalıdır: /sleek-ui/webpack.config.js ES modüllerini yüklemek için içe aktarma kullanılmalıdır. " bu yüzden o parçayı çıkarmak zorunda kaldım. Bağlantılı makaleye bir göz atacağım.
powerbuoy

Tamam böylece makale aslında modules: false(içinde değil targets) ayarlamak söyledi ama bu da işe yaramadı ... Ben sadece kaynak dosyadan doğrudan ithalat ve biz doğal olarak bu şeyler kullanabilirsiniz kadar node_modules aracılığıyla babel çalışmaya devam edeceğini düşünüyorum.
powerbuoy

@powerbuoy Kaynak dosyadan içe aktarma çalışır. Belki benim yazımdan net değildi ve bu durumda onu düzenleyebilirim, ancak sadece sınıfı almak istiyorsunuz import MyClass from 'my-package/myClass';. Bunun iyi bir repo örneği lodash-es .
CaitlinWeb

-1

Bu geçerli bir kullanım durumudur. Nihai amaç bunu yapmakimport { MyClass } from 'my-package' ama bunu yapmanın daha temiz bir yolu var.

'De bir toplayıcı dizin dosyası oluşturun my-package. Temel olarak my-package/index.jsve şöyle görünmelidir:

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

export { MyClass, MyOtherClass }

Sonra yapabilirsin import { MyClass } from 'my-package' . Çantada keklik.

İyi eğlenceler!


Tam olarak yaptığım şey bu, ki soruda oldukça açık olduğunu düşündüm.
powerbuoy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.