React: إضفاء الطابع الرسمي على الصادرات ES عالية المستوى

تم إنشاؤها على ٩ نوفمبر ٢٠١٧  ·  104تعليقات  ·  مصدر: facebook/react

لا نشحن حاليًا سوى إصدارات CommonJS من جميع الحزم. ومع ذلك ، قد نرغب في شحنها كـ ESM في المستقبل (https://github.com/facebook/react/issues/10021).

لا يمكننا القيام بذلك بسهولة لأننا لم نقرر حقًا الشكل الذي ستبدو عليه صادرات المستوى الأعلى من ES من كل حزمة. على سبيل المثال ، هل يحتوي react على مجموعة من الصادرات المسماة ، ولكن أيضًا تصدير افتراضي يسمى React ؟ هل يجب أن نشجع الناس على import * لتحسين اهتزاز الأشجار؟ ماذا عن react-test-renderer/shallow الذي يقوم حاليًا بتصدير فئة (وبالتالي سيبدأ الفشل في Node إذا تم تحويله ليكون تصديرًا افتراضيًا)؟

Build Infrastructure React Core Team Breaking Change Discussion

التعليق الأكثر فائدة

إنه عام 2020 تقريبًا الآن ، أود أن أعرف ما إذا كانت هناك أية تحديثات من فريق FB الرسمي؟ هل سيكون هناك أي تغييرات متعلقة بهذا في React v17؟

ال 104 كومينتر

Imho import * هو وسيلة للذهاب ، وأنا لا أعارض الحصول على تصدير افتراضي أيضًا ، ولكن لا ينبغي استخدامه لإعادة تصدير أشياء أخرى كما في هذا المثال:

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

ولكن لا ينبغي استخدامه لإعادة تصدير أشياء أخرى مثل هذا المثال:

هل هناك سبب تقني لماذا؟ (بصرف النظر عن وجود طريقتين لفعل الشيء نفسه).

انطباعي هو أن الأشخاص الذين يستوردون * (ولا يستخدمون الافتراضي) لن يواجهوا مشاكل في اهتزاز الشجرة لأن الافتراضي سيظل غير مستخدم. ولكن ربما أبالغ في تقدير التراكمي وما إلى ذلك.

ربما يمكن الإجابة على هذه الأسئلة بشكل أفضل من خلالlukastaegert. لست متأكدًا مما إذا كان هناك شيء قد تغير منذ https://github.com/facebook/react/issues/10021#issuecomment -335128611

كما أن Rollup ليس هو شاكر الشجرة الوحيد الموجود هناك ، وعلى الرغم من أن خوارزمية اهتزاز الشجرة الخاصة بـ webpack أسوأ من تلك الموجودة في التجميع ، فمن المحتمل أن يكون الاستخدام أعلى بكثير من أداة التجميع (كلتا الأداتين تؤديان وظائف ممتازة ، لا أريد الإساءة إلى أي شخص ، فقط ذكر الحقائق) وإذا كان بإمكاننا (كمجتمع) مساعدة كلتا الأداتين في وقت واحد ، فيجب علينا القيام بذلك كلما أمكننا ذلك.

هل اهتزاز الشجرة سيفعل أي شيء في حالة React ، بالنظر إلى أن كل شيء مُعالج مسبقًا في حزمة مسطحة واحدة؟ أتساءل ما هو نمط الاستيراد الأساسي لـ React ، فأنا شخصياً أميل إلى معاملته على أنه تصدير افتراضي ، على سبيل المثال React.Component ، React.Children لكن أحيانًا أفعل الشيء المسمى بـ cloneElement

كما ذكر gaearon بالفعل في مكان آخر ، من المتوقع أن تكون تحسينات الحجم في حالة رد الفعل ضئيلة. ومع ذلك ، هناك مزايا:

  • رد الفعل: من المحتمل أن يتم إخراج الأطفال في بعض الحالات (لذلك سمعت 😉)
  • يمكن رفع React نفسها إلى النطاق العلوي بواسطة حِزم الوحدات التي تدعم ذلك. يمكن أن يؤدي هذا مرة أخرى إلى إزالة عدد غير قليل من البايتات وقد يمنح أيضًا تحسينًا طفيفًا في الأداء. يكمن التحسين الرئيسي في حقيقة أنه لا يلزم وجود متغير آخر يشير إلى React.Component لكل وحدة ولكن فقط واحد يتم مشاركته في كل مكان (هذه هي الطريقة التي يقوم بها التجميع عادةً). أيضًا ، على الرغم من أن هذا مجرد تخمين ، فقد يقلل هذا من فرصة إنقاذ الوحدة النمطية لـ webpack
  • يعد التحليل الثابت للتفاعل أسهل ليس فقط لمجمعات الوحدات النمطية ولكن أيضًا على سبيل المثال IDEs والأدوات الأخرى. تقوم العديد من هذه الأدوات بالفعل بعمل معقول في هذا المجال لوحدات CJS ولكن في النهاية ، هناك الكثير من التخمينات من جانبهم. مع وحدات ES6 ، يكون التحليل أمرًا لا يحتاج إلى تفكير.

بالنسبة لنوع الصادرات ، بالطبع فقط التصدير المسمى يوفر حقًا ميزة اهتزاز الأشجار بسهولة (ما لم تستخدم GCC التي قد تكون قادرة على فعل المزيد في حركتها العدوانية وربما أحدث مجموعة إذا كنت محظوظًا حقًا) . من الصعب تحديد السؤال إذا كنت تقدم تصديرًا افتراضيًا أيضًا:

  • PRO: ترحيل غير مؤلم لقواعد أكواد ES6 الحالية (على سبيل المثال ، ما يصفه jquense )
  • CON: نظرًا لأن كل شيء مرتبط بكائن مشترك ، فبمجرد تضمين هذا الكائن ، يتم تضمين جميع مفاتيحه مرة واحدة مما يؤدي مرة أخرى إلى هزيمة أي محاولات لهز الشجرة. حتى دول مجلس التعاون الخليجي قد تمر بأوقات عصيبة هنا.

كإستراتيجية ترحيل ذات نسختين ، يمكنك إضافة تصدير افتراضي في الإصدار التالي لأغراض التوافق الذي تم الإعلان عنه أنه مهمل (قد يعرض تحذيرًا عبر أداة تجميع وما إلى ذلك) ثم إزالته في إصدار لاحق.

هذه أيضًا حالة مثيرة للاهتمام: https://github.com/facebook/react/issues/11526. في حين أن لعبة monkeypatching للاختبار مظللة بعض الشيء ، فإننا نريد أن نكون مدركين لكسر هذا (أو وجود حل بديل له).

أتيت هنا عبر محادثة Twitter هذه . بالنسبة لي ، هناك إجابة صحيحة وواضحة على هذا السؤال: يجب على React و ReactDOM فقط تصدير الصادرات المسماة. إنها ليست كائنات تحتوي على حالة ، أو أن المكتبات الأخرى يمكنها أن تحور أو تُلحق خصائص بها (على الرغم من 11526 #) - السبب الوحيد لوجودها هو مكان "وضع" Component ، createElement وهلم جرا. بمعنى آخر ، مساحات الأسماء ، التي يجب استيرادها على هذا النحو.

(كما أنه يجعل الحياة أسهل للمجمعين ، لكن هذا ليس هنا ولا هناك.)

بالطبع ، هذا يمثل تغييرًا جذريًا للأشخاص الذين يستخدمون حاليًا استيرادًا وترجمة افتراضيًا. ربما يكون لدى lukastaegert الفكرة الصحيحة هنا ، باستخدام

لكن ليس لدي اقتراح جاهز لـ # 11526. ربما ينتظر شحن ESM الإصدار 17 لهذا السبب على أي حال ، وفي هذه الحالة لن يكون هناك داعٍ للقلق بشأن تحذيرات الإيقاف.

لقد أصبح الناس يحبون حقا

import React, { Component } from 'react'

لذلك قد يكون من الصعب إقناعهم بالتخلي عنها.

أعتقد أن هذا ليس سيئًا للغاية ، حتى لو كان غريبًا بعض الشيء:

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

للتوضيح ، نحتاج إلى أن يكون React في النطاق (في هذه الحالة ، كمساحة اسم) لأن JSX تنتقل إلى React.createElement() . يمكننا كسر JSX والقول إنها تعتمد على وظيفة jsx() بدلاً من ذلك. ثم ستبدو الواردات كما يلي:

import {jsx, Component} from 'react';

وهو ما قد يكون مقبولًا ولكنه تغيير كبير. قد يعني هذا أيضًا أن تصميمات React UMD تحتاج الآن إلى تعيين window.jsx أيضًا.

لماذا أقترح jsx بدلاً من createElement ؟ حسنًا ، createElement مثقل بالفعل ( document.createElement ) وعلى الرغم من أنه لا بأس به مع مؤهل React. ، بدون المطالبة به على المستوى العالمي ، فإن هذا مبالغ فيه. Tbh أنا لست متحمسًا جدًا لأي من هذين الخيارين ، وأعتقد أن هذا سيكون على الأرجح أفضل حل وسط:

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

واستمر في تحويل JSX إلى React.createElement افتراضيًا.

اعتراف: لقد وجدت دائمًا أنه من الغريب أن تضطر صراحة إلى استيراد React أجل استخدام JSX ، على الرغم من أنك لا تستخدم هذا المعرف في أي مكان. ربما في المستقبل ، يمكن لـ transpilers إدخال import * as React from 'react' (قابل للتكوين من أجل Preact وما إلى ذلك) عند مواجهة JSX ، إذا لم يكن موجودًا بالفعل؟ بهذه الطريقة ما عليك سوى القيام بذلك ...

import { Component } from 'react';

... وسيتم الاهتمام باستيراد مساحة الاسم تلقائيًا.

في المستقبل البعيد ، ربما. في الوقت الحالي ، نحتاج إلى التأكد من أن المحولات تعمل مع أنظمة الوحدات الأخرى (CommonJS أو globals). إن جعل هذا التكوين قابلاً للتكوين يمثل أيضًا عقبة ، ويؤدي إلى مزيد من الانقسام في المجتمع.

ما اقترحه @ Rich-Harris (إدراج استيراد معين عند استخدام jsx) يتم تنفيذه بسهولة عن طريق البرنامج المساعد transpilers. سيتعين على المجتمع ترقية babel-plugin-transform-react-jsx وهذا كل شيء. وبالطبع ستظل الإعدادات الحالية تعمل إذا قام أحدها فقط بإضافة import * as React from 'react'; إلى الملف.

بالطبع نحن بحاجة إلى التفكير في أنظمة الوحدات النمطية الأخرى ، لكن لا يبدو أنها مشكلة صعبة الحل. هل هناك أي مشاكل معينة في الاعتبار؟

بالطبع نحن بحاجة إلى التفكير في أنظمة الوحدات النمطية الأخرى ، لكن لا يبدو أنها مشكلة صعبة الحل. هل هناك أي مشاكل معينة في الاعتبار؟

لا أدري ، ما هو اقتراحك المحدد حول كيفية التعامل معه؟ هل سيكون الإعداد الافتراضي لملحق Babel JSX؟

لقد أصبح الناس يحبون حقا

import React, { Component } from 'react'

أي شعب؟ اخرج لكي استهزأ بك.

لقد فعلت ذلك كثيرًا 🙂 متأكد من أنني رأيت هذا في أماكن أخرى أيضًا.

الإعداد الافتراضي في الوقت الحالي هو React.createElement وسيظل كما هو. المشكلة الوحيدة هي أنه يفترض الآن عالميًا (أو متاحًا بالفعل في النطاق).

أعتقد أن وحدات es هي في الأساس الطريقة القياسية (على الرغم من أنها لم يتم اعتمادها من قبل الجميع) للقيام بالوحدات النمطية ، فمن المعقول افتراض أن الأغلبية (أو ينبغي) استخدامها. تستخدم الغالبية العظمى بالفعل أدوات بناء متنوعة لإنشاء حزمها - وهذا صحيح أكثر في هذه المناقشة لأننا نتحدث عن تحويل صيغة jsx . يعد تغيير السلوك الافتراضي للمكوِّن الإضافي jsx إلى الإدراج التلقائي لـ React.createElement في النطاق أمرًا معقولاً من imho. نحن في الوقت المناسب لهذا التغيير مع babel @ 7 قريبًا (-ish). مع الإضافة الأخيرة لـ babel-helper-module-imports أصبح من السهل أكثر من أي وقت مضى إدراج النوع الصحيح من الاستيراد (es / cjs) إلى الملف.

يبدو أن وجود هذا قابل للتكوين للإنقاذ إلى سلوك اليوم (بافتراض وجوده في النطاق) يبدو حقًا بمثابة تغيير طفيف في التكوين مطلوب لأقلية من المستخدمين وتحسين (بالتأكيد ، ليس تغييرًا كبيرًا - ولكن لا يزال) للأغلبية.

هل يجب أن نشجع الناس على الاستيراد * لتحسين اهتزاز الأشجار؟

بفضل alexlamsl ، ألغى uglify-es export default عقوبة

$ 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);

واو ، هذا جديد رائع 👏 هل uglify-es يعتبر مستقرًا الآن؟ أذكر أنك ذكرت قبل بضعة أشهر أنه لم يكن موجودًا بعد ، لكن يمكنني أن أتذكر ذلك بشكل غير صحيح ، لذا لست متأكدًا.

على أي حال - هذا كل شيء ولطيف في عالم التجميع ، ولكن بالنظر إلى أن React يتم تجميعه في الغالب في التطبيقات وأن تلك تستخدم في الغالب webpack والتي لا تقوم برفع النطاق افتراضيًا ، ما زلت أقول ذلك يجب تجنب تصدير كائن كإعداد افتراضي لمساعدة أدوات أخرى غير uglisy-es + rollup في جهودهم لإنتاج أحجام حزم أصغر. بالنسبة لي أيضًا ، من الأفضل تجنب ذلك من الناحية اللغوية - ما يفعله libs بالفعل في مثل هذه الحالات هو توفير مساحة اسم ويتم تمثيلها بشكل أفضل عند استخدام import * as Namespace from 'namespace'

هل تعتبر uglify-es مستقرة الآن؟

مستقر مثل أي شيء آخر في نظام JS البيئي. أكثر من 500 ألف تنزيل في الأسبوع.

هذا كل شيء ولطيف في عالم التجميع ، ولكن بالنظر إلى أن React مجمعة في الغالب في التطبيقات وأن تلك تستخدم في الغالب حزمة الويب التي لا تقوم برفع النطاق افتراضيًا

على أي حال ، إنه خيار. إعدادات Webpack الافتراضية ليست مثالية على أي حال - عليك استخدام ModuleConcatenationPlugin كما تعلم.

نضيف بضعة سنتات هنا:

  • أتفق تمامًا مع @ Rich-Harris على أن الصادرات المسماة من الناحية اللغوية هي الاختيار الصحيح
  • أنا حقًا لا أحب import React from 'react' أو import * as React from 'react' فقط لأتمكن من استخدام صيغة JSX. من وجهة نظري ، هذا التصميم ينتهك بوضوح مبدأ فصل الواجهة من حيث أنه يجبر المستخدمين على استيراد كل React لمجرد أن يكونوا قادرين على استخدام الجزء createElement (على الرغم من أنه من المسلم به أنه مع تصدير مساحة الاسم ، فإن مُجمِّع مثل Rollup سوف تجريد الصادرات غير الضرورية مرة أخرى)

لذلك إذا كنا في مرحلة قد نتخذ فيها قرارات تغيير جذري ، فإنني أنصح بتغيير ذلك بحيث تعتمد JSX على وظيفة واحدة (عالمية أو مستوردة). كنت سأدعوه createJSXElement() ، والذي في رأيي يصفه أفضل من createElement() ولم يعد بحاجة إلى سياق React ليكون منطقيًا. ولكن في عالم يكون فيه كل بايت مهمًا ، فمن المحتمل أن يكون jsx() جيدًا أيضًا.

سيؤدي هذا أيضًا في النهاية إلى فصل JSX عن React بطريقة يمكن للمكتبات الأخرى اختيار دعم JSX باستخدام نفس التحويل وتوفير وظيفة jsx . بالطبع لديك الكثير من المسؤولية هنا في توجيه عدد لا يحصى من التطبيقات الراسخة من خلال مثل هذا التحول ولكن من وجهة نظر معمارية ، أعتقد أن هذا هو المكان الذي يجب أن تتجه إليه React و JSX. يبدو أن استخدام Babel للقيام بالرفع الثقيل لمثل هذا التحول فكرة رائعة بالنسبة لي!

أنا شخصياً لا أرى مكاسب كبيرة في الترحيل إلى المساعد الفعلي jsx حيث يجب أن يقوم IMHO الافتراضي للمكوِّن الإضافي babel باستيراده من الحزمة react ، لذا فإن اسم المساعد الفعلي ليس حقًا المسألة - الباقي هو مجرد مسألة كونها قابلة للتكوين.

ربما يكون هذا عرضيًا بعض الشيء للمناقشة الرئيسية ، لكنني أشعر بالفضول إلى أي مدى تعمل وحدات ES بشكل جيد مع فحص process.env.NODE_ENV لتصدير حزم dev / prod بشكل مشروط؟ على سبيل المثال،

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

ربما أفتقد شيئًا واضحًا هنا ، لكنني أجد صعوبة في معرفة كيفية ترجمة هذا النمط إلى وحدات ES؟

NMinhNguyen الصادرات الشرطية غير ممكنة مع وحدات ES.

يمكن أن تكون الشيكات process.env.NODE_ENV على مستوى (رمز) أكثر تفصيلاً ، وتكون جاهزة لاستبدالها بالمجمع بالقيم المناسبة.

Andaristmilesj شكرا ليؤكد لي اشتباه :)

