React: Memformalkan ekspor ES tingkat atas

Dibuat pada 9 Nov 2017  ·  104Komentar  ·  Sumber: facebook/react

Saat ini kami hanya mengirimkan versi CommonJS dari semua paket. Namun kami mungkin ingin mengirimkannya sebagai ESM di masa mendatang (https://github.com/facebook/react/issues/10021).

Kami tidak dapat melakukannya dengan mudah karena kami belum benar-benar memutuskan seperti apa ekspor ES tingkat atas dari setiap paket. Misalnya, apakah react memiliki banyak ekspor bernama, tetapi juga ekspor default yang disebut React ? Haruskah kita mendorong orang untuk import * untuk pengocokan pohon yang lebih baik? Bagaimana dengan react-test-renderer/shallow yang saat ini mengekspor kelas (dan dengan demikian akan mulai gagal di Node jika diubah menjadi ekspor default)?

Build Infrastructure React Core Team Breaking Change Discussion

Komentar yang paling membantu

Sekarang sudah hampir tahun 2020, saya ingin tahu apakah ada pembaruan dari tim FB resmi? Apakah akan ada perubahan terkait hal ini di React v17?

Semua 104 komentar

Imho import * adalah cara untuk pergi, saya tidak menentang memiliki ekspor default juga, tetapi tidak boleh digunakan untuk mengekspor kembali hal-hal lain seperti dalam contoh ini:

export const Component = ...
export default React
React.Component = Component

tetapi tidak boleh digunakan untuk mengekspor kembali hal-hal lain seperti dalam contoh ini:

Apakah ada alasan teknis mengapa? (Selain memiliki dua cara untuk melakukan hal yang sama.)

Kesan saya adalah bahwa orang yang akan mengimpor * (dan tidak menggunakan default) tidak akan mengalami masalah goyangan pohon karena default akan tetap tidak digunakan. Tapi mungkin saya melebih-lebihkan Rollup dll.

Pertanyaan itu mungkin paling baik dijawab oleh @lukastaegert. Tidak yakin apakah ada yang berubah sejak https://github.com/facebook/react/issues/10021#issuecomment -335128611

Rollup juga bukan satu-satunya pengocok pohon di luar sana, dan sementara algoritme pengocokan pohon webpack lebih buruk daripada yang ada di rollup, penggunaannya mungkin jauh lebih tinggi daripada rollup (kedua alat melakukan pekerjaan yang sangat baik, saya tidak ingin menyinggung siapa pun , hanya menyatakan fakta) dan jika kita dapat (sebagai komunitas) membantu kedua alat sekaligus, kita harus melakukannya kapan pun kita bisa.

apakah tree-shaking akan _do_ apa saja dalam kasus React, mengingat semuanya sudah diproses sebelumnya menjadi satu bundel datar? Saya ingin tahu apa gaya impor utama untuk Bereaksi, secara pribadi saya cenderung memperlakukannya seperti ekspor default misalnya React.Component , React.Children tetapi kadang-kadang melakukan hal yang disebutkan dengan cloneElement

Seperti yang sudah dinyatakan @gaearon di tempat lain, peningkatan ukuran jika terjadi reaksi diharapkan minimal. Namun demikian, ADA keuntungan:

  • React.Children mungkin akan dihapus dalam beberapa kasus (jadi saya dengar )
  • React sendiri dapat diangkat ke lingkup teratas oleh bundler modul yang mendukung ini. Ini lagi-lagi dapat menghapus beberapa byte dan mungkin juga memberikan peningkatan kinerja yang sangat sedikit. Peningkatan utama akan terletak pada kenyataan bahwa tidak perlu ada variabel lain yang mereferensikan React.Component untuk setiap modul tetapi hanya satu yang dibagikan di mana-mana (ini adalah cara rollup biasanya melakukannya). Juga, meskipun ini hanya tebakan saya, ini mungkin mengurangi kemungkinan keluarnya ModuleConcatenationPlugin webpack
  • Analisis statis untuk reaksi lebih mudah tidak hanya untuk pembuat modul tetapi juga untuk misalnya IDE dan alat lainnya. Banyak alat seperti itu sudah melakukan pekerjaan yang masuk akal dalam hal ini untuk modul CJS tetapi pada akhirnya, ada banyak tebakan yang terlibat di pihak mereka. Dengan modul ES6, analisis menjadi hal yang mudah.

Adapun jenis ekspor, tentu saja hanya ekspor bernama yang benar-benar memberikan manfaat dari pengocokan pohon yang mudah (kecuali jika Anda menggunakan GCC yang mungkin dapat melakukan sedikit lebih dalam langkah agresifnya dan mungkin rollup terbaru jika Anda benar-benar beruntung) . Pertanyaannya jika Anda memberikan ekspor default juga lebih sulit untuk diputuskan:

  • PRO: Migrasi tanpa rasa sakit untuk basis kode ES6 yang ada (misalnya apa yang dijelaskan oleh @jquense )
  • CON: Karena semuanya dilampirkan ke objek umum, setelah objek ini disertakan, semua kuncinya disertakan sekaligus yang sekali lagi mengalahkan upaya apa pun untuk menggoyahkan pohon. Bahkan GCC mungkin mengalami kesulitan di sini.

Sebagai strategi migrasi dua versi, Anda dapat menambahkan ekspor default di versi berikutnya untuk tujuan kompatibilitas yang dinyatakan tidak digunakan lagi (bahkan mungkin menampilkan peringatan melalui pengambil, dll.) dan kemudian menghapusnya di versi yang lebih baru.

Ini juga merupakan kasus yang menarik: https://github.com/facebook/react/issues/11526. Sementara monkeypatching untuk pengujian agak teduh, kami ingin berhati-hati tentang melanggar ini (atau memiliki solusi untuk itu).

Datang ke sini melalui percakapan Twitter ini . Bagi saya, ada jawaban yang benar dan jelas untuk pertanyaan ini: React dan ReactDOM seharusnya hanya mengekspor ekspor bernama. Mereka bukan objek yang berisi status, atau perpustakaan lain dapat bermutasi atau melampirkan properti (walaupun #11526) — satu-satunya alasan mereka ada adalah sebagai tempat untuk 'menempatkan' Component , createElement dan seterusnya. Dengan kata lain, ruang nama, yang harus diimpor seperti itu.

(Ini juga membuat hidup lebih mudah bagi para bundler, tetapi itu bukan di sini atau di sana.)

Tentu saja, itu menghadirkan perubahan besar bagi orang-orang yang saat ini menggunakan impor dan transpiling default. @lukastaegert mungkin memiliki ide yang tepat di sini, menggunakan

Saya tidak punya saran siap pakai untuk #11526. Mungkin pengiriman ESM akan menunggu v17 karena alasan itu, dalam hal ini tidak perlu khawatir tentang peringatan penghentian.

Orang-orang benar-benar menyukai

import React, { Component } from 'react'

jadi meyakinkan mereka untuk menyerah mungkin sulit.

Saya kira ini tidak terlalu buruk, meskipun agak aneh:

import * as React from 'react';
import { Component } from 'react';

Untuk memperjelas, kita perlu React berada dalam ruang lingkup (dalam hal ini, sebagai namespace) karena JSX ditranspile menjadi React.createElement() . Kita bisa mematahkan JSX dan mengatakan itu tergantung pada fungsi global jsx() sebagai gantinya. Maka impor akan terlihat seperti:

import {jsx, Component} from 'react';

yang mungkin baik-baik saja tapi perubahan besar. Ini juga berarti build React UMD sekarang perlu mengatur window.jsx juga.

Mengapa saya menyarankan jsx bukannya createElement ? Yah, createElement sudah kelebihan beban ( document.createElement ) dan meskipun tidak apa-apa dengan kualifikasi React. , tanpa mengklaimnya di global terlalu banyak. Tbh Saya tidak terlalu bersemangat dengan salah satu dari opsi ini, dan saya pikir ini mungkin jalan tengah terbaik:

import * as React from 'react';
import { Component } from 'react';

dan pertahankan JSX transpiling ke React.createElement secara default.

Pengakuan: Saya selalu merasa agak aneh bahwa Anda harus secara eksplisit mengimpor React untuk menggunakan BEJ, meskipun Anda sebenarnya tidak menggunakan pengenal itu di mana pun. Mungkin di masa depan, transpiler dapat memasukkan import * as React from 'react' (dapat dikonfigurasi untuk Preact dll) saat membuka BEJ, jika belum ada? Dengan begitu Anda hanya perlu melakukan ini...

import { Component } from 'react';

...dan impor namespace akan ditangani secara otomatis.

Di masa depan yang jauh, mungkin. Untuk saat ini kita perlu memastikan transpiler bekerja dengan sistem modul lain (CommonJS atau global). Membuat ini dapat dikonfigurasi juga merupakan rintangan, dan semakin memecah komunitas.

Apa yang disarankan @Rich-Harris (memasukkan impor tertentu saat jsx digunakan) mudah dilakukan oleh plugin transpiler. Komunitas harus meningkatkan babel-plugin-transform-react-jsx dan hanya itu. Dan tentu saja bahkan pengaturan yang ada akan tetap berfungsi jika hanya satu yang menambahkan import * as React from 'react'; ke file.

Tentu saja kita perlu mempertimbangkan sistem modul lain, tetapi sepertinya itu bukan masalah yang sulit untuk dipecahkan. Apakah ada gotcha tertentu dalam pikiran?

Tentu saja kita perlu mempertimbangkan sistem modul lain, tetapi sepertinya itu bukan masalah yang sulit untuk dipecahkan. Apakah ada gotcha tertentu dalam pikiran?

Saya tidak tahu, apa saran spesifik Anda tentang cara menanganinya? Apakah default untuk plugin Babel JSX?

Orang-orang benar-benar menyukai

import React, { Component } from 'react'

Orang apa? Majulah agar aku bisa mengejekmu.

Saya sering melakukan itu Cukup yakin saya pernah melihat ini di tempat lain juga.

Defaultnya saat ini React.createElement dan akan tetap sama. Satu-satunya masalah adalah bahwa ia mengasumsikan global sekarang (atau sudah tersedia dalam ruang lingkup).

Saya pikir karena modul es pada dasarnya adalah cara standar (walaupun belum diadopsi oleh semua) dalam melakukan modul, masuk akal untuk menganggap mayoritas (atau harus) menggunakannya. Sebagian besar sudah menggunakan berbagai alat langkah pembuatan untuk membuat bundelnya - yang bahkan lebih benar dalam diskusi ini karena kita berbicara tentang mentranspilasikan sintaks jsx . Mengubah perilaku default plugin jsx menjadi penyisipan otomatis React.createElement ke dalam cakupan adalah hal yang wajar untuk dilakukan. Kami berada di waktu yang tepat untuk perubahan ini dengan babel@7 segera hadir (-ish). Dengan penambahan babel-helper-module-imports baru ini, juga lebih mudah dari sebelumnya untuk memasukkan jenis impor yang tepat (es/cjs) ke file.

Memiliki ini dapat dikonfigurasi untuk menyelamatkan perilaku hari ini (dengan asumsi hadir dalam ruang lingkup) tampaknya benar-benar seperti perubahan kecil dalam konfigurasi yang diperlukan untuk sebagian kecil pengguna dan peningkatan (tentu, bukan yang besar - tapi tetap saja) untuk mayoritas.

Haruskah kita mendorong orang untuk mengimpor * untuk pengocokan pohon yang lebih baik?

Terima kasih kepada @alexlamsl uglify-es telah menghilangkan penalti export default dalam skenario umum:

$ cat mod.js 
export default {
    foo: 1,
    bar: 2,
    square: (x) => x * x,
    cube: (x) => x * x * x,
};
$ cat main.js 
import mod from './mod.js'
console.log(mod.foo, mod.cube(mod.bar));



md5-d6d4ede42fc8d7f66e23b62d7795acb9



$ uglifyjs -V
uglify-es 3.2.1

```js
$ cat bundle.js | uglifyjs --toplevel -bc
var mod_foo = 1, mod_bar = 2, mod_cube = x => x * x * x;

console.log(mod_foo, mod_cube(mod_bar));
$ cat bundle.js | uglifyjs --toplevel -mc passes=3
console.log(1,8);

wow, itu baru yang bagus apakah uglify-es dianggap stabil sekarang? Saya ingat Anda menyebutkan beberapa bulan yang lalu bahwa itu belum ada, tetapi saya dapat mengingatnya dengan tidak benar, jadi tidak yakin.

Bagaimanapun - itu saja dan bagus di dunia rollup, tetapi mengingat bahwa React sebagian besar dibundel dalam aplikasi dan sebagian besar menggunakan webpack yang tidak melakukan pengangkatan ruang lingkup secara default, saya masih akan mengatakan itu mengekspor objek sebagai default harus dihindari untuk membantu alat lain selain uglisy-es + rollup dalam upaya mereka untuk menghasilkan ukuran bundel yang lebih kecil. Juga bagi saya secara semantik lebih baik untuk menghindari ini - apa yang sebenarnya dilakukan lib dalam kasus seperti itu adalah menyediakan namespace dan lebih baik diwakili saat menggunakan import * as Namespace from 'namespace'

apakah uglify-es dianggap stabil sekarang?

Stabil seperti apa pun di ekosistem JS. Lebih dari 500 ribu unduhan per minggu.

itu saja dan bagus di dunia rollup, tetapi mengingat React sebagian besar dibundel dalam aplikasi dan mereka yang menggunakan sebagian besar webpack yang tidak melakukan pengangkatan cakupan secara default

Bagaimanapun, itu adalah pilihan. Default Webpack tetap tidak ideal - Anda harus menggunakan ModuleConcatenationPlugin seperti yang Anda tahu.

Menambahkan beberapa sen di sini:

  • Saya sangat setuju dengan @Rich-Harris bahwa secara semantik, ekspor bernama adalah pilihan yang tepat
  • Saya benar-benar tidak suka import React from 'react' atau import * as React from 'react' hanya untuk dapat menggunakan sintaks JSX. Di mata saya, desain ini jelas melanggar Prinsip Pemisahan Antarmuka karena memaksa pengguna untuk mengimpor semua React hanya untuk dapat menggunakan bagian createElement (meskipun diakui dengan ekspor namespace, bundler seperti Rollup akan hapus ekspor yang tidak dibutuhkan lagi)

Jadi, jika kita berada pada titik di mana kita mungkin membuat keputusan perubahan-perubahan, saya akan menyarankan untuk mengubahnya sehingga BEJ bergantung pada satu fungsi (global atau impor). Saya akan menyebutnya createJSXElement() , yang menurut saya menggambarkannya lebih baik daripada createElement() dan tidak lagi membutuhkan konteks Bereaksi untuk masuk akal. Tetapi di dunia di mana setiap byte diperhitungkan, jsx() mungkin juga baik-baik saja.

Ini juga pada akhirnya akan memisahkan JSX dari React sedemikian rupa sehingga perpustakaan lain dapat memilih untuk mendukung JSX dengan menggunakan transformasi yang sama dan menyediakan fungsi jsx berbeda. Tentu saja Anda memiliki banyak tanggung jawab di sini untuk memandu aplikasi mapan yang tak terhitung jumlahnya melalui transformasi seperti itu, tetapi dari sudut pandang arsitektur, saya pikir React dan JSX harus menuju ke sini. Menggunakan Babel untuk melakukan pekerjaan berat dari transformasi seperti itu terdengar seperti ide yang bagus bagi saya!

Secara pribadi saya tidak melihat banyak keuntungan dalam bermigrasi ke jsx helper karena IMHO default untuk plugin babel harus mengimpornya dari paket react , jadi nama helper yang sebenarnya tidak terlalu masalah - sisanya hanya masalah membuatnya dapat dikonfigurasi.

Ini mungkin sedikit bersinggungan dengan diskusi utama, tetapi saya ingin tahu seberapa baik modul ES bekerja dengan memeriksa process.env.NODE_ENV untuk mengekspor bundel dev/prod secara kondisional? Sebagai contoh,

https://github.com/facebook/react/blob/d9c1dbd61772f8f8ab0cdf389e70463d704c480b/packages/react/npm/index.js#L3 -L7

Saya mungkin melewatkan sesuatu yang jelas di sini, tetapi saya kesulitan melihat bagaimana menerjemahkan pola ini ke dalam modul ES?

@NMinhNguyen Ekspor bersyarat tidak dimungkinkan dengan modul ES.

process.env.NODE_ENV cek dapat berada pada level (kode) yang lebih terperinci, siap untuk digantikan oleh bundler dengan nilai yang sesuai.

@Andarist @milesj Terima kasih telah mengkonfirmasi kecurigaan saya :)

process.env.NODE_ENV cek dapat berada pada level (kode) yang lebih terperinci, siap untuk digantikan oleh bundler dengan nilai yang sesuai.

Dari posting blog React 16, saya berpikir bahwa cek process.env.NODE_ENV sengaja ditarik ke atas (sebagai lawan dari mereka yang lebih terperinci, yang merupakan sumbernya, jika saya tidak salah ), untuk membantu kinerja di Node.js?

Render sisi server yang lebih baik

React 16 menyertakan perender server yang ditulis ulang sepenuhnya. Ini sangat cepat. Ini mendukung streaming , sehingga Anda dapat mulai mengirim byte ke klien lebih cepat. Dan berkat strategi pengemasan baru yang mengkompilasi cek process.env (Percaya atau tidak, membaca process.env di Node sangat lambat!), Anda tidak perlu lagi membundel React untuk mendapatkan server yang bagus- kinerja rendering.

Seperti, saya tidak yakin bagaimana seseorang dapat menggunakan bidang module di package.json dan membedakan antara dev/prod untuk ESM sambil menjaga bundel ES tetap datar dan tidak memengaruhi kinerja Node.js

Seperti, saya tidak yakin bagaimana seseorang dapat menggunakan bidang modul di package.json dan membedakan antara dev/prod untuk ESM sambil menjaga bundel ES tetap datar dan tidak memengaruhi kinerja Node.js

Ini tentu saja merupakan kelemahan, karena tidak ada cara standar saat ini untuk melakukan ini. OTOH ini hanya masalah perkakas, mungkin (dan agak mudah) untuk mengompilasi ini dalam langkah-langkah pembuatan aplikasi Anda bahkan hingga hari ini. Tentu akan lebih mudah jika paket dapat mengekspos dev/prod build dan resolver hanya akan tahu mana yang harus dipilih, tapi mungkin itu hanya masalah mendorong ide ini ke pembuat perkakas.

Untuk kelas:

import Component from 'react/Component'

class MyButton extends Component{
  constructor(){
    this.state = {}
  }

  render() {
    return <button> Button <Button>
  }
}

Di mana transformasi akan menggunakan super.createElement() untuk mengubah ke jsx atau menggunakan static Component.createElement().

Untuk komponen tanpa kewarganegaraan:

import jsx from 'react/jsx'

const MyButton = () => jsx`<button> Button <Button>`;

mungkinkah menggunakan literal templat yang ditandai?

Node semoga menerima PR ini https://github.com/nodejs/node/pull/18392

Kami setuju di sini dengan @Rich-Harris.

Hanya menjatuhkan komentar di utas ini yang belum disebutkan secara khusus.

Saya berada dalam situasi di mana saya tidak menggunakan bundler sama sekali dan hanya ingin mengimpor reaksi dan berbagai komponen untuk digunakan secara asli melalui browser ( <script type="module" src="..."> ), yaitu

import React from “https://unpkg.com/[email protected]/umd/react.development.js”;
import ReactDOM from “https://unpkg.com/[email protected]/umd/react-dom.development.js”;
ReactDOM.render(
  React.createElement(...),
  document.getElementById('root')
);

Dari apa yang saya tahu, ini tidak mungkin hari ini. Sebagai gantinya, saya harus memasukkan versi reaksi UMD melalui tag <script> dari CDN dan kemudian menganggapnya ada di jendela di modul <script type="module"> saya tulis:

// myPage.html
<div id="myComponentRoot"></div>
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script type="module" src="/assets/scripts/components/MyComponent.js"></script>

// MyComponent.js
import AnotherComponent from "/assets/scripts/components/AnotherComponent.js";
window.ReactDOM.render(
  window.React.createElement(AnotherComponent),
  document.getElementById('root')
);

// AnotherComponent.js
export default class AnotherComponent extends window.React.Component {...}

Memiliki impor reaksi dari CDN akan luar biasa. Itu akan membuat prototyping di browser menjadi sangat cepat dan mudah sambil tetap dapat mempertahankan pemisahan file. Satu hal yang selalu saya korbankan saat menggunakan React tanpa bundler adalah kemampuan untuk memisahkan komponen (dan fungsi utilitas lainnya, dll) berdasarkan file. Tetapi sekarang dengan dukungan browser untuk modul ES asli, saya dapat menulis komponen React saya dalam file terpisah dan browser hanya menggunakannya seperti yang tertulis. Memang itu jika saya tidak menggunakan JSX, tetapi bahkan jika saya menggunakan JSX, saya dapat melakukan semua file di tempat melalui langkah build dan semua impor saya akan tetap berfungsi di browser.

// /assets/scripts/entry.js
import React from “https://unpkg.com/[email protected]/umd/react.development.js”;
import React from “https://unpkg.com/[email protected]/umd/react-dom.development.js”;
import RelatedPosts from "/assets/scripts/components/RelatedPosts.js";
ReactDOM.render(
  React.createElement(RelatedPosts),
  document.getElementById('root')
);

// /assets/scripts/components/RelatedPosts.js
import React from “https://unpkg.com/[email protected]/umd/react.development.js”;
import ListItem from "/assets/scripts/components/ListItem.js"
export default class MyComponent extends React.Component {
  componentDidMount() { /* fetch some data */ }
  render() { 
    return React.createElement(
      'ul',
      {},
      this.state.items.map(item => React.createElement(ListItem, { item: item })
    )
  }
}

// /assets/scripts/components/ListItem.js
import React from “https://unpkg.com/[email protected]/umd/react.development.js”;
export default function ListItem(props) {
  return React.createElement('li', null, ...)
}

Saya yakin beberapa orang akan berpendapat bahwa mengetikkan url CDN sepanjang waktu adalah masalah (masalah yang coba diperbaiki oleh beberapa orang) tetapi pengorbanannya sepadan bagi saya. Mengubah/memperbarui url itu mudah ditemukan/diganti. Untuk kasus penggunaan saya, ini melebihi kesulitan menyiapkan bundler.

Jika React memiliki dukungan untuk sesuatu seperti ini, tidak perlu ada perkakas. Saya hanya menggunakan browser. Saya dapat mengirimkan kode seperti ini di beberapa proyek pribadi yang mengasumsikan browser modern dan menggunakan reaksi sebagai peningkatan progresif pada halaman. Apa yang membuat ini fantastis adalah ketika saya kembali ke basis kode dalam 12 bulan, saya tidak perlu mengubah banyak API perkakas atau bahkan memiliki NPM sebagai manajer paket. Saya hanya menggunakan API dari browser, tidak ada yang lain.

FWIW: jika/ketika React dikirimkan dengan dukungan seperti ini, saya pikir akan sangat berharga untuk menunjukkan bagaimana Anda dapat menggunakan React seperti ini di dokumen, mengajarkan bahwa Anda dapat memanfaatkan React dan model komponennya dengan memisahkan logika setiap komponen melalui memiliki file sendiri dan Anda tidak perlu bundler untuk melakukannya, cukup gunakan native <script type="module"> , impor React dari CDN (atau salinan lokal Anda sendiri), dan selesai!”

Sekarang, semua browser modern termasuk versi seluler mendukung ESM. ESM bukan lagi sistem modul masa depan tetapi standar de facto saat ini.

Perlu diketahui bahwa tidak menyediakan modul standar adalah masalah kritis, terutama untuk perpustakaan web standar de facto.

import * as React from 'react';
import * as ReactDOM from 'react-dom';

Ini adalah kode khas untuk menerapkan library React, dan faktanya sebenarnya tidak ada library yang dapat diimpor, sebagai gantinya, transpiler dan bundler pihak ketiga meniru proses impor.

Sedikit dibenarkan untuk tidak menyediakan ESM yang sebenarnya karena browser tetap tidak mendukung ESM asli, tetapi jelas, waktunya sudah habis, dan sekarang adalah waktu untuk menyediakan ESM sebagaimana ditentukan oleh kode contoh tipikal ke import .

Saya mulai mengerjakan ini di sini dan di sini

@TrySound Terima kasih atas kontribusi Anda.
Apakah ada tempat untuk mengambil dan menguji build ESM?

Ini hanya siap untuk paket reaksi.

@CobaSuara
Oke, saya menemukan cabang Anda https://github.com/TrySound/react/tree/react-is-esm , dan telah membangun, dan sekarang saya tahu apa yang Anda maksud. Menantikan react-dom juga.

Saya pikir komunitas React membahas masalah ini cukup lama.
https://discuss.reactjs.org/t/es6-import-as-react-vs-import-react/360/

Silakan putuskan spesifikasi modul ES6 resmi, dan segera publikasikan.

@kenokabe Kami sedang dalam perjalanan. Tolong jangan paksa kami. Ini tidak semudah itu.

Paket saat ini memigrasikan semua paket dengan hanya ekspor bernama. Perubahan ini tidak akan memengaruhi kode pustaka dan tidak boleh menimbulkan perubahan yang melanggar karena dokumen juga menggunakan ekspor bernama.

Untuk paket lain, kita perlu menangani ekspor default dan ekspor bernama yang bekerja secara berbeda dengan berbagai alat.

@TrySound Maafkan saya.
Saya tidak bermaksud untuk Anda, karena kepala yang menyebutkan topik ini adalah

Kami tidak dapat melakukannya dengan mudah karena kami belum benar-benar memutuskan seperti apa ekspor ES tingkat atas dari setiap paket. Misalnya, apakah reaksi memiliki banyak ekspor bernama, tetapi juga ekspor default yang disebut Bereaksi? Haruskah kita mendorong orang untuk mengimpor * untuk pengocokan pohon yang lebih baik?

dan, hari yang disebutkan beberapa waktu yang lalu, dan saya pikir itu sudah dibahas di komunitas React, jadi saya ingin menyarankan keputusannya akan jelas. Terima kasih!

Ingin mendapatkan pembaruan tentang ini ...

Saya menggunakan webpack v4 untuk menggabungkan aplikasi kami, sementara intellisense IDE saya (WebStorm) menyarankan saya untuk menggunakan import * as React from 'react'; sementara rekan kerja saya meminta saya untuk mengubah import React from 'react'; dalam tinjauan kode. Keduanya berfungsi dengan baik, jadi saya pikir dia mengatakan omong kosong, tetapi untuk membuatnya senang, saya tetap mengubahnya. Itu juga bagaimana saya menemukan utas ini.

Karena penasaran, saya membandingkan perbedaan ukuran build akhir di antara keduanya (dengan React 16.8.1):

Dalam import * as React from 'react'; : 6.618.723 byte
Dalam import React from 'react'; : 6.619.077 byte

Jadi jelas, itu memang memiliki beberapa perbedaan, meskipun marjinal. (catatan. Saya telah melakukan hal yang sama dengan propTypes )

Jika pemahaman saya di utas ini benar, akan lebih baik jika memiliki import * as React from 'react'; , bukan?! Karena (1) ya, itu menghemat beberapa ukuran; (2) ESM adalah cara standar sehingga tidak ada lagi sisa CJS. Jika demikian, saya ingin mengubahnya hari ini dan menyelaraskan dengan IDE saya.

@leoyli Dalam jangka panjang ya. Tapi pertama-tama akan ada ekspor bernama dan default untuk tidak merusak kode yang ada.

Saya mengambil tindakan sendiri di sini, agak sebagai percobaan karena saya tidak menggunakan bundler dalam proyek saya lagi dan ingin tetap menggunakan reaksi (langsung dari unpkg.com seperti yang Anda bisa dengan perpustakaan lain seperti Vue, Hyperapp dll.) . Inilah yang saya buat, tidak ada yang mewah, hanya umd yang diedit dengan tangan:

https://github.com/lukejacksonn/es-react

Modul ES6 mengekspos versi terbaru dari React dan ReactDOM

Seperti yang dijelaskan dalam README ini sebagian besar adalah POC tetapi bagi orang yang tidak sabar menunggu build ini mendarat maka ini adalah build 16.8.3 yang mencakup kait, ketegangan, lazy, dll. dan berfungsi seperti yang diharapkan dengan melakukan:

import { React, ReactDOM } from 'https://unpkg.com/es-react'

Mungkin beberapa dari Anda di utas ini akan merasa berguna .. secara pribadi saya telah menggunakan pendekatan ini untuk membuat proyek starter reaksi bebas langkah build . Ini juga masih dalam proses.

@lukejacksonn Kami telah menggunakan solusi seperti itu pada produksi juga, sementara pendekatan kami berbeda dalam arti bahwa ini lebih merupakan skrip transformator untuk versi UMD dari React dan ReactDOM dalam proyek Anda saat ini. Dan itu mengeluarkan file ini secara terpisah sehingga untuk sebagian besar kode di luar sana, itu harus menjadi pengganti. Jika Anda tertarik https://github.com/wearespindle/react-ecmascript dan Anda juga dapat memuatnya dari unpkg https://unpkg.com/react-ecmascript/

@PM5544 Oh wow.. ini adalah solusi yang jauh lebih komprehensif dari saya! Kerja bagus

Hal-hal luar biasa @ PM5544. Akan senang mendengar lebih banyak tentangnya suatu hari nanti. Mungkin penampilan tamu di Xebia?
Saya baru-baru ini mengadopsi paket untuk menggabungkan paket sumber terbuka saya, yang mendukung UNPKG.
Adakah yang tahu artikel bagus tentang memuat dependensi dari UNPKG secara langsung daripada menggunakan bundler?

Saat ini saya sedang menulis satu dan akan memberikannya sebagai ceramah di React Norway pada bulan Juni juga!

@TrySound Apakah ada pembaruan tentang ini sejak Februari? Apa yang tersisa untuk menyelesaikan masalah ini, dan dapatkah saya berpartisipasi dalam menyelesaikan masalah ini dengan beberapa pekerjaan pengkodean? Saya sudah menandatangani CA, dan saya punya waktu hari ini untuk mengerjakannya.

@TrySound Oke terima kasih saya telah meneruskan tawaran bantuan saya ke utas itu.

Saat Anda menggunakan ekspor React default, Anda dapat menggunakan pendekatan ini:

// react/index.js
import * as React from "./react";
export { React as default }
export * from "./react";

// react/react.js
export function createElement() {}
...

Ini membuatnya dapat menganalisis secara statis bahwa ekspor default adalah objek namespace yang memungkinkan penggoyangan pohon untuk konstruksi ini di webpack 5 dan rollup:

import React from "react";

React.createElement(); // <- only `createElement` export is used

Saya dalam obrolan rollup gitter selama 1,5 tahun dan masalah seperti ini muncul setiap 2 minggu atau lebih ...

BTW, @lukejacksonn melakukan pekerjaan luar biasa pada fork es-react tidak resmi, sangat merekomendasikannya.

BTW, @lukejacksonn melakukan pekerjaan luar biasa pada fork es-react tidak resmi, sangat merekomendasikannya.

Saya bertanya-tanya mengapa tim FB resmi tidak melakukan apa pun untuk ini.

Saya juga berharap ini akan menghasilkan beberapa tekanan untuk memajukan segalanya, dan saya kira begitu juga @lukejacksonn sendiri. Namun, seperti yang saya pahami, dia sebenarnya menerima beberapa dukungan dari tim React untuk membuat garpunya dari sumber aslinya, jadi tampaknya setidaknya ada minat dalam hal ini.

Saya berharap ini juga memang. Sebenarnya saya hampir tidak menerima dukungan dari tim reaksi dalam pembuatan paket (selain beberapa kata-kata dorongan dari @threepointone). Baru-baru ini seorang rekan di sini di Formidable membantu saya membangun paket secara terprogram yang merupakan peningkatan daripada melakukannya dengan tangan setiap kali versi reaksi baru dirilis tetapi menghasilkan keluaran yang jauh lebih bersih di tab jaringan jadi saya tidak yakin apakah itu akan terjadi tetap seperti ini. Kita akan melihat!

Sekarang sudah hampir tahun 2020, saya ingin tahu apakah ada pembaruan dari tim FB resmi? Apakah akan ada perubahan terkait hal ini di React v17?

Bagi mereka yang membutuhkan ES-module yang diperbarui Bereaksi SEKARANG, coba @pica/react , yang sudah ada di v16.13.x
https://www.npmjs.com/package/@pika/react
https://www.npmjs.com/package/@pika/react -dom
https://github.com/pikapkg/react

Di masa depan yang jauh, mungkin.

Oke, sudah di masa depan. Apakah dalam waktu dekat sekarang?

@gaearon apa pemblokir untuk memutuskan bagaimana menyusun ekspor (ekspor default vs ekspor bernama)? Apakah ada komunitas yang dapat membantu Anda membuat keputusan ini?

Rupanya keputusan itu sudah dibuat beberapa waktu lalu: #18102. Masalah ini dapat ditutup sekarang.

Saya akan memberikan pembaruan kecil tentang ini.

Tidak ada Ekspor Default

Rencana akhir kami adalah untuk sepenuhnya beralih dari ekspor default:

import { useState } from 'react';

Di dunia itu, ini tidak akan berhasil:

import React from 'react'; // no

Ini akan berhasil meskipun agak bising:

import * as React from 'react';

Tapi inilah penendangnya. Sebenarnya tidak ada banyak alasan untuk mengimpor React sama sekali.

Impor Otomatis BEJ

Alasan orang mengimpor React hari ini sebagian besar karena BEJ. Tapi @lunaruan sedang menyelesaikan pekerjaan pada transformasi JSX baru dan codemods terkait, yang menghilangkan kebutuhan untuk itu.

Jadi Anda akan pergi dari ini:

import React from 'react';
import { useState } from 'react';

function Button() {
  const [pressed, setPressed] = useState(false)
  return <button />
}

untuk ini:

import { useState } from 'react';

function Button() {
  const [pressed, setPressed] = useState(false)
  return <button />
}

BEJ menyisipkan impor yang benar secara otomatis, jadi tidak perlu untuk React dalam cakupan.
Inilah yang membuat langkah untuk menghapus ekspor default dapat ditoleransi. Anda hanya tidak membutuhkan mereka sebanyak itu.

Modul ES

Menyebarkan ESM di luar sebagian kecil penggemar secara keseluruhan merupakan tantangan. Ekosistem yang luas belum benar-benar siap dan ada banyak cara di mana ada yang salah dengan kombinasi alat yang berbeda. Cara CJS dan ESM berinteraksi sangat kompleks, dan interop itu (dan bagaimana kegagalannya) adalah sumber dari sebagian besar masalah ini.

Jadi pemikiran kami saat ini adalah ketika kami menggunakan ESM, kami mungkin ingin mencoba menggunakan ESM sepenuhnya. Tidak ada CJS sama sekali — atau dipisahkan dalam paket warisan yang kompatibel. Ini tidak akan terjadi di React 17 dan tidak mungkin di 18, tetapi masuk akal untuk dicoba di React 19.

Bagi siapa pun yang mencari alternatif untuk membangun ESM @pika/react , lihat https://github.com/esm-bundle/react dan https://github.com/esm-bundle/react-dom. Perbedaannya adalah bahwa itu dapat digunakan di browser tanpa polyfill peta impor - import React from 'react'; di dalam kode sumber react-dom diubah untuk mengimpor React dari url CDN lengkap. Perbedaan lainnya adalah bahwa versi baru diterbitkan secara otomatis setiap kali versi reaksi baru diterbitkan, tanpa langkah manual apa pun.

Kode Sandbox mendemonstrasikan: https://codesandbox.io/s/gifted-roentgen-qcqoj?file=/index.html

Beberapa orang telah menentang gagasan bahwa ekosistem belum siap. Saya tidak memiliki konteks penuh tentang ini, tetapi jika menurut Anda ini saat yang tepat untuk mulai membuat perubahan, saya akan menghargai jika Anda dapat melihat https://github.com/reactjs/rfcs/pull/38 dan mengungkapkannya kekhawatiran tentang hal itu. Apakah itu kira-kira yang Anda pikirkan, atau Anda lebih suka pendekatan yang berbeda?

Tapi inilah penendangnya. Sebenarnya tidak ada banyak alasan untuk mengimpor React sama sekali.

Ada jika Anda menggunakan TypeScript, dan akan terus demikian di masa mendatang. Sampai TS mengetahui tentang perilaku ajaib baru dari babel ini, pengembang harus terus mengimpor React secara eksplisit, dan mereka perlu tahu apa pernyataan impor yang benar.

JSX menyisipkan impor yang benar secara otomatis, jadi tidak perlu React dalam cakupan.

s/JSX/Babel baru bereaksi jsx transform plugin/. JSX adalah ekstensi sintaks untuk JavaScript, itu sendiri tidak melakukan apa-apa.

Ada jika Anda menggunakan TypeScript, dan akan terus demikian di masa mendatang. Sampai TS mengetahui tentang perilaku ajaib baru dari babel ini, pengembang harus terus mengimpor React secara eksplisit, dan mereka perlu tahu apa pernyataan impor yang benar.

Tim TypeScript mengetahui perubahan ini, dan sedang dilacak di https://github.com/microsoft/TypeScript/issues/34547. Kami berhubungan dekat dengan mereka jadi yakinlah itu bukan warga negara kelas dua bagi kami.

s/JSX/Babel baru bereaksi jsx transform plugin/

Ya, ini yang saya maksud!

Saya akan menghargai jika Anda dapat melihat reactjs/rfcs#38 dan mengungkapkan kekhawatiran apa pun tentangnya. Apakah itu kira-kira yang Anda pikirkan, atau Anda lebih suka pendekatan yang berbeda?

Beberapa teks asli RFC sudah kedaluwarsa. NodeJS memungkinkan ESM untuk berjalan di file .js alih-alih .mjs sekarang, ketika Anda menentukan "type" di package.json Anda. ( dok ).

Secara khusus, teks asli RFC mengatakan hal berikut yang tidak benar:

Kode ESM harus berada di dalam file .mjs

Setelah berbicara dengan @frehner , inilah proposal kami tentang bagaimana React dapat dikonversi secara bertahap ke ESM. Perhatikan bahwa kami tidak memasangkan masalah ekspor bernama/default dengan menerbitkan versi ESM dari React. @gaearon telah mengklarifikasi bahwa ekspor default pada akhirnya akan hilang, tetapi itu tidak tercantum dalam proposal kami hingga Fase 4.

| | Fase 1 | Fase 2 | Fase 3 | Fase 4 |
| - | -------- | -------- | -------- | ------- |
| ESM diterbitkan? | ️ | ️ | ️ | ️ |
| package.json "module" | | ️ | ️ | ️ |
| webpack/rollup gunakan esm 1 , 2 | | ️ | ️ | ️ |
| package.json "exports" | | | ️ | ️ |
| package.json "type" | | | ️ | ️ |
| NodeJS menggunakan esm | | | ️ | ️ |
| Menghancurkan perubahan? | | | | ️ |
| Ekspor default hilang? | | | | ️ |
| Ekstensi file diperlukan dalam impor | | | | |
| ekstensi file mjs | | | | |

Saya pikir ada argumen yang valid untuk menggabungkan Fase 1 dan Fase 2 bersama-sama, karena Fase 1 benar-benar hanya menargetkan para penggemar. Namun, saya membaginya karena menurut saya memisahkan fase memberi kesempatan untuk meluncurkan ESM dengan sangat perlahan dengan cara yang tidak akan langsung merusak CRA dan seluruh ekosistem tanpa terlebih dahulu memberi kesempatan kepada pengadopsi awal untuk melaporkan masalah dan menemukan perbaikan apa pun. .

@joeldenning apa yang akan menjadi waktu kasar fase? apakah ini hanya berdasarkan waktu atau apakah itu terkait dengan beberapa pos pemeriksaan waktu di ekosistem? Apakah require('react') masih berfungsi di Fase 3?

apa yang akan menjadi waktu kasar fase? apakah ini hanya berdasarkan waktu atau apakah itu terkait dengan beberapa pos pemeriksaan waktu di ekosistem?

Waktu untuk semua fase hanya dibatasi oleh pekerjaan yang harus dilakukan dan jadwal rilis React. Pemahaman saya adalah bahwa semua hal yang diusulkan didukung oleh bundler dan nodejs, dengan fallback yang sesuai saat menggunakan versi lama yang tidak mendukungnya.

Apakah require('react') masih berfungsi di Fase 3?

Saya pikir begitu, ya. Lihat https://nodejs.org/api/esm.html#esm_dual_commonjs_es_module_packages dan https://nodejs.org/api/esm.html#esm_package_entry_points. Tentu saja sangat mungkin bahwa saya tidak tahu semua kasus sudut untuk semuanya, tetapi pemahaman saya adalah bahwa jalur transisi yang saya usulkan "akan bekerja di mana-mana." Mungkin itu kata-kata terakhir yang terkenal

Klarifikasi tambahan, inilah tampilan tarball yang kami usulkan untuk React:

node_modules/react/
  cjs/
    react.development.js
    react.production.min.js
    react.profiling.min.js
  umd/
    react.development.js
    react.production.min.js
    react.profiling.min.js
  esm/
    react.development.js
    react.production.min.js
    react.profiling.min.js
  index.js

Dan di sini adalah perkiraan dari apa package.json akan menjadi di akhir:

{
  "type": "module",
  "main": "index.js",
  "module": "esm/react.development.js",
  "exports": {
    "import": "./esm/react.development.js",
    "require": "./cjs/react.development.js"
  }
}

^ Ini tidak sepenuhnya dipikirkan dan disempurnakan, tetapi saya berbagi untuk memberikan konteks konkret pada proposal.

Jadi - Bereaksi menderita dari bahaya paket ganda karena stateful (kait), jadi status ini harus diisolasi dengan hati-hati. Entah itu harus hidup dalam file CJS kecil yang dapat diimpor oleh entri CJS dan ESM atau mungkin ada cara memuat .json dan mengubahnya dengan status itu dari kedua entri (saya tidak 100% yakin tentang pendekatan kedua).

Saya juga berpikir bahwa penting untuk membuat daftar di tabel Anda menambahkan ekspor bernama, yang sudah akan terjadi di Fase 1.

Saya masih belum 100% yakin jika saya tidak melewatkan beberapa kasus sudut, topik ini sangat kompleks. Pada saat yang sama, jadwal harus dikaitkan dengan pos pemeriksaan ekosistem - Fase 3 hanya dapat dikirimkan setelah exports memiliki dukungan yang memadai dalam bundel, jika tidak, saya merasa ini dapat menyebabkan masalah potensial.

Bereaksi menderita bahaya paket ganda karena stateful (kait), jadi status ini harus diisolasi dengan hati-hati.

Poin bagus, saya belum mempertimbangkan ini ( info lebih lanjut ). Dalam hal ini, mungkin saran Anda tentang file bersama antara build CJS / ESM akan berguna. Atau mungkin versi ESM bukan salinan lengkap dari reaksi, tetapi hanya antarmuka publik ESM yang memanggil ke build CJS.

Saya juga berpikir bahwa penting untuk membuat daftar di tabel Anda menambahkan ekspor bernama, yang sudah akan terjadi di Fase 1.

Tampaknya ini sudah terjadi, dalam kode sumber? Dari apa yang saya tahu, kode sumber sudah mengekspor barang-barang sebagai ekspor bernama.

https://github.com/facebook/react/blob/ef22aecfc52cdf0d7cedc723c590719c009c2a64/packages/react/index.js#L39

https://github.com/facebook/react/blob/ef22aecfc52cdf0d7cedc723c590719c009c2a64/packages/react/index.js#L39

Saya masih belum 100% yakin jika saya tidak melewatkan beberapa kasus sudut, topik ini sangat kompleks. Pada saat yang sama, jadwal harus dikaitkan dengan pos pemeriksaan ekosistem - Fase 3 hanya dapat dikirimkan setelah ekspor memiliki dukungan yang cukup dalam bundel, jika tidak, saya merasa ini dapat menyebabkan masalah potensial.

Setuju tentang Fase 3 - inilah mengapa saya memberi tanda tanya apakah itu perubahan yang melanggar. Saya tahu bahwa menambahkan ekspor package.json sering kali merupakan perubahan besar untuk paket lain dalam ekosistem. Dan topiknya pasti kompleks. Satu hal yang perlu diperhatikan adalah urutan Fase 3 dan 4 dapat ditukar, jika diinginkan. Saya pikir mereka yang mengimplementasikan setiap fase harus melakukan pengujian yang sangat sangat sangat menyeluruh dari banyak versi webpack, rollup, nodejs, dll. Saya tidak mengatakan bahwa pekerjaan yang harus dilakukan itu sepele - hanya mengatakan bahwa saya berpikir bahwa ada kemungkinan jalur transisi di sini :)

Tampaknya ini sudah terjadi, dalam kode sumber? Dari apa yang saya tahu, kode sumber sudah mengekspor barang-barang sebagai ekspor bernama.

Ah - benar, dalam hal ini harus ada baris tabel untuk menambahkan export default 😂 karena saat ini berfungsi di sebagian besar bundler dan populer di alam liar, tetapi menambahkan entri ESM yang sebenarnya tanpa memberikan default akan melanggar penggunaan tersebut.

dalam hal ini harus ada baris tabel untuk menambahkan default ekspor

Ya, poin yang bagus. Saya akan menambahkan itu. Saya pikir PR melakukan itu akan "tampak buruk", tetapi saya melihatnya hanya menerima antarmuka publik saat ini apa adanya, dengan rencana untuk meningkatkan di masa depan.

Kami harus mencatat bahwa segera setelah beberapa versi diterbitkan, tidak ada jalan untuk kembali dan perubahan semantik apa pun padanya akan rusak. Mengingat kami tidak merilis jurusan terlalu sering, kami harus mempertimbangkan cara mengelompokkan perubahan apa pun sehingga ada sedikit churn.

Ada juga pertanyaan tentang bagaimana pembagian pembangunan/produksi akan ditangani. Dan memang, sifat stateful dari build React cukup penting untuk dipertahankan.

Kami harus mencatat bahwa segera setelah beberapa versi diterbitkan, tidak ada jalan untuk kembali dan perubahan semantik apa pun padanya akan rusak. Mengingat kami tidak merilis jurusan terlalu sering, kami harus mempertimbangkan cara mengelompokkan perubahan apa pun sehingga ada sedikit churn.

Poin bagus. Ide saya adalah untuk menambahkan export default React eksplisit ke build ESM yang diterbitkan di React 16. Saya pikir PR mungkin akan menaikkan alis dan mungkin kontroversial, karena itu bukan tujuan yang telah diputuskan. Namun, pandangan saya adalah bahwa kita dapat memiliki ESM build di React 16 dan kemudian menghapus export default di versi utama yang akan datang. Bagi saya, menggunakan reaksi melalui import React from 'react'; sangat umum sehingga mengekspor default di build ESM hanyalah "menerima di mana kita berada." Versi utama masa depan akan menghapusnya.

Juga terkait dengan meminimalkan perubahan yang melanggar - fase 3 dan 4 dapat menjadi bagian dari rilis utama yang sama. Ada kemungkinan bahwa fase 3 dapat dilakukan dengan cara yang sepenuhnya kompatibel, dalam hal ini juga dapat menyelinap ke rilis 16. Tapi yang itu lebih rumit dan saya tidak cukup tahu tentang itu untuk yakin akan hal itu.

Ada juga pertanyaan tentang bagaimana pembagian pembangunan/produksi akan ditangani.

Ini adalah sesuatu yang saya abaikan. Saya tidak tahu bagaimana melakukan ini dengan ESM di bundler dan di NodeJS, tetapi akan melakukan riset untuk melihat apa yang mungkin. Saya menemukan proposal mati ini , tetapi akan melihat

Dan memang, sifat stateful dari build React cukup penting untuk dipertahankan.

Sepakat. Satu hal yang perlu diperhatikan adalah bahwa sifat stateful dari build React hanya perlu diselesaikan di Fase 3, bukan di Fase 1 dan 2. Opsi yang saya dan @Andarist sarankan akan bekerja untuk menyelesaikannya.

Pendekatan termudah dan paling kompatibel untuk saat ini adalah menambahkan pembungkus ESM sederhana untuk memungkinkan impor bernama.

Saya akan dengan senang hati membuat PR untuk menambahkan ini ke React, memastikan bahwa penambahan bidang "ekspor" bukanlah perubahan yang melanggar (saya menulis sebuah alat, npx ls-exports , yang membuat penentuan ini menjadi mudah). Ini tidak akan membantu orang yang mencoba menggunakan ESM tanpa proses pembuatan, tetapi itu adalah masalah yang tidak dapat diselesaikan oleh paket individu.

@gaearon apakah itu berguna? Itu bisa mendarat di React 16 sebagai semver-minor.

Pembuatan CJS akan terus menggunakan deteksi lingkungan, seperti yang dilakukannya sekarang, sehingga masalah (sulit, tidak terpecahkan) di ESM belum harus dipecahkan.

Namun, pandangan saya adalah bahwa kita dapat memiliki build ESM di React 16 dan kemudian menghapus default ekspor di versi utama yang akan datang.

Kekhawatiran lain adalah bahwa peningkatan jumlah konfigurasi memberi tekanan pada ekosistem. Misalnya, saya pikir jika kita merilis build ESM, itu tidak boleh menyertakan sesuatu yang pasti akan kita hapus di rilis berikutnya, seperti ekspor default. Dengan kata lain, menurut saya tidak masuk akal untuk memperkenalkan sesuatu yang hilang (ekspor default) menjadi sesuatu yang baru saja ditambahkan (pembuatan ESM).

Namun, pandangan saya adalah bahwa kita dapat memiliki build ESM di React 16 dan kemudian menghapus default ekspor di versi utama yang akan datang.

Kekhawatiran lain adalah bahwa peningkatan jumlah konfigurasi memberi tekanan pada ekosistem. Misalnya, saya pikir jika kita merilis build ESM, itu tidak boleh menyertakan sesuatu yang pasti akan kita hapus di rilis berikutnya, seperti ekspor default. Dengan kata lain, menurut saya tidak masuk akal untuk memperkenalkan sesuatu yang hilang (ekspor default) menjadi sesuatu yang baru saja ditambahkan (pembuatan ESM).

Saya pikir itu tergantung pada berapa lama rilis berikutnya. Jika kita berbicara tentang perbedaan minggu, maka itu tampaknya masuk akal. Namun, jika kita berbicara bulan/tahun, maka saya tidak mengerti mengapa akan buruk untuk mengeluarkannya selama itu

Kekhawatiran dalam kasus ini adalah bahwa semakin lama itu di luar sana, semakin banyak orang bergantung padanya dalam bentuk saat ini. Dan kemudian memperkenalkan perubahan yang melanggar di sana akan membuat mereka lebih sulit untuk mengupgrade React. Sekarang tidak hanya satu migrasi ESM, tetapi beberapa, dan beberapa orang akan tertinggal karena mereka melompat terlalu dini dan kemudian tidak memiliki sumber daya untuk migrasi lain. Yang, dalam kasus ESM, akan beriak di seluruh ekosistem.

Saya pikir jika kami merilis build ESM, itu tidak boleh menyertakan sesuatu yang pasti akan kami hapus di rilis berikutnya, seperti ekspor default. Dengan kata lain, menurut saya tidak masuk akal untuk memperkenalkan sesuatu yang hilang (ekspor default) menjadi sesuatu yang baru saja ditambahkan (pembuatan ESM).

Saya tidak melihat import React from 'react' sebagai sesuatu yang baru ditambahkan, melainkan penerimaan dari kenyataan saat ini. Meskipun mungkin tidak disengaja dan hanya efek samping dari interop ESM/CJS yang sekarang sudah usang, masih ada ribuan (jutaan?) baris kode yang melakukannya. Alternatif (hanya mengekspor ekspor bernama) mengatakan kepada pengguna "kami menerbitkan build ESM dalam versi minor, tetapi Anda tidak dapat menggunakannya tanpa mengubah semua kode Anda" yang bagi saya lebih membingungkan bagi pengguna daripada melihat "ekspor default yang dihapus" dalam catatan rilis versi utama.

Saya ingin tahu - bagaimana ESM dengan ekspor default dapat ditambahkan dengan cara yang kompatibel? Ini telah muncul sebelumnya (mis. https://github.com/facebook/react/pull/18187 yang juga menautkan ke masalah terkait). Masalahnya adalah dengan webpack CJS <-> ESM interop di mana jika Anda memiliki kode CJS melakukan require('react') webpack apa yang akan kembali dengan adanya ESM react dengan ekspor default, adalah objek dengan default properti (artinya sekarang membutuhkan require('react').default ) terlepas dari CJS react . Tapi mungkin jika Anda juga mengekspor bernama maka itu tidak akan menjadi masalah? Saya pikir @TrySound telah mengalami masalah seperti itu di paket lain sebelumnya.

Tapi mungkin jika Anda juga mengekspor bernama maka itu tidak akan menjadi masalah?

Ya, ini adalah pendekatan yang saya pikirkan. Lihat 40 baris terakhir https://unpkg.com/browse/@esm-bundle/react @16.13.1/esm/react.development.js - ini adalah versi tidak resmi dari React yang melakukan hal ini dan digunakan oleh beberapa organisasi sebagai pengganti drop-in untuk React resmi. Tidak ada perubahan yang melanggar.

Tapi mungkin jika Anda juga mengekspor bernama maka itu tidak akan menjadi masalah?

Ya, ini adalah pendekatan yang saya pikirkan. Lihat 40 baris terakhir https://unpkg.com/browse/@esm-bundle/react @16.13.1/esm/react.development.js - ini adalah versi tidak resmi dari React yang melakukan hal ini dan digunakan oleh beberapa organisasi sebagai pengganti drop-in untuk React resmi. Tidak ada perubahan yang melanggar.

Tetapi apakah Anda mengonsumsinya dari kode CJS atau ESM? Karena masalah interop CJS <-> ESM yang bisa sangat mengejutkan.

@gaearon menjadi jelas; masuk akal untuk tidak memiliki ekspor default di pembungkus ESM yang saya usulkan; siapa pun yang melakukan ESM asli akan melakukan import * as React from 'react' untuk mengatasinya. Namun, wajar jika siapa pun yang melakukan itu sekarang akan melihatnya sebagai perubahan besar yang tiba-tiba tidak memiliki ekspor default, jadi itu harus menunggu hingga v17 jika Anda tidak ingin menambahkan default sekarang.

Tetapi apakah Anda mengonsumsinya dari kode CJS atau ESM? Karena masalah interop CJS <-> ESM yang bisa sangat mengejutkan.

Saya telah berhasil mengimpornya di webpack dari file CJS dan ESM.

siapa pun yang melakukan ESM asli akan melakukan import * as React from 'react' untuk mengatasinya. Namun, wajar jika siapa pun yang melakukan itu sekarang akan melihatnya sebagai perubahan besar yang tiba-tiba tidak memiliki ekspor default, jadi itu harus menunggu hingga v17 jika Anda tidak ingin menambahkan default sekarang.

Sepakat. Jika memulai dari awal, tidak perlu memiliki ekspor default. Namun, tanpa menambahkan ekspor default, tidak mungkin untuk mengimplementasikan Fase 2 tanpa perubahan yang melanggar. Saya pribadi akan baik-baik saja dengan melakukan Fase 1 di reaksi 16 dan Fase 2-4 di Bereaksi 17+, meskipun preferensi saya adalah melakukan Fase 1, 2, dan mungkin bahkan 3 (dengan bantuan alat pemeriksa ekspor @ljharb ) di React 16 tanpa merusak perubahan. Alasannya adalah fase 2 adalah fase besar di mana mayoritas pengguna mulai menggunakan bundel ESM, sedangkan fase 1 sebagian besar untuk pengadopsi/penggemar awal.

Melanjutkan dari proposal ini . Ini tampaknya merupakan proposal untuk beralih ke paket ganda dengan sumber CJS dan ESM lengkap yang menangani bahaya paket ganda dengan mengisolasi status di tempat lain ( pendekatan 2 ). Berbeda dengan menggunakan pembungkus ESM seperti RFC saya sebelumnya ( pendekatan 1 ).

Dengan asumsi itu, saya memiliki beberapa catatan tentang hal-hal yang belum disebutkan.

  • Anda tidak dapat memiliki paket Node.js di mana file ESM dan CommonJS menggunakan .js . Jika Anda menetapkan "type": "module" maka semua file CommonJS perlu menggunakan ekstensi file .cjs sebagai gantinya.
  • Bahaya paket ganda status dan kesetaraan bukan satu-satunya masalah dengan memiliki CJS dan ESM. Memiliki potensi 2 versi dari paket yang sama yang dimuat juga meningkatkan jejak memori React dalam kasus tersebut, dan React bukanlah perpustakaan kecil. Ini bukan pemecah kesepakatan, tetapi perlu diingat.
  • Saya memang melihat potensi bahaya paket ganda selain status internal React. Misalnya jika implementasi kelas Component bukan bagian dari kode CJS tempat kita berbagi status dan sebagai gantinya merupakan bagian dari bundel CJS/ESM maka ada risiko pemeriksaan instanceof Component di berbagai perpustakaan pemecahan.

Anda tidak dapat memiliki paket Node.js di mana file ESM dan CommonJS menggunakan .js. Jika Anda mengatur "type": "module" maka semua file CommonJS harus menggunakan ekstensi file .cjs sebagai gantinya.

Ini berlaku untuk NodeJS (tetapi tidak untuk bundler), jadi file di direktori cjs harus diakhiri dengan .cjs .

Memiliki potensi 2 versi dari paket yang sama yang dimuat juga meningkatkan jejak memori React dalam kasus tersebut

Saya melihat bagaimana ini meningkatkan ukuran tarball yang diterbitkan ke npm, dan dengan demikian ukuran keseluruhan pada disk. Tapi saya tidak melihat bagaimana ini memengaruhi memori. Sejauh yang saya tahu, bundler dan NodeJS tidak membawa kode ke memori yang belum dimuat melalui import / require() . Bisakah Anda menjelaskan bagaimana jejak memori akan berubah?

Misalnya jika implementasi kelas Komponen bukan bagian dari kode CJS tempat kami berbagi status dan sebagai gantinya merupakan bagian dari bundel CJS/ESM, maka ada risiko instanceof pemeriksaan Komponen di berbagai perpustakaan rusak.

Salah satu solusi yang diusulkan ( 1 , 2 ) adalah membuat implementasi esm NodeJS menjadi antarmuka ESM yang memanggil kode CJS. Dengan begitu hanya ada satu definisi Component yang pernah digunakan di Node.js. Fase 1 dan Fase 2 tidak akan mengubah apa yang berjalan di NodeJS, jadi ini hanya akan berlaku untuk Fase 3.

Karena kami (webpack) baru-baru ini juga menambahkan dukungan bidang exports ke webpack 5, saya ingin memberikan 2 sen saya untuk topik ini:

  • Dokumen pekerjaan dalam proses ini memiliki banyak informasi tentang bidang exports mengenai webpack tetapi juga Node.js dan secara umum: https://Gist.github.com/sokra/e032a0f17c1721c71cfced6f14516c62
  • Ini adalah poin utama dibandingkan dengan Node.js:

    • webpack 5 juga menambahkan kondisi development dan production , yang sangat berguna untuk reaksi. ( process.env.NODE_ENV , sementara masih didukung, harus dihindari untuk kode frontend secara umum, khusus Node.js)

    • webpack (dan bundler lainnya) mendukung require("esm") , yang memungkinkan untuk menghindari masalah status ganda dengan selalu menggunakan ESM (bahkan untuk require() ). webpack telah memperkenalkan kondisi khusus untuk itu: module . Untuk versi CommonJs dan ESM ini harus mengekspor antarmuka yang sama. Saat ini tidak ada hal lain yang memiliki masalah dual-state selain Node.js. Saya tidak berharap kita akan melihat sesuatu di masa depan, karena ini sebagian besar merupakan masalah kompatibilitas mundur.

      Untuk kompatibilitas maksimum, saya akan merekomendasikan yang berikut:

package.json

{
    "type": "commonjs",
    "main": "index.js",
    "module": "esm/wrapper.js",
    "exports": {
        ".": {
            "node": {
                "development": {
                    "module": "./esm/index.development.js",
                    "import": "./esm/wrapper.development.js",
                    "require": "./cjs/index.development.js"
                },
                "production": {
                    "module": "./esm/index.production.min.js",
                    "import": "./esm/wrapper.production.min.js",
                    "require": "./cjs/index.production.min.js"
                },
                "import": "./esm/wrapper.js",
                "default": "./cjs/index.js"
            },
            "development": "./esm/index.development.js",
            "production": "./esm/index.production.min.js",
            "default": "./esm/index.production.min.js"
        },
        "./index": "./index.js",
        "./index.js": "./index.js",
        "./umd/react.development": "./umd/react.development.js",
        "./umd/react.development.js": "./umd/react.development.js",
        "./umd/react.production.min": "./umd/react.production.min.js",
        "./umd/react.production.min.js": "./umd/react.production.min.js",
        "./umd/react.profiling.min": "./umd/react.profiling.min.js",
        "./umd/react.profiling.min.js": "./umd/react.profiling.min.js",
        "./package.json": "./package.json"
    }
}

esm/package.json

Memungkinkan untuk menggunakan .js sebagai ekstensi di direktori ini. Atau .mjs dapat digunakan, tetapi ini dapat memiliki potensi efek samping saat alat memeriksa ekstensi. Jadi .js agar aman.

{
    "type": "module"
}

esm/wrapper.js

Pembungkus ini diperlukan untuk Node.js untuk menghindari masalah status ganda.

import React from "../cjs/index.js";
export const {
    Children,
    Component,
    ...,
    useState,
    version
} = React;
export { React as default };

cjs/index.js

Ini digunakan oleh Node.js ketika kondisi development dan production tidak didukung.

'use strict';

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./cjs/react.production.min.js');
} else {
  module.exports = require('./cjs/react.development.js');
}

esm/wrapper.development.js (esm/wrapper.production.min.js serupa)

Pembungkus ini diperlukan untuk Node.js untuk menghindari masalah status ganda.
Mereka hanya digunakan setelah Node.js menambahkan kondisi development dan production .

import React from "../cjs/index.development.js";
export const {
    Children,
    Component,
    ...,
    useState,
    version
} = React;
export { React as default };

index.js

Untuk kompatibilitas mundur.

module.exports = require('./cjs/index.js');

esm/index.development.js, esm/index.production.min.js

Ini digunakan oleh alat yang mendukung bidang exports , kondisi module dan kondisi production / development .

/* React in ESM format */

// compat for the default exports with support for tree-shaking
import * as self from "./esm/index.development.js";
export { self as default }

Hasil

  • webpack 5: ./esm/index.development.js atau ./esm/index.production.min.js
  • browserify: ./cjs/index.js
  • webpack 4 dari .mjs: ./cjs/index.js
  • bundler lain: ./esm/wrapper.js
  • Node.js (ESM): ./cjs/index.js (wajib) atau ./esm/wrapper.js (impor)
  • Node.js (lama): ./cjs/index.js
  • Node.js (ESM + dev/prod): ./esm/wrapper.development.js atau ./esm/wrapper.production.min.js untuk impor, ./cjs/index.development.js atau ./cjs/index.production.min.js untuk kebutuhan

Catatan

Tidak ada esm/index.js karena memilih versi secara kondisional tidak mungkin dilakukan di ESM tanpa pengorbanan besar.
Alat hanya dapat memperoleh manfaat sepenuhnya dari reaksi ESM ketika mereka mendukung bidang exports , kondisi module (karena masalah status ganda) dan production / development condition (karena masalah impor bersyarat).

Alat dapat memperoleh manfaat sebagian dari reaksi ESM ketika mereka mendukung bidang module atau bidang exports .

import { useState } from "react" atau import * as React from "react" secara teknis ilegal selama reaksinya adalah modul CommonJs.
Sebagian besar perkakas masih mendukungnya untuk kompatibilitas mundur, tetapi beberapa tidak, misalnya Node.js
Jadi saat ini satu-satunya cara untuk menggunakan reaksi yang valid di mana-mana adalah: import React from "react" .
Cara ini harus tetap didukung, jika tidak akan ada kasus (misalnya Node.js 14) di mana tidak ada sintaks yang valid dalam reaksi sekarang dan reaksi setelah penambahan ESM.

Node.js menolak penambahan kondisi development / production untuk exports untuk saat ini.
Itu menyedihkan, dan saya masih berharap yang terbaik bahwa mereka akhirnya akan menambahkan itu.
Itu sebabnya dukungan untuk itu disiapkan di bidang exports atas.

@sokra bagus sekali, sangat membantu, terima kasih!

Satu pertanyaan kecil:

Node.js menolak penambahan kondisi pengembangan/produksi untuk ekspor untuk saat ini.

pemahaman saya adalah bahwa itu masih sedang dikerjakan? https://github.com/nodejs/node/pull/33171 tapi mungkin saya salah memahami PR itu

[sunting] PR di atas yang saya tautkan telah digantikan oleh https://github.com/nodejs/node/pull/34637

[sunting2] dan sekarang telah digabungkan menjadi nodejs

Terima kasih @sokra , itu saran yang sangat membantu.

Berikut adalah opsi yang saya lihat. Tampaknya semuanya secara teknis mungkin, dan keputusan itu lebih merupakan salah satu strategi daripada implementasi teknis:

Pilihan 1

Tambahkan export default React ke build ESM React 17, dan hapus setelah dukungan CJS untuk import React from 'react' dihentikan (mungkin di React 18?).

pilihan 2

Jangan tambahkan export default React , dan buat build React 17 ESM hanya dengan ekspor bernama.

Opsi 3

Jangan mempublikasikan build React 17 ESM. (😢) Tunggu hingga dukungan import React from 'react'; dihentikan sebelum membuat build ESM.

Perbandingan

| | Opsi 1 | Opsi 2 | Opsi 3 |
| - | -------- | -------- | -------- |
| Bangunan ESM yang tidak direferensikan | v17 | v17 | v18+ |
| package.json "modul" (penggoyangan pohon secara default) | v17 | v18+ | v18+ |
| package.json "type" / "exports" (NodeJS menggunakan ESM) | v18+ 1 | v18+ | v18+ |

  1. Dimungkinkan untuk mengimplementasikan package.json type/exports dengan cara yang sepenuhnya kompatibel, dalam hal ini dapat menjadi bagian dari React 17 jika Opsi 1 dipilih.

Preferensi saya adalah menuju Opsi 1, seperti yang sudah saya jelaskan di atas. Namun, Opsi 2 juga cukup menarik bagi saya. Opsi 3 tentu saja kurang seru. Dari apa yang saya kumpulkan dalam edisi github ini, kami memiliki keahlian teknis untuk mewujudkan semua ini (dan mungkin bahkan tenaga kerja!).

Reaksi awal untuk masalah ini adalah, mengapa masalah ini terbuka bahkan setelah 3 tahun ? Setelah membaca sebagian, masuk akal mengapa butuh waktu lama. Mempertahankan perpustakaan seperti React adalah tugas besar. Jadi

Mengingat berita terbaru dengan React 17, saya telah memperbarui komentar saya sebelumnya ke referensi React 17 alih-alih 16 untuk rencana masa depan.

Saya akan menghargai umpan balik dari orang-orang tentang mana dari tiga opsi di atas yang lebih disukai.

Saya pikir kita bisa menambahkan bidang exports di package.json di React 17, kita mungkin bisa mem-backportnya ke versi sebelumnya juga:

{
  "exports": {
    ".": {
      "development": "./esm/react.development.mjs",
      "production": "./esm/react.production.mjs",
      "node": {
        "import": "./esm/react.node.mjs",
        "require": "./index.js"
      },
      "default": "./index.js"
    },
    "./jsx-dev-runtime": {
      "development": "./esm/react-jsx-dev-runtime.development.mjs",
      "production": "./esm/react-jsx-dev-runtime.production.mjs",
      "node": {
        "import": "./esm/react-jsx-dev-runtime.node.mjs",
        "require": "./jsx-dev-runtime.js"
      },
      "default": "./jsx-dev-runtime.js"
    },
    "./jsx-runtime": {
      "development": "./esm/react-jsx-runtime.development.mjs",
      "production": "./esm/react-jsx-runtime.production.mjs",
      "node": {
        "import": "./esm/react-jsx-runtime.node.mjs",
        "require": "./jsx-runtime.js"
      },
      "default": "./jsx-runtime.js"
    },
    "./": "./"
  },
}

Kami membutuhkan bundel esm baru, meskipun itu seharusnya tidak terlalu sulit untuk ditambahkan dengan rollup.

  • Bundel ./esm/react.development.mjs dan ./esm/react.production.mjs harus bebas dari process.env.NODE_ENV cek:

    • kondisi diselesaikan pada waktu impor/bundel melalui bidang exports .

    • process adalah API simpul, tidak masuk akal di lingkungan browser, dan tidak didukung oleh _default_ oleh webpack 5 misalnya.

  • ./esm/react.node.mjs akan menyimpan cek process.env.NODE_ENV .
  • AFAIK hanya webpack 5 dan node mendukung bidang exports sekarang.

Saya pikir ini agak aman untuk ditambahkan, WDYT?

https://webpack.js.org/guides/package-exports/
https://nodejs.org/dist/latest-v15.x/docs/api/packages.html

"./": "./" membuatnya aman, ya, tetapi juga mencegah enkapsulasi apa pun, jadi Anda ingin menghapusnya segera setelah Anda memiliki semver-major.

Babel FWIW menampilkan impor runtime jsx baru sebagai

import { jsxs, jsx, Fragment } from 'react/jsx-runtime';

tetapi jika Anda memuat modul seperti itu di Node, itu akan mengeluh tentang kurangnya ekstensi file:

> node .\node.mjs
node:internal/process/esm_loader:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'test\node_modules\react\jsx-runtime' imported from test\node_modules\react-data-grid\lib\bundle.js
Did you mean to import react/jsx-runtime.js?
    at new NodeError (node:internal/errors:259:15)
    at finalizeResolution (node:internal/modules/esm/resolve:307:11)
    at moduleResolve (node:internal/modules/esm/resolve:742:10)
    at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:853:11)
    at Loader.resolve (node:internal/modules/esm/loader:85:40)
    at Loader.getModuleJob (node:internal/modules/esm/loader:229:28)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:51:40)
    at link (node:internal/modules/esm/module_job:50:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Menambahkan exports akan memperbaikinya

@nstepien memberikan peta exports seperti yang Anda tunjukkan di posting sebelumnya bukanlah pilihan dari apa yang saya yakini. Apa yang diimplementasikan node terkait interop cjs dan hal-hal lainnya tidak terlalu cocok dengan ekosistem yang ada. Bahaya paket ganda itu nyata - terutama untuk paket seperti Reac yang membutuhkan satu salinannya.

Peta exports dengan file commonjs saja berpotensi ditambahkan tanpa merusak apa pun tetapi juga harus dilakukan dengan ekstra hati-hati dan dengan tes e2e yang sesuai untuk ini (mengingat betapa rumitnya hal-hal yang harus diperbaiki)

@Andarist berfungsi dengan baik, dan tidak berbeda dalam kasus reaksi, yang selalu memiliki bahaya itu dan ekosistem menyelesaikannya dengan menjadikan reaksi sebagai rekan sejawat di mana-mana. Peta "ekspor" dapat berfungsi dengan baik di sini, selama file ESM dan file CJS memiliki status yang sama - yang dapat dicapai dengan menulis pembungkus ESM sederhana.

Jika semua dependensi, transitif atau tidak, dari React berada di bawah kendali React (yang dalam hal ini mereka) dan titik masuk ESM dari semuanya hanya mengekspor ulang konten CJS maka Anda - mungkin itu dapat dicapai dalam kasus khusus ini.

Masih ada drama keseluruhan tentang bentuk sebenarnya dari entri ESM (bernama, default, keduanya):

  • bernama-saja: tidak benar-benar kompatibel ke belakang karena banyak kode di luar sana menggunakan import React from 'react' , yang juga merupakan satu-satunya cara untuk benar-benar mengimpor React di node sekarang saat menggunakan ESM
  • default-only: tidak benar-benar kompatibel ke belakang karena banyak kode kami di sana menggunakan import * as React from 'react' , ini sering dipromosikan oleh pemeriksa tipe dan alat lainnya
  • keduanya: satu-satunya cara untuk membuatnya sepenuhnya kompatibel ke belakang, sehingga dapat bekerja dengan semua gaya pemuatan saat ini dan saat menggabungkan modul ESM & CJS di seluruh pohon ketergantungan

Saya terus-menerus melupakan kemungkinan pembungkus ESM karena mereka merasa seperti curang tetapi juga karena teknik ini hanya berfungsi jika Anda mengontrol semua dependensi Anda dan tidak dapat benar-benar digunakan sebagai strategi universal yang akan "berhasil"

Saya khawatir satu-satunya strategi universal untuk menyediakan keduanya adalah, pada kenyataannya, memiliki semua kode Anda yang sebenarnya di CJS, dan menulis pembungkus ESM di sekitarnya untuk memberikan ekspor bernama. Kode yang tidak stateful atau bergantung pada identitas dapat ditulis secara asli di keduanya, tetapi itu adalah bagian, peringatan.

jsx-runtime bukan stateful kan? Seharusnya aman untuk mengirim esm/cjs tanpa pembungkus untuk itu.

Haruskah saya mencatat masalah terpisah untuk mengimpor react/jsx-runtime di esm node?

Untuk paket frontend, tantangan ekstra bergabung dengan bahaya status ganda: sebut saja bahaya bundel ganda.

Saat mengekspor versi ESM dan CJS dan paket digunakan melalui require dan import , kedua versi akan dibundel dan menggandakan ukuran bundel efektif untuk paket tersebut.

@sokra apakah itu mungkin dalam praktik? Misalnya dengan rollup saya akan berasumsi bahwa karena modul cjs diubah menjadi modul esm, maka ia akan lebih suka mengimpor modul esm bila tersedia.

Ini mungkin dalam praktiknya untuk bundler yang mengikuti semantik node - seperti webpack 5. Penting untuk mencocokkan semantik karena jika tidak, Anda berpotensi mengalami hasil yang berbeda saat berjalan di node dan saat menjalankan kode bundel.

Namun, webpack 5 menangani kondisi "module" yang digunakan untuk menghapus duplikat esm/cjs (yang berasal dari peta ekspor).

Jika kami mempertimbangkan proposal @ ljharb, ini tidak terlalu relevan karena dia mengusulkan bahwa file esm bisa jadi hanya beberapa baris kode pembungkus yang hanya akan mengekspor ulang file cjs.

Dengan pembungkus ESM yang tipis, tidak ada bahaya tambahan, dengan atau tanpa bundler - hanya yang normal yang dihindari rekan sejawat tentang penipuan dalam grafik.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat