Paylaşılan bileşen kitaplığı en iyi uygulamaları


12

Paylaşılabilir bir React bileşen kitaplığı oluşturuyorum.

Kitaplık birçok bileşen içerir, ancak son kullanıcının sadece birkaçını kullanması gerekebilir.

Kodu Webpack (veya Parsel veya Toplama) ile paketlediğinizde, tüm kodla birlikte tek bir dosya oluşturur .

Performans nedenlerinden ötürü, gerçekte kullanılmadıkça tüm bu kodların tarayıcı tarafından indirilmesini istemiyorum. Bileşenleri bir araya getirmemem gerektiğini düşünüyor muyum? Demet bileşenlerin tüketicisine bırakılmalı mı? Bileşenlerin tüketicisine başka bir şey bırakabilir miyim? Sadece JSX'i mi aktarırım?

Aynı repo birçok farklı bileşen içeriyorsa main.js'de ne olmalıdır?


1
Sorunuzu doğru anlamış Eğer böyle bir yaklaşım arıyorsanız biri kendi kaynak koduna bakmak ve bir istemci uygulaması kendi bileşenlerini (ve bireysel ithalat kullandığında onlar tüm bileşenleri yanı sıra bireysel olanları ve ihracat olduğunu göreceksiniz tüm modül yerine bileşenler) webpack, yalnızca koddaki dosyaları çeker importedve böylece paket boyutunu azaltır.
Edward Chopuryan

Yanıtlar:


5

Bu son derece uzun bir cevaptır, çünkü bu soru son derece uzun ve ayrıntılı bir cevabı hak eder çünkü “en iyi uygulama” yolu sadece birkaç satır yanıtından daha karmaşıktır.

Iv'e, ev kütüphanelerimizi 3.5+ yıl boyunca sürdürdüğümüzde, o zaman iv'e kütüphanelerin bir araya getirilmesi gerektiğini düşündüğüm iki yol üzerine yerleştik. tüketicilerin.

Yöntem 1: dışa aktarılmasını istediğiniz her şeyi içeren bir index.ts dosyası oluşturun. Kitaplığınızın tamamını tek bir index.js dosyası ve index.css dosyasına ekleyin; Harici bağımlılık ile kütüphane kodunun çoğaltılmasını önlemek için tüketici projesinden miras. (örnek yapılandırmanın altına gist dahil edilmiştir)

  • Artıları: Proje tüketicileri kök göreli kütüphane yolundan her şeyi içe aktarabildiğinden, kullanımı kolay import { Foo, Bar } from "library"
  • Eksileri: Bu asla ağaç sarsılmaz olmayacak; ve insanlar bunu ESM ile yapmadan önce ve ağaçlar değişebilir olacak. NextJS şu anki aşamada ESM'yi desteklemiyor ve proje kurulumlarının birçoğu da bu nedenle bu yapıyı sadece CJS'ye derlemek için hala iyi bir fikir. Birisi bileşenlerinizi 1 içe aktarırsa, tüm bileşenleriniz için tüm css ve tüm javascript'leri alır.

Yöntem 2: Bu, ileri düzey kullanıcılar içindir: Her dışa aktarma için yeni bir dosya oluşturun ve kullandığınız css sistemini nasıl kullandığınıza bağlı olarak "preserveModules: true" seçeneğiyle birlikte rollup-plugin-multi-input kullanın. css'iniz tek bir dosyada birleştirilmez, ancak her css dosyasının gerektirdiği (". css") ifadesinin toplandıktan sonra çıktı dosyasının içinde bırakıldığını ve bu css dosyası bulunduğunu unutmayın.

  • Artıları: Kullanıcılar "Foo} dosyasını" library / dist / foo "'dan içe aktardıklarında yalnızca Foo için kod ve Foo için css ve başka bir şey almazlar.
  • Eksileri: Bu kurulum, node_modules requirment (". Css") ifadelerini NextJS ile derleme yapılandırmalarında işlemek zorunda olan tüketiciyi içerir, bu next-transpile-modulesnpm paketi ile yapılır .
  • Dikkat: Burada bulabileceğiniz kendi babel eklentimizi kullanıyoruz: https://www.npmjs.com/package/babel-plugin-qubic insanların import { Foo,Bar } from "library"babel ile dönüştürmek ve daha sonra babel ile dönüştürmek için ...
import { Foo } from "library/dist/export/foo"
import { Bar } from "library/dist/export/bar"