يمكن أن تكون الشيكات process.env.NODE_ENV على مستوى (رمز) أكثر تفصيلاً ، وتكون جاهزة لاستبدالها بالمجمع بالقيم المناسبة.

من منشور مدونة React 16 ، اعتقدت أن الشيكات process.env.NODE_ENV تم سحبها إلى الأعلى عمدًا (على عكس كونها أكثر دقة ، وهو ما هو موجود في المصدر ، إذا لم أكن مخطئًا ) ، للمساعدة في الأداء في Node.js؟

عرض أفضل من جانب الخادم

تتضمن React 16 عارض خادم تمت إعادة كتابته بالكامل. إنه سريع حقًا. وهو يدعم البث ، لذا يمكنك البدء في إرسال البايت إلى العميل بشكل أسرع. وبفضل استراتيجية التغليف الجديدة التي تجمع شيكات process.env (صدق أو لا تصدق ، قراءة process.env في Node بطيئة حقًا!) ، لم تعد بحاجة إلى تجميع React للحصول على خادم جيد- تقديم الأداء.

مثل ، لست متأكدًا من كيفية استخدام الحقل module في package.json والتمييز بين dev / prod لـ ESM مع الحفاظ على حزم ES ثابتة وعدم التأثير على أداء Node.js

مثل ، لست متأكدًا من كيفية استخدام حقل الوحدة النمطية في package.json والتمييز بين dev / prod لـ ESM مع الحفاظ على حزم ES مسطحة وعدم التأثير على Node.js perf

