Saya telah membangun paket NPM yang relatif kecil yang terdiri dari sekitar 5 kelas ES6 berbeda yang terkandung dalam satu file masing-masing, mereka semua terlihat sangat mirip:
export default class MyClass {
// ...
}
Saya kemudian mengatur titik masuk untuk paket saya yang terlihat seperti ini:
export { default as MyClass } from './my-class.js';
export { default as MyOtherClass } from './my-other-class.js';
Saya kemudian menjalankan entry point melalui webpack dan babel berakhir dengan index.js yang di-transpilasikan dan diperkecil
Menginstal dan mengimpor paket berfungsi dengan baik, tetapi ketika saya melakukan hal berikut dari kode klien saya:
import { MyClass } from 'my-package';
Itu tidak hanya mengimpor "MyClass" itu mengimpor seluruh file termasuk semua dependensi dari setiap kelas (beberapa kelas saya memiliki dependensi yang sangat besar).
Saya pikir ini adalah cara kerja webpack ketika Anda mencoba mengimpor bagian dari paket yang sudah dibundel? Jadi saya mengatur konfigurasi webpack lokal saya untuk dijalankan node_modules/my-package
melalui babel juga dan kemudian mencoba:
import { MyClass } from 'my-package/src/index.js';
Tetapi bahkan ini mengimpor setiap kelas yang diekspor oleh index.js. Satu-satunya hal yang tampaknya bekerja seperti yang saya inginkan adalah jika saya melakukannya:
import MyClass from 'my-package/src/my-class.js';
Tapi saya lebih suka:
- Dapat mengimpor file yang diubah dan diperkecil sehingga saya tidak perlu memberi tahu webpack untuk menjalankan babel di dalam node_modules dan
- Mampu mengimpor setiap kelas individu langsung dari titik masuk saya daripada harus memasukkan path ke setiap file
Apa praktik terbaik di sini? Bagaimana orang lain mencapai pengaturan serupa? Saya perhatikan GlideJS memiliki versi ESM dari paketnya yang memungkinkan Anda untuk mengimpor hanya hal-hal yang Anda butuhkan tanpa harus menjalankan babel melaluinya misalnya.
Paket yang dimaksud: 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"
}
}
sumber
main
atribut (entry point) di lib's package.json Anda? Periksa bangunan Anda. Dan bagaimana Anda menggabungkan paket lib Anda?import { MyClass } from 'my-package/src/MyClass';
. Anda juga dapat menghapus kemasan src build untuk mempersingkat jalur file.Jawaban:
Ya, cara Anda mengaturnya adalah mengimpor setiap kelas di index.js, yang kemudian diubah menjadi satu file (jika itu menargetkan ES5, yang paling umum *). Ini berarti bahwa ketika file itu diimpor dalam file lain, ia datang secara keseluruhan, dengan semua kelas tersebut.
Jika Anda ingin pengocokan pohon yang benar, Anda harus menghindari mentransformasikannya menjadi bundel CommonJS (ES5). Saran saya adalah menjaga modul ES6, baik dengan sendirinya atau di lokasi yang terpisah dari bundel ES5. Artikel ini akan membantu Anda memahami hal ini dan merekomendasikan instruksi. Pada dasarnya itu bermuara pada pengaturan lingkungan Babel menggunakan preset-env (sangat disarankan jika Anda belum menggunakannya!) Untuk mempertahankan sintaks ES6 . Berikut konfigurasi Babel yang relevan, jika Anda tidak ingin melakukan transpile ke ES5:
Artikel ini menjelaskan cara mengatur 2 bundel, masing-masing menggunakan sintaks modul yang berbeda.
Juga patut dicatat, dan agak disebutkan dalam artikel juga, Anda dapat mengatur titik entri modul ES di package.json. Itu memberitahu Webpack / Babel di mana modul ES6 dapat ditemukan, yang mungkin semua yang Anda butuhkan untuk kasus penggunaan Anda. Tampaknya kebijaksanaan konvensional mengatakan untuk melakukan:
Tetapi dokumentasi Node memilikinya sebagai:
Jika saya punya waktu saya akan bermain-main dengan ini dan melihat mana yang bekerja dengan benar, tetapi ini seharusnya cukup untuk membuat Anda berada di jalan yang benar.
* Bundel bertarget ES5 dalam format CommonJS, yang harus menyertakan semua file yang terkait, karena ES5 tidak memiliki dukungan modul asli. Itu datang dalam ES2015 / ES6.
sumber
targets.esmodules: true
dan sementara itu membuat perubahan pada skrip yang dibuat, itu tidak membuat perubahan apa yang diimpor pada akhirnya. Mengimpor satu kelas darimy-package
masih mengimpor semuanya. Saya juga mencoba perubahan dipackage.json
(bersama dengan perubahan lainnya) dan itu juga tidak mengubah apa pun. Nah, menambahkantype: module
benar-benar merusak bangunan saya dengan "Harus menggunakan impor untuk memuat Modul ES: /sleek-ui/webpack.config.js memerlukan () modul ES tidak didukung." jadi saya harus menghapus sedikit itu. Saya akan melihat artikel yang ditautkan.modules: false
(tidak di dalamtargets
) tapi itu tidak berhasil ... Saya pikir saya hanya akan mengimpor langsung dari file sumber dan terus menjalankan babel melalui node_modules sampai kita dapat menggunakan barang-barang ini secara asli.import MyClass from 'my-package/myClass';
. Contoh repo yang baik dari ini adalah lodash-es .Ini adalah use case yang valid. Tujuan utamanya adalah melakukan ini
import { MyClass } from 'my-package'
tetapi ada cara yang lebih bersih untuk melakukan ini.Buat file indeks agregator di blog Anda
my-package
. Pada dasarnyamy-package/index.js
dan akan terlihat seperti ini:Maka Anda bisa melakukannya
import { MyClass } from 'my-package'
. Peasy mudah.Selamat bersenang-senang!
sumber