Her iki yöntemi de kullandığımız çoklu toplama yapılandırmalarımız var; ağaç sallama umurumda olmayan kütüphane tüketicileri için sadece "Foo from "library"tek css dosyasını yapabilir ve alabilirsiniz; ve ağaç sallamaya özen gösteren kütüphane tüketicileri için ve sadece kritik css kullanarak babil eklentimizi açabilirler.

En iyi uygulama için toplama kılavuzu:

typescript kullanıp kullanmadığınızı ALWAYS ile "rollup-plugin-babel": "5.0.0-alpha.1" yapıp yapmadığınızı .babelrc dosyanızın böyle göründüğünden emin olun.

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {"chrome": "58", "ie": "11"},
      "useBuiltIns": false
    }],
    "@babel/preset-react",
    "@babel/preset-typescript"
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "absoluteRuntime": false,
      "corejs": false,
      "helpers": true,
      "regenerator": true,
      "useESModules": false,
      "version": "^7.8.3"
    }],
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-transform-classes",
    ["@babel/plugin-proposal-optional-chaining", {
      "loose": true
    }]
  ]
}

Ve rollup babel eklentisi böyle görünüyor ...

        babel({
            babelHelpers: "runtime",
            extensions,
            include: ["src/**/*"],
            exclude: "node_modules/**",
            babelrc: true
        }),

Ve senin paket.json böyle ATLEAST görünümlü:

    "dependencies": {
        "@babel/runtime": "^7.8.3",
        "react": "^16.10.2",
        "react-dom": "^16.10.2",
        "regenerator-runtime": "^0.13.3"
    },
    "peerDependencies": {
        "react": "^16.12.0",
        "react-dom": "^16.12.0",
    }

Ve son olarak toparlanmada ATLEAST gibi dış görünüşleriniz böyle.

const makeExternalPredicate = externalArr => {
    if (externalArr.length === 0) return () => false;
    return id => new RegExp(`^(${externalArr.join('|')})($|/)`).test(id);
};

//... rest of rollup config above external.
    external: makeExternalPredicate(Object.keys(pkg.peerDependencies || {}).concat(Object.keys(pkg.dependencies || {}))),
// rest of rollup config below external.

Neden?

  • Bu, tepki / tepki-dom'u ve diğer eş / dış bağımlılıklarınızı tüketici projesinden devralmak için bokunuzu paketleyecek, yani paketinizde çoğaltılmayacak.
  • Bu ES5 ile paketlenecek
  • Bu, paket projenizden başka bir 15-25KB silecek ve objectSpread için yardımcı işlevlerin kitaplığınızda çoğaltılmayacağı anlamına gelen tüketici projesinden objectSpread, sınıflar vb. çıktı + tüketen projeler birlikte çıktı.
  • Zaman uyumsuz işlevler çalışmaya devam eder
  • Haricilar bu bağımlı bağımlılık ekiyle başlayan herhangi bir şeyle eşleşecek, yani babil yardımcıları babil yardımcıları / yardımcıları / nesne yayılımı için harici ile eşleşecek

Son olarak, örnek tek bir index.js dosyası çıktı toplama yapılandırma dosyası için bir özgeçmiş. https://gist.github.com/ShanonJackson/deb65ebf5b2094b3eac6141b9c25a0e3 Hedef src / export / index.ts nerede böyle görünüyor ...

export { Button } from "../components/Button/Button";
export * from "../components/Button/Button.styles";

export { Checkbox } from "../components/Checkbox/Checkbox";
export * from "../components/Checkbox/Checkbox.styles";

export { DatePicker } from "../components/DateTimePicker/DatePicker/DatePicker";
export { TimePicker } from "../components/DateTimePicker/TimePicker/TimePicker";
export { DayPicker } from "../components/DayPicker/DayPicker";
// etc etc etc

Babil, toplanma ile ilgili herhangi bir sorun yaşarsanız veya gruplama / kitaplıklar hakkında herhangi bir sorunuz varsa bana bildirin.


3

Kodu Webpack (veya Parsel veya Toplama) ile paketlediğinizde, tüm kodla birlikte tek bir dosya oluşturur.

Performans nedenlerinden ötürü, gerçekte kullanılmadıkça tüm bu kodların tarayıcı tarafından indirilmesini istemiyorum

Her bileşen için ayrı dosyalar oluşturmak mümkündür. Webpack, birden fazla giriş ve çıkış tanımlayarak böyle bir yeteneğe sahiptir. Diyelim ki bir projenin aşağıdaki yapısı var