هذا بالتأكيد عيب ، لأنه لا توجد طريقة قياسية في الوقت الحالي للقيام بذلك. OTOH إنها مجرد مسألة أدوات ، فمن الممكن (وهو سهل نوعًا ما) تجميع هذا في خطوات إنشاء تطبيقك حتى اليوم. سيكون من الأسهل أن تقوم الحزمة بكشف تصميمات dev / prod وأن المحلل سيعرف فقط أي واحد يختار ، ولكن ربما يكون هذا مجرد مسألة دفع هذه الفكرة لمؤلفي الأدوات.

للصف:

import Component from 'react/Component'

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

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

حيث سيستخدم التحويل super.createElement () للتحويل إلى jsx أو استخدام مكون ثابت.

للمكونات عديمة الحالة:

import jsx from 'react/jsx'

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

من الممكن استخدام قالب حرفي بعلامات تمييز؟

نأمل أن تقبل العقدة هذه العلاقات العامة https://github.com/nodejs/node/pull/18392

نحن نتفق هنا مع @ Rich-Harris.

مجرد إسقاط تعليق على هذا الموضوع الذي لم يتم ذكره على وجه التحديد.

أنا في موقف لا أستخدم فيه أداة تجميع على الإطلاق وأريد فقط استيراد تفاعل ومكونات مختلفة للاستخدام محليًا من خلال المتصفح ( <script type="module" src="..."> ) ، أي

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')
);

مما يمكنني قوله ، هذا غير ممكن اليوم. بدلاً من ذلك ، يجب أن أقوم بتضمين إصدار UMD من رد الفعل عبر علامة <script> من CDN ثم افترض وجودها على النافذة في أي وحدة <script type="module"> أكتبها:

// 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 {...}

سيكون الحصول على تفاعل استيراد من CDN أمرًا رائعًا. سيجعل النماذج الأولية في المتصفح سريعة وسهلة للغاية مع الاستمرار في الحفاظ على فصل الملفات. كان أحد الأشياء التي شعرت دائمًا أنني كنت أضحي بها عند استخدام React بدون مجمّع هو القدرة على فصل المكونات (ووظائف المرافق الأخرى ، إلخ) حسب الملف. ولكن الآن مع دعم المتصفح لوحدات ES الأصلية ، يمكنني كتابة مكونات React الخاصة بي في ملفات منفصلة وجعل المتصفح يستهلكها كما هو مكتوب. من المسلم به أنه إذا لم أكن أستخدم JSX ، ولكن حتى لو كنت أستخدم JSX ، يمكنني نقل جميع الملفات في مكانها عبر خطوة بناء وستظل جميع عمليات الاستيراد الخاصة بي تعمل في المتصفح.

// /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, ...)
}

أنا متأكد من أن بعض الأشخاص قد يجادلون بأن كتابة عنوان URL لـ CDN يمثل مشكلة طوال الوقت (مشكلة يحاول بعض الأشخاص إصلاحها) ولكن المقايضات تستحق العناء بالنسبة لي. يعد تغيير / تحديث عنوان url هذا بحثًا / استبدالًا بسيطًا. بالنسبة لحالة الاستخدام الخاصة بي ، فإن هذا يفوق مشكلة إعداد مجمع.

إذا كان لدى React دعم لشيء كهذا ، فلن تكون هناك حاجة للأدوات. أنا فقط أستخدم المتصفح. يمكنني إرسال رمز مثل هذا في عدد قليل من المشاريع الشخصية التي تفترض المتصفحات الحديثة واستخدام التفاعل كتحسين تدريجي على الصفحة. ما يجعل هذا رائعًا هو عندما أعود إلى قاعدة التعليمات البرمجية في 12 شهرًا ، لست مضطرًا لتغيير مجموعة من واجهات برمجة التطبيقات للأدوات أو حتى NPM كمدير للحزم. أنا فقط أستخدم واجهات برمجة التطبيقات من المتصفح ، ولا شيء آخر.

FWIW: إذا / عندما تتفاعل يفعل السفينة مع دعم من هذا القبيل، وأعتقد أنه يمكن أن يكون قيما جدا لاظهار كيف يمكن استخدام رد فعل من هذا القبيل في مستندات والتعليم التي يمكنك الاستفادة من رد فعل ونموذج مكون من خلال فصل كل منطق المكونات عبر لها ملفك الخاص ولا تحتاج إلى أداة تجميع للقيام بذلك ، ما عليك سوى استخدام <script type="module"> الأصلي ، واستيراد React من CDN (أو نسختك المحلية) ، وإيقاف تشغيلك! "

الآن ، تدعم جميع المتصفحات الحديثة بما في ذلك إصدارات الأجهزة المحمولة ESM. لم تعد ESM نظامًا نموذجيًا مستقبليًا بل أصبحت معيارًا فعليًا حاليًا.

يرجى الانتباه إلى أن عدم توفير الوحدة الموحدة يمثل مشكلة حرجة ، خاصة بالنسبة لمكتبة الويب المعيارية الفعلية.

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

هذا هو الكود النموذجي لتطبيق مكتبات React ، والحقيقة أنه لا توجد مكتبات يمكن استيرادها ، بدلاً من ذلك ، تحاكي محولات ومجمعات الطرف الثالث عملية الاستيراد.

لقد تم تبرير عدم توفير ESM الحقيقي نظرًا لأن المتصفحات لم تدعم ESM الأصلي على أي حال ، ولكن من الواضح أن الوقت قد انتهى ، والآن حان الوقت لتقديم ESM كما هو محدد في نموذج الكود النموذجي إلى import .

لقد بدأت العمل على هذا هنا وهنا

TrySound شكرا
هل يوجد مكان للاستيلاء على تصميم ESM واختباره؟

إنه جاهز فقط لحزمة رد الفعل.

تضمين التغريدة
حسنًا ، لقد وجدت فرعك https://github.com/TrySound/react/tree/react-is-esm ، وقمت ببناءه ، والآن أعرف ما تعنيه. نتطلع إلى react-dom أيضًا.

أعتقد أن مجتمع React ناقش هذه المسألة بما يكفي لفترة من الوقت.
https://discuss.reactjs.org/t/es6-import-as-react-vs-import-react/360/

يرجى تحديد مواصفات الوحدة النمطية ES6 الرسمية ، والنشر قريبًا.

kenokabe نحن في الطريق. لا تجبرنا من فضلك. الأمر ليس بهذه السهولة.

تعمل الخطة الحالية على ترحيل جميع الحزم ذات عمليات التصدير المسماة فقط. لن يؤثر هذا التغيير على رمز المكتبات ويجب ألا يُدخل تغييرات فاصلة لأن المستندات تستخدم عمليات تصدير مسماة أيضًا.

بالنسبة للحزم الأخرى ، نحتاج إلى التعامل مع الصادرات الافتراضية والمسمية التي تعمل بشكل مختلف مع الأدوات المختلفة.

TrySound اعتذاري.
لم أقصد لكم ، حيث أن العنوان الرئيسي لهذا الموضوع هو

لا يمكننا القيام بذلك بسهولة لأننا لم نقرر حقًا الشكل الذي ستبدو عليه صادرات المستوى الأعلى من ES من كل حزمة. على سبيل المثال ، هل يحتوي رد الفعل على مجموعة من عمليات التصدير المسماة ، ولكن أيضًا تصدير افتراضي يسمى React؟ هل يجب أن نشجع الناس على الاستيراد * لتحسين اهتزاز الأشجار؟

واليوم المذكور منذ فترة ، وأعتقد أنه تمت مناقشته في مجتمع React ، لذلك أردت أن أقترح أن القرار سيكون واضحًا. شكرا!

هل تريد الحصول على بعض التحديثات حول هذا ...

أنا أستخدم webpack v4 لتجميع تطبيقنا ، بينما يقترح علي IDE intellisense (WebStorm) استخدام import * as React from 'react'; بينما يطلب مني زميلي في العمل تغيير import React from 'react'; في مراجعة الكود. كلاهما يعمل بشكل جيد لذلك اعتقدت أنه يقول بعض الهراء ، لكن لجعله سعيدًا ، سأغيره على أي حال. هذا أيضًا كيف أجد هذا الموضوع.

بدافع الفضول ، أقارن الاختلافات في حجم الإصدار النهائي بينهما (باستخدام React 16.8.1):

في import * as React from 'react'; : 6،618،723 بايت
في import React from 'react'; : 6،619،077 بايت

لذا من الواضح أن لديها بعض الاختلافات ، على الرغم من كونها هامشية. (ملاحظة. لقد فعلت الشيء نفسه مع propTypes )

إذا فهمت في هذا الموضوع بشكل صحيح ، فسيكون من الأفضل أن يكون لديك import * as React from 'react'; ، أليس كذلك ؟! لأنه (1) نعم ، لقد وفر بعض الحجم ؛ (2) ESM هي طريقة موحدة لذلك لا مزيد من بقايا CJS. إذا كان هذا هو الحال ، أود تغيير هذا اليوم والتوافق مع IDE الخاص بي.

leoyli على المدى الطويل نعم. ولكن أولاً سيكون هناك عمليات تصدير مسماة وافتراضية حتى لا تكسر الكود الحالي.

