كيفية استخدام ميزة Web magic الجديدة "للتعليق السحري" مع React Universal Component + SSR

تم إطلاق Webpack 2.4.0 ، الذي تم طرحه قبل أسابيع قليلة ، بميزة جديدة مثيرة للاهتمام: "التعليقات السحرية". بالاقتران مع الواردات الديناميكية ، تعمل "التعليقات السحرية" على تبسيط عملية تقسيم الشفرات + التقديم من جانب الخادم. يمكنك الآن تسمية الأجزاء المطابقة للوحدات / المكونات التي تستوردها. قبل ذلك ، كانت هناك حاجة إلى قدر هائل من العمل لتحديد القطع التي سيتم عرضها في الطلبات الأولية حتى يمكن أيضًا عرض المكونات غير المتزامنة بشكل متزامن.

إليك كل ما يبدو عليه:

() => استيراد (/ * webpackChunkName: 'أي شيء' * / './MyComponent')

لقد كتبت مؤخرًا حول كيفية استخدام قطع تدفق حزمة الويب إلى وحدة الإسناد الترافقي ، حيث يتم مسحها من مكون التفاعل العالمي أو التفاعل القابل للتحميل مع إحصائيات Webpack لإنشاء البرامج النصية وأوراق الأنماط الدقيقة لإرسالها من الخادم. ومع ذلك ، فإن تسمية القطع بشكل كبير يبسط هذه العملية إلى حد كبير. يدعم Webpack-flush-chunks هذا أيضًا ، ولكن من المهم جدًا معرفة كيفية القيام بذلك يدويًا لأنك حتماً سيكون لديك احتياجات مخصصة.

سنبدأ بالخادم ونعمل في طريقنا للخلف ، مع توفير السحر للأخير.

الخطوة 1 - تقديم + قطع دافق

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

const appString = ReactDOMServer.renderToString ()
const chunkNames = flushChunkNames ()

الآن ، يجب أن يكون لديك مجموعة من الأسماء المقطوعة التي تبدو كما يلي:

["chunk1" ، "chunkWhatever" ، "my-chunk-name" ، "إلخ"]

الخطوة 2 - الحصول على الملفات من احصائيات

سنقوم بتخطي توضيح مفصل لكيفية الحصول على إحصائيات تجميع Webpack.

في الإنتاج ، أنصحك باستخدام البرنامج المساعد Webpack و stats-webpack-plugin ، وأثناء التطوير أوصي باستخدام webpack-hot-server-middleware لإدخال الإحصائيات إلى وظيفة serverRender الخاصة بك. يمكنك استخدام أحد ملفات التعريف الخاصة بي لتجربة كل هذا في بضعة أوامر: https://github.com/faceyspacey/flush-chunks-boilerplate-webpack-chunknames

بمجرد حصولك على الإحصائيات ، ستحتاج إلى معرفة مكان العثور على القطع والملفات التي تحتوي عليها. كانت موجودة داخل stats.assetsByChunkName:

stats.assetsByChunkName = {
   chunk1: ['0.js'، '0.js.map'، '0.css'، '0.css.map']،
   chunk2: ["1.js" ، "1.js.map" ، "1.css" ، "1.css.map"] ،
   chunk3: ["2.js" ، "2.js.map" ، "2.cs" ، "2.css.map"] ،
   main: ['main.js'، 'main.js.map'، 'main.css'، 'main.css.map']،
   بائع: ['vendor.js'، 'vendor.js.map'] ،
   bootstrap: ['bootstrap.js' ، 'bootstrap.js.map']
}
إن الإلمام بما تبدو عليه الأصول ByBunk هو نصف المعركة. لاحظ أن "القطعة" ليست مجرد ملف جافا سكريبت ، ولكنها مجموعة من الملفات.

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

أصول الأصول = webpackStats.assetsByChunkName
const filesForChunk = chunk => الأصول [القطعة]
ملفات const = flatten (chunkNames.map (filesForChunk))
وظيفة تتسطح (مجموعة) {
   إرجاع [] .concat (... مجموعة)
}

الخطوة 3 - تصفية البرامج النصية الخاصة بك وأنماط

هذا هو الجزء الأسهل. لو أن الأمور كانت بلا احتكاك طوال الوقت ، فإن تقسيم الشفرة مع SSR كان من السهل جدًا كسره:

مخطوطات const = files.filter (f => f.endsWith ('. js'))
أوراق أنماط const = files.filter (f => f.endsWith ('. css'))
// ولإجراء جيد ، دعونا نحصل على publicPath قبل المتابعة
مسار المسار = webpackStats.publicPath