- my-cool-react-components
  - src // Folder contains all source code
    - index.js
    - componentA.js
    - componentB.js
    - ...
  - lib // Folder is generated when build
    - index.js // Contains components all together
    - componentA.js
    - componentB.js
    - ...

Webpack dosyası şöyle görünecektir

const path = require('path');

module.exports = {
  entry: {
    index: './src/index.js',
    componentA: './src/componentA.js',
    componentB: './src/componentB.js',
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'lib'),
  },
};

"Kod bölme" hakkında daha fazla bilgi Webpack dokümanlarında

Aynı repo birçok farklı bileşen içeriyorsa main.js'de ne olmalıdır?

package.jsonDosya adında tek bir alan mainvar, değerini lib/index.jsyukarıdaki proje yapısına göre koymak iyi . Ve index.jsdosyada tüm bileşenler ihraç var. Tüketicinin tek bir bileşen kullanmak istemesi durumunda,

const componentX = require('my-cool-react-components/lib/componentX');

Bileşenleri bir araya getirmemem gerektiğini düşünüyor muyum? Demet bileşenlerin tüketicisine bırakılmalı mı? Bileşenlerin tüketicisine başka bir şey bırakabilir miyim? Sadece JSX'i mi aktarırım?

Tamam, size kalmış. Bazı React kütüphanelerinin orijinal şekilde, bazılarının ise paket halinde yayınlandığını gördüm. Bazı oluşturma işlemlerine ihtiyacınız varsa, onu tanımlayın ve birlikte verilen sürümü dışa aktarın.

Umut, tüm sorularınıza cevap :)


Yanıt için teşekkürler. Örneğinizde olduğu gibi her yeni bileşen eklediğimde Webpack yapılandırmamı güncellemek istemiyorum. "bu size bağlı. Bazı React kütüphanelerinin orijinal şekilde, bazılarının ise birlikte yayınlandığını gördüm." Durum böyle olmadığını kanıtlıyor. Create React App benim ayrıştırılmamış bileşenleri ile çalıştı Tamam, ama Next JS bir hata atıyor ve açıkça sadece birlikte elime karar alarak, birlikte gelen bileşenler ile çalışır.
OTW

Araştırmak için elimden geleni yaptım :) "Her yeni bileşen eklediğimde Webpack yapılandırmamı güncellemek istemiyorum" - tüm bileşenleri listelememek için bazı glob-joker karakterleri kullanmak mümkün, sorunu çözüyor her yeni bileşen için webpack yapılandırmasını güncelleme. "Next JS bir hata atıyor" - peki, o zaman paketinizi paketleyin :) Açıkçası ham paket sadece tüketici projesinden paketlemeye dahil edildiğinde işe yarayacaktır. Birlikte verilen sürüm% 100 çalışacaktır.
Rashad Ibrahimov

1

Lodash'ın yöntemleri için yaptığı gibi bileşenlerinizi bölebilirsiniz .

Muhtemelen sahip olduğunuz, ayrı ayrı veya ana bileşen üzerinden içe aktarmaya izin verebileceğiniz ayrı bileşenlerdir.

Sonra tüketici tüm paketi alabilir

import {MyComponent} from 'my-components';

veya tek tek parçaları

import MyComponent from 'my-components/my-component';

Tüketiciler, ithal ettikleri bileşenlere göre kendi paketlerini oluşturacak. Bu, tüm paketinizin indirilmesini engellemelidir.


1

Sen de bir göz atmalısınız Bit , ben bu pay, yeniden kullanım ve görselleştirmek bileşenlerine iyi bir çözüm olduğunu düşünüyorum.

Kurulumu çok kolaydır. Bit kitaplığınızı veya yalnızca aşağıdakileri içeren bir bileşeni yükleyebilirsiniz:

npm i @bit/bit.your-library.components.buttons

Ardından, uygulamanızdaki bileşeni aşağıdakilerle içe aktarabilirsiniz:

import Button3 from '@bit/bit.your-library.components.buttons';

İyi tarafı, Webpack'i ve tüm bu cazları yapılandırma konusunda endişelenmenize gerek yok. Bit bile bileşenlerinizin versiyonunu destekler. Bu örnek , başlık listesi tepki bileşenini gösterir, böylece gereksinimlerinizi karşılayıp karşılamadığına bir göz atabilirsiniz


0

Web paketinde yığın dosyalar oluşturmak için bir yapılandırma vardır. Başlamak için ana paketi birden fazla parçaya oluşturacak ve gerektiğinde yükleyecektir. projenizde iyi yapılandırılmış modüller varsa, gerekli olmayan herhangi bir kod yüklenmez.

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.