لقد أخذت الأمور بين يدي هنا ، إلى حد ما كتجربة لأنني لم أعد أستخدم مجمّعًا في مشاريعي وأردت الاستمرار في استخدام التفاعل (مباشرة من unpkg.com كما يمكنك مع مكتبات أخرى مثل Vue و Hyperapp وما إلى ذلك) . هذا ما توصلت إليه ، لا شيء رائع ، مجرد يد تم تحريرها أمد:

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

وحدة ES6 تعرض أحدث إصدار من React و ReactDOM

كما هو موضح في README ، هذا في الغالب عبارة عن POC ولكن بالنسبة للأشخاص الذين لا يستطيعون الانتظار حتى يصل هذا البناء ، فهو عبارة عن بناء 16.8.3 يتضمن خطافات ، تشويق ، كسول وما إلى ذلك ويعمل كما هو متوقع من خلال القيام بما يلي:

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

ربما سيجد البعض منكم في هذا الموضوع أنه مفيد .. شخصيًا لقد كنت أستخدم هذا الأسلوب لإنشاء مشروع مبتدئ للتفاعل وخالي من البناء . كما أنه لا يزال قيد التنفيذ.

lukejacksonn لقد https://github.com/wearespindle/react-ecmascript ويمكنك أيضًا تحميله من unpkg https://unpkg.com/react-ecmascript/

@ PM5544 يا نجاح باهر .. هذا هو الحل أشمل بكثير من لي! عمل رائع 💯

رهيبة @ PM5544. احب ان اسمع المزيد عنها يوما ما. ربما ظهر الضيف مرة أخرى في Xebia؟
لقد اعتمدت مؤخرًا حزمة لتجميع حزمتي مفتوحة المصدر ، والتي تدعم UNPKG.
هل يعرف أي شخص مقالًا جيدًا عن تبعيات التحميل من UNPKG مباشرةً بدلاً من استخدام أداة التجميع؟

أكتب حاليًا واحدة وسألقيها كمحادثة في React Norway في يونيو أيضًا!

TrySound هل كان هناك أي تحديث على هذا منذ فبراير؟ ما الذي تبقى لتحريك هذه المشكلة ، وهل يمكنني المشاركة في إنهاء هذه المشكلة ببعض أعمال الترميز؟ لقد وقعت بالفعل على CA ، ولدي الوقت المتاح اليوم للعمل عليها.

يجب دمج هذا أولاً https://github.com/facebook/react/pull/15037

TrySound حسنًا ، شكرًا لقد أرسلت عرضي للمساعدة في هذا الموضوع.

عندما تذهب مع تصدير React الافتراضي ، يمكنك اتباع هذا الأسلوب:

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

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

هذا يجعله قابلاً للتحليل بشكل ثابت أن التصدير الافتراضي هو كائن مساحة اسم يسمح بهز الشجرة لهذه التركيبات في حزمة الويب 5 والتجميع:

import React from "react";

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

التراكمي سيحب ذلك كثيرا

أنا في دردشة gitter التراكمية لمدة 1.5 سنة ويظهر هذا النوع من المشكلات كل أسبوعين أو نحو ذلك ...

راجع للشغل ، lukejacksonn قام بعمل هائل على مفترق es- reaction غير الرسمي ، يمكنه أن يوصي به بشدة.

راجع للشغل ، lukejacksonn قام بعمل هائل على مفترق es- reaction غير الرسمي ، يمكنه أن يوصي به بشدة.

أتساءل لماذا لا يفعل فريق FB الرسمي شيئًا حيال ذلك.

كنت آمل أيضًا أن يولد هذا بعض الضغط لدفع الأمور إلى الأمام ، وأعتقد أن lukejacksonn نفسه كان

كنت آمل هذا أيضا حقا. في الواقع ، تلقيت دعمًا من فريق رد الفعل في إنشاء الحزمة (إلى جانب بعض كلمات التشجيع اللطيفة منthreepointone). لقد ساعدني أحد الزملاء في Formidable مؤخرًا في إنشاء الحزمة بشكل برمجي ، وهو ما يعد تحسينًا عن القيام بذلك يدويًا في كل مرة يتم فيها إصدار إصدار جديد من رد الفعل ، ولكنه ينتج عنه إخراج أقل نظافة في علامة تبويب الشبكة ، لذلك لست متأكدًا مما إذا كان سيتم ذلك. ابق هكذا بعد. سوف نرى!

إنه عام 2020 تقريبًا الآن ، أود أن أعرف ما إذا كانت هناك أية تحديثات من فريق FB الرسمي؟ هل سيكون هناك أي تغييرات متعلقة بهذا في React v17؟

لأولئك الذين يحتاجون إلى وحدة ES محدثة React NOW ، جرب @pica/react ، وهو موجود بالفعل في الإصدار 16.13.x
https://www.npmjs.com/package/@pika/react
https://www.npmjs.com/package/@pika/react -dom
https://github.com/pikapkg/react

في المستقبل البعيد ، ربما.

حسنًا ، في المستقبل بالفعل. هل هو في المستقبل القريب الآن؟

gaearon ما هو مانع تحديد كيفية هيكلة الصادرات (التصدير الافتراضي مقابل الصادرات المسماة)؟ هل هناك أي شيء يمكن للمجتمع أن يساعدك في اتخاذ هذا القرار؟

يبدو أن هذا القرار قد اتخذ بالفعل منذ فترة: # 18102. يمكن إغلاق هذه القضية الآن.

سأقدم تحديثًا صغيرًا عن هذا.

لا توجد عمليات تصدير افتراضية

تتمثل خطتنا النهائية في الابتعاد تمامًا عن عمليات التصدير الافتراضية:

import { useState } from 'react';

في هذا العالم، هذا لن يجدي نفعا:

import React from 'react'; // no

سيعمل هذا على الرغم من أنه صاخب بعض الشيء:

import * as React from 'react';

ولكن هذا هو الهدف. لن يكون هناك سبب حقيقي لاستيراد React على الإطلاق.

استيراد السيارات JSX

يرجع سبب استيراد الأشخاص لـ React اليوم إلى JSX. لكن lunaruan أنهى العمل على تحويل JSX

لذلك ستنتقل من هذا:

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

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

الى هذا:

import { useState } from 'react';

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

يقوم JSX بإدراج الاستيراد الصحيح تلقائيًا تحت الغطاء ، لذلك لا حاجة إلى النطاق React .
وهذا ما يجعل التحرك لإزالة الصادرات الافتراضية أمرًا مقبولاً. أنت فقط لا تحتاجهم كثيرًا.

وحدات ES

يعد نشر ESM خارج نطاق شريحة صغيرة عامة من المتحمسين أمرًا صعبًا. النظام البيئي الواسع ليس جاهزًا حقًا وهناك الكثير من الطرق التي تسوء فيها الأمور مع مجموعات الأدوات المختلفة. إن الطريقة التي يتفاعل بها CJS و ESM معقدة للغاية ، وهذا التداخل (وكيف يفشل) هو مصدر معظم هذه المشكلات.

لذا فإن تفكيرنا الحالي هو أنه عندما نذهب ESM ، قد نرغب في تجربة ESM على طول الطريق. لا يوجد CJS على الإطلاق - أو منفصل في حزمة قديمة متوافقة. لن يحدث هذا في React 17 ومن غير المرجح أن يحدث في 18 ، لكن من المعقول تجربته في React 19.

لأي شخص يبحث عن بديل لبناء ESM @pika/react ، تحقق من https://github.com/esm-bundle/react و https://github.com/esm-bundle/react-dom. الفرق هو أن هذه قابلة للاستخدام في المتصفحات بدون إعادة تعبئة خريطة الاستيراد - يتم تغيير import React from 'react'; داخل الكود المصدري لـ React-dom لاستيراد React من عنوان URL كامل لـ CDN. الفرق الآخر هو أن الإصدارات الجديدة يتم نشرها تلقائيًا كلما تم نشر إصدار رد فعل جديد ، دون أي خطوات يدوية.

رمز Sandbox التوضيحي: https://codesandbox.io/s/gifted-roentgen-qcqoj؟file=/index.html

طعن قلة من الناس في فكرة أن النظام البيئي غير جاهز. ليس لدي سياق كامل حول هذا الأمر ، ولكن إذا كنت تعتقد أن هذا هو الوقت المناسب لبدء إجراء التغييرات ، فسأكون ممتنًا لو تفضلت بالاطلاع على

ولكن هذا هو الهدف. لن يكون هناك بالفعل سبب كبير لاستيراد React على الإطلاق.

هناك ما إذا كنت تستخدم TypeScript ، وستستمر في ذلك في المستقبل المنظور. حتى يتعرف TS على هذا السلوك السحري الجديد لـ babel ، سيتعين على المطورين الاستمرار في استيراد React بشكل صريح ، ويحتاجون إلى معرفة بيان الاستيراد الصحيح.

يُدرج JSX الاستيراد الصحيح تلقائيًا تحت الغطاء ، لذلك لا داعي لـ React في النطاق.

s / JSX / المكوِّن الإضافي للتحويل المتفاعل jsx من بابل الجديد /. JSX هو امتداد لغوي لجافا سكريبت ، وهو في حد ذاته لا يفعل أي شيء.

هناك ما إذا كنت تستخدم TypeScript ، وستستمر في ذلك في المستقبل المنظور. حتى يتعرف TS على هذا السلوك السحري الجديد لـ babel ، سيتعين على المطورين الاستمرار في استيراد React بشكل صريح ، ويحتاجون إلى معرفة بيان الاستيراد الصحيح.