الخطوة 4 - ضعها معًا وخدمتها

الآن الأمر يتعلق فقط بإنشاء سلاسل (أو ربما عناصر React لـ ReactDOMServer.renderToStaticMarkup) لإرسالها إلى العملاء:

وظيفة التصدير الافتراضية serverRender (req، res) {
  const appString = ReactDOMServer.renderToString ()
  const chunkNames = flushChunkNames () // سيصل إلى هذا قريبًا
  أصول الأصول = webpackStats.assetsByChunkName
  const filesForChunk = chunk => الأصول [القطعة]
  ملفات const = flatten (chunkNames.map (filesForChunk))
  
  مخطوطات const = files.filter (f => f.endsWith ('. js'))
  أوراق أنماط const = files.filter (f => f.endsWith ('. css'))
  مسار المسار = webpackStats.publicPath
  
  res.send (
    `
      
        <رئيس>
          $ {الأنماط
              .map (f => ``)
              .join ( '\ ن')
          }
        
        
          
$ {appString}
          $ {مخطوطات               .map (f => ``)               .join ( '\ ن')           }                 `   ) }              const flatten = (array) => [] .concat (... array)
في مثال أقل سذاجة ، يمكنك التأكد من أن البرنامج النصي bootstrap.js يأتي أولاً ، يليه قطع ، وينتهي بـ main.js. إنه عمل روتيني لتحقيق ذلك. هذه واحدة من الأشياء التي تقوم بها webpack-flush-chunks تلقائيًا لك.

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

ما تبقى هو:

  • في الواقع نقول Webpack لإنشاء هذه القطع
  • ترسيم التعليمات البرمجية عند استخدامها في الواقع
  • ومن ثم مسح تلك المستخدمة.

الجزء 2: استخدام التعليقات السحرية لإنشاء هذه القطع

الخطوة 1 - إنشاء

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

استيراد رد من "رد فعل"
استيراد عالمي من "مكون التفاعل العالمي"
const asyncComponent =
   () => استيراد (/ * webpackChunkName: 'أي شيء' * / './MyComponent')
const UniversalComponent = عام (asyncComponent ، {
  حل: () => require.resolveWeak ('./ Foo') ،
  chunkName: "أي شيء"
})
الافتراضي التصدير () =>
  
       

الجزء المهم هو أن السلسلة التي تقدمها webpackChunkName يجب أن تتوافق مع خيار chunkName. لاحظ أنهما "أي شيء". إنه لا لزوم له بعض الشيء ، لكن السابق هو تعليق ثابت وليس هناك الكثير مما يمكننا فعله حيال ذلك. من وجهة نظري ، فإن إنفاق هذه السطور هو أقل ما يقلقني. أنا ممتن جدًا لأن هذه الميزة موجودة أخيرًا في Webpack.

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

ولكن ما هو خيار العزم؟

هذا هو في نهاية المطاف خدعة النهائي هنا. إنه يمنح خادم Webpack الخاص بك طريقة متزامنة لطلب المكون الخاص بك ، دون أن يدرجه العميل في تبعيات القطعة الأصلية. انظر ، إذا كنت قد فعلت ذلك: حل: مطلوب ('./ Foo') ، فقط بوجود ذلك بشكل رئيسي ، ستضم Webpack الكود الذي تحاول نقله إلى جزء آخر. سيكون لهزيمة الغرض من تقسيم الرمز.

بالإضافة إلى ذلك ، يتم استخدام require.resolveWeak من قِبل العميل عند تحميل الصفحة عند تقديم التطبيق لأول مرة وقمت بتقديم الجزء المقابل له بشكل صحيح (وفقًا للجزء 1). هذا يتجنب رد فعل "عدم تطابق المجموع الاختباري" الذي يؤدي إلى تقديم إضافي. والأهم من ذلك أن هذا يمنع الطلب الثاني غير الضروري للحصول على جزء يتوافق مع ما تم تقديمه بالفعل بشكل صحيح بواسطة SSR.

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

ولكن هل بابل قد تتطلب. حل؟

إذا كنت تستخدم Babel لخادمك ، فيجب عليك أيضًا تقديم مسار الوحدة المطلقة:

const UniversalComponent = عام (asyncComponent ، {
  حل: () => require.resolveWeak ('./ Foo') ،
  اسم القطعة: "أي شيء" ،
  path: path.join (__ dirname، './Foo')
})

يتم ترك الباقي حتى React Universal Component للتبديل بشكل حيوي بين استخدام إحدى الطرق الثلاث لاستيراد الوحدة النمطية وفقًا للبيئة.