يدرك فريق TypeScript هذا التغيير ، ويتم تعقبه في https://github.com/microsoft/TypeScript/issues/34547. نحن على اتصال وثيق بهم ، لذا يرجى التأكد من أنهم ليسوا مواطنًا من الدرجة الثانية بالنسبة لنا.

s / JSX / المكوِّن الإضافي للتحويل المتفاعل jsx من بابل الجديد /

نعم هذا ما قصدته!

سأكون ممتنًا لو تفضلتم بالاطلاع على رد الفعل / rfcs # 38 والتعبير عن أي مخاوف بشأنه. هل هذا تقريبًا ما كنت تفكر فيه ، أم تفضل نهجًا مختلفًا؟

بعض النصوص الأصلية لـ RFC قديمة. يسمح NodeJS بتشغيل ESM في ملفات .js بدلاً من .mjs الآن ، عندما تحدد "type" في الحزمة الخاصة بك. json. ( مستندات ).

على وجه التحديد ، ينص النص الأصلي لـ RFC على ما يلي وهو غير صحيح:

يجب أن يكون رمز ESM داخل ملف .mjs

بعد التحدث مع frehner ، إليك اقتراحنا لكيفية تحويل gaearon أن التصدير الافتراضي

| | المرحلة 1 | المرحلة الثانية | المرحلة 3 | المرحلة 4 |
| - | -------- | -------- | -------- | ------- |
| نشر ESM؟ | ✔️ | ✔️ | ✔️ | ✔️ |
| package.json "module" | ❌ | ✔️ | ✔️ | ✔️ |
| حزمة ويب / تجميع استخدام esm 1 ، 2 | ❌ | ✔️ | ✔️ | ✔️ |
| package.json "exports" | ❌ | ❌ | ✔️ | ✔️ |
| package.json "type" | ❌ | ❌ | ✔️ | ✔️ |
| يستخدم NodeJS esm | ❌ | ❌ | ✔️ | ✔️ |
| كسر التغيير؟ | ❌ | ❌ | ❓ | ✔️ |
| ذهب التصدير الافتراضي؟ | ❌ | ❌ | ❌ | ✔️ |
| امتدادات الملفات المطلوبة في الواردات | ❌ | ❌ | ❌ | ❌ |
| ملحقات الملفات mjs | ❌ | ❌ | ❌ | ❌ |

أعتقد أن هناك حجة صالحة للجمع بين المرحلتين الأولى والثانية معًا ، لأن المرحلة الأولى تستهدف المتحمسين فقط. ومع ذلك ، فقد قسمتهم لأنني أعتقد أن الفصل بين المراحل يعطي فرصة لطرح ESM ببطء شديد بطريقة لن تؤدي على الفور إلى كسر CRA والنظام البيئي بأكمله دون إعطاء المتبنين الأوائل فرصة للإبلاغ عن المشكلات والعثور على أي إصلاحات. .

joeldenning ما هو التوقيت التقريبي للمراحل؟ هل تعتمد فقط على الوقت أم تلك المتعلقة ببعض نقاط التفتيش الزمنية في النظام البيئي؟ هل سيظل require('react') يعمل في المرحلة 3؟

ما هو التوقيت التقريبي للمراحل؟ هل تعتمد فقط على الوقت أم تلك المتعلقة ببعض نقاط التفتيش الزمنية في النظام البيئي؟

يقتصر توقيت جميع المراحل فقط على العمل الذي يتعين القيام به والجدول الزمني لإصدار React. ما أفهمه هو أن جميع الأشياء المقترحة مدعومة بواسطة حزم و nodejs ، مع احتياطات مناسبة عند استخدام الإصدارات القديمة التي لا تدعمها.

هل يتطلب ("رد فعل") لا يزال يعمل في المرحلة 3؟

أعتقد ذلك ، نعم. راجع https://nodejs.org/api/esm.html#esm_dual_commonjs_es_module_packages و https://nodejs.org/api/esm.html#esm_package_entry_points. بالطبع من المحتمل جدًا أنني لا أعرف جميع الحالات الأساسية لكل شيء ، لكن ما أفهمه هو أن مسار الانتقال الذي اقترحته "سيعمل في كل مكان." ربما هذه هي الكلمات الأخيرة الشهيرة 😄

توضيح إضافي ، هذا ما نقترح أن تبدو عليه كرة القطران المنشورة لـ 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

وهذا تقريب لما ستكون الحزمة json في النهاية:

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

^ لم يتم التفكير في هذا بالكامل ولم يتم إتقانه ، لكنني أشارك لإعطاء سياق ملموس للاقتراح.

لذلك - تعاني React من خطر الحزمة المزدوجة لأنها ذات حالة (خطافات) ، لذلك يجب عزل هذه الحالة بعناية. إما أن يكون موجودًا في ملف CJS صغير يمكن استيراده بواسطة إدخالات CJS و ESM أو ربما هناك طريقة لتحميل .json وتحويلها بهذه الحالة من كلا الإدخالين (لست متأكدًا بنسبة 100٪ من ذلك) النهج الثاني).

أعتقد أيضًا أنه من المهم أن تدرج في جدولك إضافة الصادرات المسماة ، وهو ما سيحدث بالفعل في المرحلة 1.

ما زلت غير متأكد بنسبة 100٪ إذا لم أفوت بعض الحالات الجانبية ، فهذا الموضوع معقد للغاية. في الوقت نفسه ، يجب ربط الجدول الزمني بنقاط فحص النظام البيئي - لا يمكن شحن المرحلة 3 إلا بمجرد حصول exports على دعم كافٍ في المجمعات ، وإلا أشعر أن هذا قد يؤدي إلى مشكلات محتملة.

تعاني React من خطر الحزمة المزدوجة لأنها ذات حالة (خطافات) ، لذلك يجب عزل هذه الحالة بعناية.

نقطة جيدة ، لم أفكر في هذا ( مزيد من المعلومات ). في هذه الحالة ، ربما يكون اقتراحك لملف مشترك بين إصدارات CJS / ESM مفيدًا. أو ربما لا يكون إصدار ESM نسخة كاملة من التفاعل ، ولكنه مجرد واجهة عامة لـ ESM تستدعي بنية CJS.

أعتقد أيضًا أنه من المهم أن تدرج في جدولك إضافة الصادرات المسماة ، وهو ما سيحدث بالفعل في المرحلة 1.

يبدو أن هذا هو الحال بالفعل ، على الرغم من ذلك ، في شفرة المصدر؟ مما يمكنني قوله ، فإن الكود المصدري يقوم بالفعل بتصدير الأشياء على أنها عمليات تصدير مسماة.

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

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

ما زلت غير متأكد بنسبة 100٪ إذا لم أفوت بعض الحالات الجانبية ، فهذا الموضوع معقد للغاية. في الوقت نفسه ، يجب ربط الجدول الزمني بنقاط فحص النظام البيئي - لا يمكن شحن المرحلة 3 إلا بمجرد حصول الصادرات على دعم كافٍ في الحزم ، وإلا أشعر أن هذا قد يؤدي إلى مشكلات محتملة.

متفق عليه بشأن المرحلة 3 - ولهذا السبب وضعت علامة استفهام حول ما إذا كان تغييرًا مفاجئًا. أعلم أن إضافة صادرات package.json غالبًا ما كانت بمثابة تغيير جذري للحزم الأخرى في النظام البيئي. والموضوع معقد بالتأكيد. شيء واحد يجب ملاحظته هو أنه يمكن تبديل ترتيب المرحلتين 3 و 4 ، إذا رغبت في ذلك. أعتقد أنه يتعين على أولئك الذين ينفذون كل مرحلة إجراء اختبار شامل للغاية للعديد من إصدارات حزمة الويب ، والتجميع ، و nodejs ، وما إلى ذلك. من المحتمل أن يكون مسار انتقال هنا :)

يبدو أن هذا هو الحال بالفعل ، على الرغم من ذلك ، في شفرة المصدر؟ مما يمكنني قوله ، فإن الكود المصدري يقوم بالفعل بتصدير الأشياء على أنها عمليات تصدير مسماة.

آه - صحيح ، في هذه الحالة يجب أن يكون هناك صف جدول لإضافة export default 😂 لأنه يعمل حاليًا في معظم الحزم وهو شائع في البرية ، لكن إضافة إدخال ESM حقيقي دون تقديم default سيكون كسر تلك الأعراف.

في هذه الحالة يجب أن يكون هناك صف في الجدول لإضافة الافتراضي للتصدير

نعم نقطة جيدة. سأضيف ذلك. أعتقد أن قيام العلاقات العامة بهذا الأمر قد "يبدو سيئًا" ، لكني أرى أنه مجرد قبول للواجهة العامة الحالية على حقيقتها ، مع وجود خطط للتحسين في المستقبل.

يجب أن نلاحظ أنه بمجرد نشر بعض الإصدارات ، لن يكون هناك رجوع إلى الوراء وأي تغيير دلالي عليه سيتم كسره. نظرًا لأننا لا نقوم بإصدار العملات الرئيسية في كثير من الأحيان ، يجب أن نفكر في كيفية تجميع أي تغييرات بحيث يكون هناك أقل قدر من الاضطراب.

هناك أيضًا سؤال حول كيفية التعامل مع تقسيم بناء التطوير / الإنتاج. وبالفعل ، فإن الطبيعة الحكيمة لبناء React مهمة جدًا للمحافظة عليها.

يجب أن نلاحظ أنه بمجرد نشر بعض الإصدارات ، لن يكون هناك رجوع إلى الوراء وأي تغيير دلالي عليه سيتم كسره. نظرًا لأننا لا نقوم بإصدار العملات الرئيسية في كثير من الأحيان ، يجب أن نفكر في كيفية تجميع أي تغييرات بحيث يكون هناك أقل قدر من الاضطراب.

نقاط جيدة. فكرتي هي إضافة export default React إلى إصدار ESM الذي تم نشره في React 16. أعتقد أن العلاقات العامة قد تثير بعض الدهشة وقد تكون مثيرة للجدل ، لأن هذه ليست الوجهة التي تم تحديدها. ومع ذلك ، فإن وجهة نظري هي أنه يمكننا الحصول على بنية ESM في React 16 ثم إزالة export default في إصدار رئيسي مستقبلي. بالنسبة لي ، يعد استخدام رد الفعل عبر import React from 'react'; أمرًا شائعًا للغاية لدرجة أن التصدير الافتراضي في بنية ESM هو ببساطة "قبول ما نحن فيه". نسخة رئيسية في المستقبل ستزيله.

مرتبط أيضًا بتقليل تغييرات التكسير - يمكن أن تكون المرحلتان 3 و 4 جزءًا من نفس الإصدار الرئيسي. من الممكن أن تتم المرحلة 3 بطريقة متوافقة تمامًا مع الإصدارات السابقة ، وفي هذه الحالة يمكن أيضًا التسلل إلى إصدار 16. لكن هذا الأمر أكثر تعقيدًا ولا أعرف ما يكفي عنه لأكون واثقًا من ذلك.

هناك أيضًا سؤال حول كيفية التعامل مع تقسيم بناء التطوير / الإنتاج.

هذا شيء تجاهلت. لا أعرف كيفية القيام بذلك مع ESM في كل من الحزم وفي NodeJS ، لكنني سأقوم ببعض الأبحاث لمعرفة ما هو ممكن. لقد وجدت هذا الاقتراح الميت ، لكنني سأبحث في العروض الحية :)

وبالفعل ، فإن الطبيعة الحكيمة لبناء React مهمة جدًا للمحافظة عليها.

متفق. شيء واحد يجب ملاحظته هو أن الطبيعة الحالة لبناء React تحتاج فقط إلى حلها في المرحلة 3 ، وليس في المرحلتين 1 و 2. والخيارات التي اقترحتها Andarist و

الطريقة الأسهل والأكثر توافقًا مع الإصدارات السابقة في الوقت الحالي هي إضافة برنامج تضمين بسيط لـ ESM للسماح بعمليات الاستيراد المسماة.

يسعدني إنشاء علاقات عامة لإضافة هذا إلى React ، مما يضمن أن إضافة حقل "الصادرات" ليس تغييرًا فاصلاً (لقد كتبت أداة ، npx ls-exports ، مما يجعل تحديد ذلك أمرًا سهلاً). لن يساعد الأشخاص الذين يحاولون استخدام ESM بدون عملية إنشاء ، ولكن هذه مشكلة لا تستطيع الحزم الفردية حلها على أي حال.

gaearon سيكون ذلك مفيدا؟ يمكن أن تهبط في React 16 باعتبارها نصف صغيرة.

سيستمر إنشاء CJS في استخدام اكتشاف البيئة ، كما هو الحال الآن ، بحيث لا يلزم حل المشكلة (الصعبة ، التي لم يتم حلها) في ESM حتى الآن.

ومع ذلك ، فإن وجهة نظري هي أنه يمكننا الحصول على بنية ESM في React 16 ثم إزالة افتراضي التصدير في إصدار رئيسي مستقبلي.

مصدر قلق آخر هو أن زيادة عدد التكوينات تضع ضغطًا على النظام البيئي. على سبيل المثال ، أعتقد أنه إذا أطلقنا إصدار ESM ، فلا ينبغي أن يتضمن شيئًا سنقوم بإزالته بالتأكيد في الإصدار التالي ، مثل التصدير الافتراضي. بعبارة أخرى ، لا أعتقد أنه من المنطقي تقديم شيء ما يتم التخلص منه (الصادرات الافتراضية) إلى شيء تمت إضافته للتو (بناء ESM).

ومع ذلك ، فإن وجهة نظري هي أنه يمكننا الحصول على بنية ESM في React 16 ثم إزالة افتراضي التصدير في إصدار رئيسي مستقبلي.

مصدر قلق آخر هو أن زيادة عدد التكوينات تضع ضغطًا على النظام البيئي. على سبيل المثال ، أعتقد أنه إذا أطلقنا إصدار ESM ، فلا ينبغي أن يتضمن شيئًا سنقوم بإزالته بالتأكيد في الإصدار التالي ، مثل التصدير الافتراضي. بعبارة أخرى ، لا أعتقد أنه من المنطقي تقديم شيء ما يتم التخلص منه (الصادرات الافتراضية) إلى شيء تمت إضافته للتو (بناء ESM).

أعتقد أن ذلك يعتمد على المدة التي يستغرقها الإصدار التالي. إذا كنا نتحدث عن فرق الأسبوع ، فهذا يبدو معقولاً. ومع ذلك ، إذا كنا نتحدث عن شهور / سنوات ، فأنا لا أفهم لماذا سيكون من السيئ إخراجها لهذه الفترة من الوقت

القلق في هذه الحالة هو أنه كلما طالت مدة وجوده ، زاد عدد الأشخاص الذين يعتمدون عليه في الشكل الحالي. ومن ثم فإن إدخال تغيير جذري هناك سيجعل الأمر أكثر صعوبة بالنسبة لهم لترقية React. لا يوجد الآن ترحيل واحد لـ ESM ، ولكن هناك العديد من الأشخاص ، وسيترك بعض الأشخاص خلفهم لأنهم قفزوا مبكرًا جدًا وبعد ذلك لا يملكون الموارد اللازمة لترحيل آخر. والذي ، في حالة الإدارة السليمة بيئياً ، سوف ينتشر عبر النظام البيئي.

أعتقد أنه إذا أطلقنا إصدار ESM ، فلا ينبغي أن يتضمن شيئًا سنقوم بإزالته بالتأكيد في الإصدار التالي ، مثل التصدير الافتراضي. بعبارة أخرى ، لا أعتقد أنه من المنطقي تقديم شيء ما يتم التخلص منه (الصادرات الافتراضية) إلى شيء تمت إضافته للتو (بناء ESM).

لا أرى import React from 'react' كشيء مضاف حديثًا ، بل هو قبول للواقع الحالي. على الرغم من أنه ربما كان غير مقصود وكان أحد الآثار الجانبية فقط لإمكانية التشغيل المتداخل ESM / CJS التي عفا عليها الزمن ، لا يزال هناك الآلاف (الملايين؟) من سطور التعليمات البرمجية التي تقوم بذلك. البديل (تصدير الصادرات المسماة فقط) يقول للمستخدمين "لقد نشرنا إصدار ESM في إصدار ثانوي ، ولكن لا يمكنك استخدامه دون تغيير كل التعليمات البرمجية" الأمر الذي يعد محيرًا للمستخدمين أكثر من رؤية "تصدير افتراضي تمت إزالته" في ملاحظات إصدار إصدار رئيسي.