يأخذ HoC العالمي العديد من الخيارات (جميعها اختيارية). لمعرفة المزيد عنهم ، تفضل بزيارة:

إليك ملخص سريع للخيارات:

  • خطأ - مكون <خطأ /> اختياري
  • التحميل - اختياري <تحميل /> المكون
  • مفتاح - يستخدم للعثور على التصدير الذي تريده في وحدة نمطية معينة
  • onLoad - يستخدم لنقل الصادرات الأخرى من وحدة نمطية والقيام بأشياء مثل استبدال المخفضات
  • minDelay - تأخير مسيطر عليه لمنع الزاحف عند التبديل من مكون التحميل الخاص بك إلى المكون الأساسي
  • المهلة - الحد الأقصى لوقت التحميل قبل ظهور مكون الخطأ
  • chunkName - اسم القطعة التي سيتم مسحها إذا تم عرضها

الخطوة 2 - ضخ تلك القطع

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

استيراد flushChunks من 'قطع webpack-flush-
استيراد * كـ Universal من "react-universal-component / server"
const appString = ReactDOM.renderToString ()
const {js، styles} = flushChunks (webpackStats ، {
  chunkNames: Universal.flushChunkNames () ،
  قبل: ['bootstrap' ، 'vendor'] ،
  بعد: ['الرئيسي']
})
res.send ( `
  
    <رئيس>
      $ {أساليب}
    
    
      
$ {appString}
      $ {شبيبة}         `)

الشيء الأساسي الذي يجب التعرف عليه هنا هو أنه نظرًا لطريقة عمل Node (أي فيما يتعلق بحلقة الحدث) وطريقة عمل renderToString (أي بشكل متزامن) ، يمكنك تنفيذ إجراءات متزامنة أخرى بعد ذلك مباشرةً ، والتي تستخدم بعض الحالات العامة (وهي: صفائف / مجموعات وراء الكواليس التي تحتوي على chunkNames الخاصة بك) وتأكد من إعادة تعيينها لطلبات قائمة الانتظار. يقوم flushChunkNames () بمسح مجموعة من الأسماء المقطوعة المسجلة في التجسيد ، ونتيجة لذلك لا يلزم وجود مكونات مفاعل React مزعج. فقط تأكد من عدم الاتصال في انتظار أو بدء أي وعود قبل الاتصال res.send.

بالنسبة إلى المثال الأصلي في الجزء 1 ، من الواضح أنه يمكنك استخدام Universal.flushChunkNames () بنفس الطريقة والقيام بالعمل المقابل للحصول على البرامج النصية وأوراق الأنماط يدويًا. يحتوي webpack-flush-chunks أيضًا على واجهة برمجة التطبيقات (API) ذات المستوى المنخفض والتي يمكنها تبسيط الأمور في المسار شبه اليدوي أيضًا. على وجه التحديد ، يمنحك جميع الملفات من قطع المقدمة ، دون معالجة ترتيب الملفات ، أو إنشاء سلاسل / مكونات ، أو الحصول على البرامج النصية الرئيسية / البائع الخاص بك ، وما إلى ذلك.

أهم شيء ستحتاجه هو تكوين Webpack الصحيح. تأكد من مراجعة هذا القسم من المستندات.

التعليمات

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

1. ماذا عن إنشاء أجهزتي الخاصة؟

في كل مكان تقريبًا نريد القيام بتقسيم الرموز ، نريد القيام بذلك بشكل ديناميكي لمجموعة من الأقسام من موقعنا / التطبيق في نفس الوقت. نريد ضرب مجموعة من الطيور بالحجر نفسه. كيف يمكننا تحقيق ما يلي:

وظيفة createUniversalComponent (صفحة) {
  إرجاع عالمي (استيراد (`./pages/`$ {page}`) ، {
    حل: () => require.resolveWeak (`./pages/`$ {page}`)
  })
}
لم تعد استيرادك بحاجة إلى أن تكون وظيفة نظرًا لأنها ضمن وظيفة لا تُسمى حتى "تقديم الوقت". يتم ترك التعليقات السحرية للقراءة. إذا لم تكن على دراية بذلك ، فإن قطع webpack-flush تعمل بدون تعليقات سحرية أيضًا. باستخدام moduleIds التي يمكنك استرجاعها من Universal.flushModuleIds () ، يمكنك تحقيق نفس الشيء على الإصدارات القديمة من Webpack!

تختلف طريقة تطبيقنا لهذا الأمر بعض الشيء نظرًا لأننا لا نعرف الصفحة التي تريد عرضها حتى "تقديم الوقت". دعنا نلقي نظرة:

const MyParentComponent = ({page}) => {
  const UniversalComponent = createUniversalComponent (صفحة)
  إرجاع (
    
              ) }

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

هناك مشكلة واحدة مع هذا. تتطلب حاليًا. لا يمكن أن يحل حل مشكلة الاستيراد الديناميكي مثل الاستيراد. أي. لا يمكنك الحصول على سلسلة مثل "./page/${page}" حيث يكون جزء من المسار ديناميكيًا. إذا كنت لا تعرف بالفعل ، فإن Webpack قادر تمامًا على القيام بذلك. طريقة معالجتها هي إنشاء أجزاء لكل وحدة نمطية في مجلد الصفحة.

لقد قمت بإنشاء مشكلة لهذا الأمر ، وقد أعطاها Tobias Koppers مؤخرًا الأولوية لـه. التصويت عليه إذا كنت تريد هذا ثابت.

إليك كيفية تحقيق ذلك في الوقت الحالي (ومن المحتمل أن يكون مماثلاً لما كنت تفعله في الماضي ، بدون SSR فقط):

const Page1 = universal (() => import ('./ pages / Page1') ، {
  حل: () => require.resolveWeak (('./ pages / Page1')
})
const Page2 = universal (() => import ('./ pages / Page2') ، {
  حل: () => require.resolveWeak (('./ pages / Page2')
})
const Page3 = universal (() => import ('./ pages / Page3') ، {
  حل: () => require.resolveWeak (('./ pages / Page3')
})
صفحات الصفحات = {الصفحة 1 ، الصفحة 2 ، الصفحة 3}
const createUniversalComponent = page => الصفحات [الصفحة]

وتنفيذ هو نفسه كما كان من قبل.

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

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

في المستقبل ، من المحتمل أن نقدم هذه الواجهة أيضًا:

const create = universal (({page}) => import (`./pages / $ {page}`) ، {
  حل: ({الصفحة}) => require.resolveWeak ((`./pages / $ {page}`) ،
  path: ({page}) => path.join (__ dirname، `./pages / $ {page}`)
})
const UniversalComponent = create ()

بعد ذلك ، لن تحتاج حتى إلى إنشاء HoCs الخاصة بك ، ويمكنك تجنب إهدار دورات CPU الثمينة في وقت العرض. أفضل من كل العالمين.

2. ماذا عن تحميل المكونات الخاصة بي؟

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

استيراد عالمي من "مكون التفاعل العالمي"

const UniversalComponent = universal (() => import ('../ components / Foo') ، {
  حل: () => require.resolveWeak ('./ Foo')
})

فئة التصدير الافتراضية MyComponent يمتد React.Component {
  componentWillMount () {
    UniversalComponent.preload ()
  }

  يجعل() {
    إرجاع 
{this.props.visible && }
  } }

3. هل يمكنني تشغيل مكون التحميل أثناء جلب البيانات؟

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

const UniversalUser = universal (() => import ('./ User') ، {
  حل: () => require.resolveWeak ('./ المستخدم') ،
  التحميل: <تحميل />
})
const المستخدم = ({loading ، خطأ ، user}) =>
  
        graphql التصدير الافتراضي (gql`   استعلام CurrentUser {     المستعمل {       هوية شخصية       اسم     }   } `، {   props: ({ownProps، data: {loading، error، user}}) => ({     جار التحميل،     خطأ،     المستعمل،   })، })(المستعمل)

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

أما بالنسبة للخادم ، فستستخدم بالطبع حل دقة الوعود العودية المدهش من Apollo لتعبئة شجرة المكونات الخاصة بك بالبيانات بينما يتم حل المتطلبات من بشكل متزامن وفي ثانية مقسمة. لذلك فهو يجمع بشكل جيد في كل البيئات.

4. ماذا عن إنشاء أجزاء CSS؟

أي شخص نجح في تقسيم الشفرة (مع أو بدون SSR) يعرف أن الأمر يتعلق فقط بقطع جافا سكريبت الخاص بك - حسنًا ، إليكم درجة الحرارة الجديدة:

const ExtractCssChunks = require ("extract-css-chunks-webpack-plugin")
module.exports = {
  وحدة: {
    قواعد: [
      {
        اختبار: / \ .css/
        الاستخدام: ExtractCssChunks.extract ({
          استعمال: {
            اللودر: 'css-loader' ،
            خيارات: {
              وحدات: صحيح ،
              localIdentName: '[name] __ [local] - [hash: base64: 5]'
            }
          }
        })
      }
    ]
  }،
  الإضافات: [
    ExtractCssChunks جديدة ،
  ]
}

تبدو مألوفة؟ استغرق الأمر الكثير من العمل لإعادة توجيه هذا البرنامج المساعد. extract-css-chunks-webpack-plugin يدعم أيضًا HMR لـ css الخاص بك - وهو الشيء الذي لم يفعله برنامج extract-text-webpack-plugin الأصلي. هناك الكثير في هذا أيضًا ، نظرًا لأنك مضطر إلى تهيئة بيئة خادم مطابقة إما مع Babel أو Webpack ، قم بإنشاء مجموعات تقوم بضخ js وقطعًا تم إزالتها نظرًا لأن صفحات الأنماط لديها بالفعل ، وما إلى ذلك.

استنتاج

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

تخدم هذه الإمكانية نفس الغرض مثل getInitialProps لـ Next.js:

const asyncWork = async props => {
  const prom = في انتظار Promise.all ([
    استيراد ( 'العضو ./')،
    استيراد ( './ المشاركة')،
    جلب ( `/ المستخدم؟ ID = $ {props.id}`)
  ])
  const المستخدم = حفلة موسيقية [0]
  const المشاركة = حفلة موسيقية [1]
  بيانات const = في انتظار prom [2] .json ()
  إرجاع (
    <بيانات المستخدم = {data} {... props}>
      <نشر />
    
  )
}
const UniversalComponent = () => عالمي (asyncWork)
لاحظ كيف نطلب قطعتين + جلب بعض البيانات بشكل متوازٍ!

إن القدرة على ترميز مكوناتك دون احتكاك من هذا القبيل ، ودون الحاجة إلى القلق بشأن المقايضات فيما يتعلق بـ SSR مقابل Code-Splitting ، هو المستقبل. إذا كنت قد قرأت مقالة Bret Victor’s Ladder of Abstraction ، فأنت تعلم أهمية أن تصبح الأشياء غير قابلة للاحتكاك حتى تتطور المنصات. حتى وقت قريب ، كنا متعطشين لأننا قادرون على الاستفادة الكاملة من منصتنا. يجب ألا تكون هناك أماكن معينة يمكننا من خلالها القيام بالأشياء المذكورة أعلاه وغيرها من الأماكن التي لا يمكننا القيام بها. يجب ألا نكون مقيدين حتى بـ HoC الحالي التفاعل العالمي المكون. كانت هناك حلول تنجز asyncWork أعلاه ، لكنها غير متزامنة فقط. يمكنك تداول SSR للتقسيم غير المتزامن فقط. لا ينبغي أن يكون هذا هو الحال على الإطلاق.

ومع ذلك ، فإن عنصر التفاعل العالمي - كما هو مهم - سيبقى مهمًا للغاية ، حتى لو / عندما يتم حل المشكلة المذكورة أعلاه. ستظل دائمًا على الحلول التي تعيد تقديم حلول الوعود لشجرة المكونات الخاصة بك في الواقع البسيط المتمثل في أنها لا تحتاج إلى تضييع دورات على خادمك للقيام "بتقديم مسبق" للعثور على تلك الوعود. ومع ذلك ، سأصدر الأسبوع القادم أفضل ما في العالم ، ويمكنك أن تقرر بناءً على احتياجاتك. كل شيء مغطى هنا سيبقى كما هو ، وأنا شخصيا ، سأواصل 100٪ استخدام بالضبط ما رأيته اليوم. ولكن بالنسبة للمطورين الذين يرغبون في جلب البيانات في componentWillMount ، لدي بعض الأشياء المثيرة للغاية التي تصل إليك. ترقب!

BOILERPLATES:

https://github.com/faceyspacey/webpack-flush-chunks/#boilerplates

تحقق من المراجل الأربعة لتجربة الأشياء بدون احتكاك باستخدام خادم Webpack أو Babel ، ومع أو بدون "تعليقات سحرية".

> للحصول على مزيد من جافا سكريبت الاصطلاحية في Reactlandia ، اقرأ:

تغريدات وغيرها من الحب هي محل تقدير كبير. تجدني على twitterfaceyspacey

لا وقت للمساعدة في المساهمة؟ هل تريد رد الجميل بطرق أخرى؟ كن داعمًا أو راعيًا لحزمة الويب عبر التبرع لجماعتنا المفتوحة. لا يساعد Open Collective في دعم الفريق الأساسي فحسب ، بل يدعم أيضًا المساهمين الذين قضوا وقتًا كبيرًا في تحسين منظمتنا في أوقات فراغهم! ❤