لدي فضول - كيف يمكن إضافة ESM مع تصدير افتراضي بطريقة متوافقة مع الإصدارات السابقة؟ لقد ظهر هذا من قبل (على سبيل المثال https://github.com/facebook/react/pull/18187 والذي يرتبط أيضًا بالمسائل ذات الصلة). تكمن المشكلة في webpack CJS <-> ESM interop حيث إذا كان لديك كود CJS يقوم بـ require('react') ما هو webpack الذي سيعود في وجود ESM react مع تصدير افتراضي ، هو كائن مع default خاصية require('react').default ) بغض النظر عن CJS react . ولكن ربما إذا قمت أيضًا بالتصدير بالاسم فلن تكون هناك مشكلة؟ أعتقد أن TrySound واجهت مثل هذه المشكلات في حزم أخرى من قبل.

ولكن ربما إذا قمت أيضًا بالتصدير بالاسم فلن تكون هناك مشكلة؟

نعم ، هذا هو النهج الذي أفكر فيه. راجع آخر 40 سطرًا من https://unpkg.com/browse/@esm-bundle/react @ 16.13.1 / esm / رد فعل. المنظمات كبديل مؤقت لـ React الرسمي. لا توجد تغييرات فاصلة.

ولكن ربما إذا قمت أيضًا بالتصدير بالاسم فلن تكون هناك مشكلة؟

نعم ، هذا هو النهج الذي أفكر فيه. راجع آخر 40 سطرًا من https://unpkg.com/browse/@esm-bundle/react @ 16.13.1 / esm / رد فعل. المنظمات كبديل مؤقت لـ React الرسمي. لا توجد تغييرات فاصلة.

لكن هل تستهلكه من كود CJS أو ESM؟ نظرًا لأن مشكلات التشغيل المتداخل CJS <-> ESM هي التي يمكن أن تكون مفاجئة للغاية.

gearon ليكون واضحا ؛ من المنطقي عدم وجود تصدير افتراضي في غلاف ESM الذي أقترحه ؛ أي شخص يقوم بعمل ESM أصلي يمكنه عمل import * as React from 'react' للتغلب عليه. ومع ذلك ، من العدل أن يرى أي شخص يقوم بذلك الآن أنه تغيير مفاجئ لعدم توفر التصدير الافتراضي فجأة ، لذلك سيتعين عليه الانتظار حتى الإصدار 17 إذا كنت لا ترغب في إضافة الإعداد الافتراضي الآن.

لكن هل تستهلكه من كود CJS أو ESM؟ نظرًا لأن مشكلات التشغيل المتداخل CJS <-> ESM هي التي يمكن أن تكون مفاجئة للغاية.

لقد قمت باستيراده بنجاح في حزمة الويب من ملفات CJS و ESM.

يمكن لأي شخص يقوم بإجراء ESM أصلي أن يقوم بالاستيراد * مثل React من "رد فعل" للتغلب عليها. ومع ذلك ، من العدل أن يرى أي شخص يفعل ذلك الآن أنه تغيير مفاجئ لعدم توفر التصدير الافتراضي فجأة ، لذلك سيتعين عليه الانتظار حتى الإصدار 17 إذا كنت لا ترغب في إضافة الإعداد الافتراضي الآن.

متفق. في حالة البدء من نقطة الصفر ، لن تكون هناك حاجة إلى الحصول على التصدير الافتراضي. ومع ذلك ، بدون إضافة تصدير افتراضي ، لا يمكن تنفيذ المرحلة 2 دون أن تكون تغييرًا جذريًا. أنا شخصياً سأكون على ما يرام في تنفيذ المرحلة 1 في رد الفعل 16 والمراحل 2-4 في React 17+ ، على الرغم من أني أفضل تنفيذ المرحلة 1 و 2 وربما حتى 3 (بمساعدة أداة مدقق الصادرات ljharb ) في React 16 دون تغيير التغييرات. والسبب هو أن المرحلة الثانية هي المرحلة الكبيرة حيث يبدأ غالبية المستخدمين في استخدام حزمة ESM ، في حين أن المرحلة الأولى مخصصة في الغالب للمتبنين / المتحمسين الأوائل.

استمرار من هذا الاقتراح على. يبدو أن هذا اقتراح للتبديل إلى حزمة مزدوجة مع مصدر CJS و ESM كامل يتعامل مع مخاطر الحزمة المزدوجة عن طريق عزل الحالة في مكان آخر ( النهج 2 ). على عكس استخدام غلاف ESM مثل RFC السابق (الطريقة 1 ).

بافتراض ذلك ، لدي بعض الملاحظات حول الأشياء التي لم يتم ذكرها بعد.

  • لا يمكنك الحصول على حزمة Node.js حيث تستخدم ملفات ESM و CommonJS .js . إذا قمت بتعيين "type": "module" فستحتاج جميع ملفات CommonJS إلى استخدام امتداد الملف .cjs بدلاً من ذلك.
  • لا تعد مخاطر الحزمة المزدوجة الخاصة بالحالة والمساواة هي المشكلة الوحيدة في وجود CJS و ESM. يؤدي تحميل نسختين محتملتين من نفس الحزمة أيضًا إلى زيادة أثر الذاكرة لـ React في تلك الحالات ، كما أن React ليست مكتبة صغيرة. هذه ليست صفقة ، لكن الأمر يستحق أن يؤخذ في الاعتبار.
  • أرى احتمالًا لخطر الحزمة المزدوجة إلى جانب الحالة الداخلية لـ React. على سبيل المثال ، إذا لم يكن تنفيذ فئة Component جزءًا من كود CJS حيث نشارك الحالة وبدلاً من ذلك جزء من حزم CJS / ESM ، فهناك خطر شيكات instanceof Component في مكتبات مختلفة كسر.

لا يمكنك الحصول على حزمة Node.js حيث تستخدم ملفات ESM و CommonJS ملفات .js. إذا قمت بتعيين "type": "module" ، فستحتاج جميع ملفات CommonJS إلى استخدام امتداد الملف .cjs بدلاً من ذلك.

هذا صحيح بالنسبة لـ NodeJS (ولكن ليس للمجمعات) ، لذا يجب أن تنتهي الملفات الموجودة في الدليل cjs بـ .cjs .

يؤدي تحميل نسختين محتملتين من نفس الحزمة أيضًا إلى زيادة تأثير ذاكرة React في تلك الحالات

أرى كيف يؤدي هذا إلى زيادة حجم كرة القطر المنشور إلى npm ، وبالتالي الحجم الإجمالي على القرص. لكني لا أرى كيف يؤثر ذلك على الذاكرة. بقدر ما أعرف ، لا تقوم المجمعات و NodeJS بإحضار التعليمات البرمجية إلى الذاكرة التي لم يتم تحميلها عبر import / require() . هل يمكنك توضيح كيف ستتغير بصمة الذاكرة؟

على سبيل المثال ، إذا لم يكن تطبيق فئة المكوّن جزءًا من رمز CJS حيث نشارك الحالة وبدلاً من ذلك جزء من حزم CJS / ESM ، فهناك خطر حدوث عمليات تحقق من مثيل للمكونات في مكتبات مختلفة.

يتمثل أحد الحلول المقترحة ( 1 ، 2 ) في جعل تطبيق NodeJS esm مجرد واجهة ESM تستدعي رمز CJS. بهذه الطريقة يوجد تعريف واحد فقط لـ Component يتم استخدامه في Node. لن تغير المرحلة 1 والمرحلة 2 ما يتم تشغيله في NodeJS ، على الرغم من ذلك ، لن ينطبق هذا إلا على المرحلة 3.

نظرًا لأننا (webpack) أضفنا مؤخرًا دعمًا ميدانيًا exports إلى webpack 5 ، أريد أن أعطي 2 سنت لهذا الموضوع:

  • يحتوي مستند العمل قيد المعالجة هذا على الكثير من المعلومات حول الحقل exports بخصوص حزمة الويب ولكن أيضًا Node.js وبشكل عام: https://gist.github.com/sokra/e032a0f17c1721c71cfced6f14516c62
  • هذه هي النقاط الأساسية مقارنةً بـ Node.js:

    • يضيف webpack 5 أيضًا شروط development و production ، وهي مفيدة جدًا للتفاعل. ( process.env.NODE_ENV ، بينما لا يزال مدعومًا ، يجب تجنبه لرمز الواجهة الأمامية بشكل عام ، فهو خاص بـ Node.js)

    • حزمة الويب (وغيرها من الحزم) تدعم require("esm") ، مما يسمح بتجنب مشكلة الحالة المزدوجة باستخدام ESM دائمًا (حتى مقابل require() ). أدخل webpack شرطًا خاصًا لذلك: module . بالنسبة إلى إصدار CommonJs و ESM هذا ، يجب تصدير نفس الواجهة. لا يوجد حاليًا أي شيء آخر لديه مشكلة الحالة المزدوجة غير Node.js. لا أتوقع أننا سنرى شيئًا ما في المستقبل ، لأن هذه في الغالب مشكلة متخلفة.

      لتحقيق أقصى قدر من التوافق ، أوصي بما يلي:

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

يسمح باستخدام .js كامتداد في هذا الدليل. بدلاً من ذلك ، يمكن استخدام .mjs ، لكن هذا قد يكون له آثار جانبية محتملة عندما تتحقق الأدوات من الامتداد. لذا فإن .js ليكون آمنًا.

{
    "type": "module"
}

esm / wrapper.js

هذا الغلاف ضروري لـ Node.js لتجنب مشكلة الحالة المزدوجة.

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

cjs / index.js

يتم استخدام هذا بواسطة Node.js عندما لا يتم دعم الشروط development و production .

'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 مماثل)

هذه الأغلفة مطلوبة لـ Node.js لتجنب مشكلة الحالة المزدوجة.
يتم استخدامها فقط عندما يضيف Node.js شروط development و production .

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

index.js

للمواطنين المتخلفين.

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

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

يتم استخدام هذا بواسطة الأدوات التي تدعم الحقل exports و module و شروط 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 }

نتائج

  • حزمة الويب 5: ./esm/index.development.js أو ./esm/index.production.min.js
  • browserify: ./cjs/index.js
  • حزمة الويب 4 من mjs.: ./cjs/index.js
  • حزم أخرى: ./esm/wrapper.js
  • Node.js (ESM): ./cjs/index.js (مطلوب) أو ./esm/wrapper.js (استيراد)
  • Node.js (قديم): ./cjs/index.js
  • Node.js (ESM + dev / prod): ./esm/wrapper.development.js أو ./esm/wrapper.production.min.js للاستيراد ، ./cjs/index.development.js أو ./cjs/index.production.min.js لطلب

ملحوظات

لا يوجد esm/index.js لأن الاختيار المشروط للإصدار غير ممكن في ESM بدون المقايضات الرئيسية.
يمكن للأدوات الاستفادة بشكل كامل فقط من تفاعل ESM عندما تدعم الحقل exports ، حالة module (بسبب مشكلة الحالة المزدوجة) و production / development شروط

يمكن أن تستفيد الأدوات جزئيًا من تفاعل ESM عندما تدعم الحقل module أو الحقل exports .

import { useState } from "react" أو import * as React from "react" من الناحية الفنية غير قانوني طالما رد الفعل هو وحدة CommonJs.
لا تزال معظم الأدوات تدعمها للتوافق المتخلف ، لكن البعض الآخر لا يدعمها ، على سبيل المثال Node.js
الطريقة الوحيدة حاليًا لاستخدام رد الفعل الصالحة في كل مكان هي: import React from "react" .
يجب أن تظل هذه الطريقة مدعومة ، وإلا ستكون هناك حالات (على سبيل المثال Node.js 14) حيث لا توجد صياغة صالحة في التفاعل الآن وتتفاعل بعد إضافة ESM.

رفض Node.js إضافة شرط development / production مقابل exports في الوقت الحالي.
هذا أمر محزن ، وما زلت آمل أن أفضل ما سيضيفونه في النهاية.
لهذا السبب تم إعداد الدعم لذلك في الحقل exports أعلاه.

sokra انهيار عظيم ، مفيد جدا ، شكرا لك!

سؤال واحد صغير:

رفض Node.js إضافة شرط تطوير / إنتاج للصادرات في الوقت الحالي.

ما أفهمه هو أنه لا يزال قيد العمل؟ https://github.com/nodejs/node/pull/33171 لكن ربما أساء فهم ذلك العلاقات العامة

[تحرير] تم استبدال العلاقات العامة أعلاه التي ربطتها بـ https://github.com/nodejs/node/pull/34637

[edit2] والآن تم دمجه في nodejs

شكرًا sokra ، هذه اقتراحات مفيدة جدًا.

فيما يلي الخيارات التي أراها. يبدو أن جميعها ممكنة تقنيًا ، وأن القرار يتعلق بالاستراتيجية أكثر من كونه تنفيذًا تقنيًا:

الخيار 1

أضف export default React إلى بنية React 17 ESM ، وقم بإزالتها بمجرد إسقاط دعم CJS لـ import React from 'react' (ربما في React 18؟).

الخيار 2

لا تضف export default React ، وأنشئ بنية React 17 ESM مع عمليات تصدير محددة فقط.

الخيار 3

لا تنشر بنية React 17 ESM. (😢) انتظر حتى يتم إسقاط الدعم import React from 'react'; قبل إنشاء إصدار ESM.

مقارنة

| | الخيار 1 | الخيار 2 | الخيار 3 |
| - | -------- | -------- | -------- |
| بناء ESM غير مراجع | الإصدار 17 | الإصدار 17 | الإصدار 18 + |
| package.json "module" (اهتزاز الشجرة افتراضيًا) | الإصدار 17 | الإصدار 18 + | الإصدار 18 + |
| package.json "نوع" / "صادرات" (يستخدم NodeJS ESM) | v18 + 1 | الإصدار 18 + | الإصدار 18 + |

  1. قد يكون من الممكن تنفيذ نوع package.json / الصادرات بطريقة متوافقة تمامًا مع الإصدارات السابقة ، وفي هذه الحالة يمكن أن تكون جزءًا من React 17 إذا تم اختيار الخيار 1.

أفضّل الخيار 1 ، كما أوضحت أعلاه. ومع ذلك ، فإن الخيار 2 مثير جدًا بالنسبة لي. الخيار 3 بالطبع أقل إثارة. من خلال ما جمعته في قضية github هذه ، لدينا الخبرة الفنية لإجراء أي من هذه الأمور (وربما حتى العمل!).

كان رد الفعل الأولي لهذه المشكلة هو ، لماذا ظلت هذه القضية مفتوحة حتى بعد 3 سنوات ؟ بعد قراءة جزء منه ، من المنطقي سبب استغراقه وقتًا طويلاً. يعد الحفاظ على مكتبة مثل React مهمة ضخمة. إذن 🙇🏻

نظرًا للأخبار الأخيرة باستخدام React 17 ، فقد قمت بتحديث تعليقي السابق للإشارة إلى React 17 بدلاً من 16 لأي خطط مستقبلية.

سأكون ممتنًا للتعليقات من الأشخاص بشأن أي من الخيارات الثلاثة المذكورة أعلاه مفضل.

أعتقد أنه يمكننا إضافة الحقل exports في package.json في React 17 ، ربما يمكننا نقله إلى الإصدارات السابقة أيضًا:

{
  "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"
    },
    "./": "./"
  },
}

سنحتاج إلى حزم esm جديدة ، على الرغم من أنه لا ينبغي أن يكون من الصعب جدًا إضافتها مع مجموعة التحديثات.

  • يجب أن تكون مجموعتي ./esm/react.development.mjs و ./esm/react.production.mjs خالية من شيكات process.env.NODE_ENV :

    • تم حل الشرط في وقت الاستيراد / الحزمة عبر الحقل exports .

    • process عبارة عن عقدة API ، ولا معنى لها في بيئة المتصفح ، ولا تدعمها _default_ بواسطة webpack 5 على سبيل المثال.

  • و ./esm/react.node.mjs شأنه أن يبقي process.env.NODE_ENV الشيكات.
  • AFAIK فقط حزمة الويب 5 والعقدة تدعم الحقل exports الآن.

أعتقد أن هذا آمن إلى حد ما ، WDYT؟

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

"./": "./" يجعله آمنًا ، نعم ، ولكنه يمنع أيضًا أي تغليف ، لذلك قد ترغب في إزالته بمجرد حصولك على semver-major.

يقوم FWIW babel بإخراج استيراد وقت تشغيل jsx كملف

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

ولكن إذا قمت بتحميل وحدة مثل تلك في Node ، فسوف تشتكي من عدم وجود امتداد الملف:

> 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'
}

إضافة exports يجب أن يصلح 🤔

إن تقديم exports كاملة كما أوضحت في مشاركتك السابقة ليس خيارًا مما أعتقده. ما تنفذه العقدة فيما يتعلق بـ Cjs interop والأشياء لا تعمل بشكل جيد مع النظام البيئي الحالي. خطر الحزمة المزدوجة حقيقي - خاصة بالنسبة للحزم مثل Reac التي تتطلب نسخة واحدة منها.

يمكن إضافة خريطة exports تحتوي على ملفات commonjs فقط دون كسر أي شيء ، ولكن يجب أيضًا إجراؤها بعناية فائقة وباستخدام اختبارات e2e المناسبة لذلك (نظرًا لمدى تعقيد الأمور)

Andarist يعمل بشكل جيد ، ولا يختلف في حالة التفاعل ، والتي لطالما

إذا كانت جميع تبعيات React ، متعدية أم لا ، تحت سيطرة React (وهي في هذه الحالة) وكانت نقاط دخول ESM جميعها تعيد تصدير محتوى CJS ، فربما يكون ذلك ممكنًا في هذه الحالة بالذات.

لا تزال هناك الدراما الكاملة لما يجب أن يكون عليه الشكل الفعلي لإدخال ESM (مسمى ، افتراضي ، كلاهما):

  • مسمى فقط: ليس متوافقًا مع الإصدارات السابقة حقًا لأن الكثير من الشفرات الموجودة هناك تستخدم import React from 'react' ، وهي أيضًا الطريقة الوحيدة لاستيراد React فعليًا في العقدة الآن عند استخدام ESM
  • افتراضي فقط: ليس متوافقًا مع الإصدارات السابقة حقًا لأن الكثير من الكود لدينا يستخدم import * as React from 'react' ، وغالبًا ما يتم الترويج لهذا بواسطة مدققات الكتابة وأدوات أخرى
  • كلاهما: الطريقة الوحيدة لجعله متوافقًا تمامًا مع الإصدارات السابقة ، بحيث يمكنه العمل مع جميع أنماط التحميل الحالية وعند خلط وحدات ESM و CJS عبر شجرة التبعية

أنسى دائمًا إمكانية استخدام أغلفة ESM لأنها تشعر وكأنها غش ولكن أيضًا لأن هذه التقنية لا تعمل

أخشى أن الإستراتيجية العالمية الوحيدة لتقديم كليهما هي ، في الواقع ، وجود كل التعليمات البرمجية الفعلية في CJS ، وكتابة أغلفة ESM حولها لتوفير عمليات تصدير مسماة. التعليمات البرمجية التي ليس جليل ولا تعتمد على هوية يمكن كتابة أصلا في كليهما، ولكن هذا فرعية، والتحذير.

jsx-runtime ليس صاحب الحالة ، أليس كذلك؟ يجب أن يكون شحن كل من esm / Cjs آمنًا بدون غلاف لذلك.

هل يجب علي تسجيل مشكلة منفصلة لاستيراد react/jsx-runtime في عقدة esm؟

بالنسبة لحزم الواجهة الأمامية ، هناك تحد إضافي ينضم إلى خطر الحالة المزدوجة: دعنا نسميها خطر الحزمة المزدوجة.

عند تصدير إصدارات ESM و CJS واستخدام الحزمة عبر require و import ، سيتم تجميع كلا الإصدارين ومضاعفة حجم الحزمة الفعال للحزمة.

sokra هل هذا ممكن في الممارسة؟ على سبيل المثال مع التجميع ، أفترض أنه نظرًا لأن وحدات cjs يتم تحويلها إلى وحدات ESM ، فإنها تفضل استيراد وحدات ESM متى توفرت.

من الممكن عمليًا للمجمّعين الذين يتبعون دلالات العقدة - مثل حزمة الويب 5. من المهم مطابقة الدلالات لأنه بخلاف ذلك من المحتمل أن تواجه نتائج مختلفة عند التشغيل في العقدة وعند تشغيل رمز الحزم.

ومع ذلك ، يتعامل webpack 5 مع شرط "module" يتم استخدامه لإزالة تكرار esm / cjs (تلك الواردة من خريطة الصادرات).

إذا أخذنا في الاعتبار اقتراح @ ljharb ، فهذا ليس مناسبًا حقًا على الرغم من أنه يقترح أن ملف esm يمكن أن يكون مجرد بضعة أسطر من التعليمات البرمجية المجمعة التي من شأنها إعادة تصدير ملف cjs فقط.

باستخدام غلاف ESM رفيع ، لا توجد مخاطر إضافية ، مع أو بدون الحزم - فقط الخطر العادي الذي يتجنبه النظراء بشأن المغفلين في الرسم البياني.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات