الفرق بين المراجعتين لصفحة: «Next.js/upgrading»

من موسوعة حسوب
لا ملخص تعديل
لا ملخص تعديل
سطر 283: سطر 283:
</syntaxhighlight>
</syntaxhighlight>


==== معاملة <u>مختلف لمكونات</u> المجلد <code>/pages/api</code> ====
==== معاملة مختلف مكونات المجلد <code>/pages/api</code> ====
تُعد جميع الملفات في هذا المجلد وجهات API، ولن يتضمن تجميعات خاصة بواجهة العميل.
تُعد جميع الملفات في هذا المجلد وجهات API، ولن يتضمن تجميعات خاصة بواجهة العميل.



مراجعة 08:00، 14 يوليو 2022

إليك قائمة بالتغييرات التي تحدث عند ترقية إصدارات Next.js والمتطلبات اللازمة لكل منها.

ترقية Next.js من النسخة 11 إلى 12

النسخة الأدنى من Node.js

رُفع متطلب الحد الأدنى لنسخة Node.js من 12.0.0 إلى 12.22.0، وهي أولى نسخ Node.js التي تدعم وحدات ES الأساسية.

ترقية React إلى أحدث نسخة

إن أدنى نسخة مدعومة من React هي 17.0.2. نفِّذ الأمر التالي لترقية الإصدار الذي لديك:

npm install react@latest react-dom@latest

أو باستخدام yarn:

yarn add react@latest react-dom@latest

ترقية Next.js إلى الإصدار 12

نفِّذ الأمر التالي:

npm install next@12

أو:

yarn add next@12

استبدال المفسّر Babel بالمصرِّف SWR

تستخدم Next.js حاليًا المصرِّف SWC المكتوب بلغة Rust لتصريف شيفرة JavaScript وTypeScript. وهذا المصرِّف أسرع بسبع عشرة مرة من Babel عند تصريف الملفات المفردة وأسرع بخمس مرات عندما يتعلق الأمر بميزة التحديث السريع.

تدعم Next.js بشكل كامل التوافقية الرجعية للتطبيقات التي تستخدم تهيئة خاصة بمفسِّر Babel، ونُقلت جميع التحويلات التي تتعامل معها افتراضيًا مثل "styled-jsx" و"tree-shaking" الخاصة بالدوال getStaticProps / getStaticPaths / getServerSideProps إلى Rust.

تتوقف Next.js عن استخدام SWC عندما يكون للتطبيق تهيئة Babel مخصصة، ويتراجع ليستخدم Babel عند تصريف شيفرة JavaScript/Typescript بنفس الطريقة التي استُخدمت في النسخة 11 من Next.js.

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

  • Styled Components
  • Emotion
  • Relay

استبدال المجمّع Terser بالمصرِّف SWR

يزيد استخدام SWC بدلًا من Terser من سرعة تصغير شيفرة JavaScript، وذلك بتفعيل الراية swcMinify في الملف next.config.js:

module.exports = {
  swcMinify: true,
}

لا بد حاليًا من التأكيد على استخدام SWC لتصغير الشيفرة لاختباره في تطبيقات Next.js الحقيقية قبل أن يُعتمد كمصرّف افتراضي في النسخة 12.1.

التحسينات على تفسير تنسيقات styled-jsx

أنجزنا مفسّر CSS جديد مبني على المفسّر الذي استُخدم في تحويل Babel الخاص يتنسيقات styled-jsx. طوّرت آلية التعامل مع تنسيقات CSS في المفسّر الجديد، وستظهر أخطاء CSS الآن أثناء التطوير وعند تنفيذ الأمر next build بدلًا من تجاهلها وظهور مشاكل غير متوقعة. لكن هذه التغييرات ستُطبق فقط عند استخدام styled-jsx.

تغير عنصر تغليف next/image

تصير next/image الآن العنصر <img> داخل عنصر <span> وليس <div>. فإن استخدم تطبيقك قاعدة CSS محددة تستهدف العنصر <span> مثل container span.، سيؤدي تحديث التطبيق إلى مطابقة عناصر التغليف ضمن المكوّن <Image>، لهذا لا بد من تحاشي ذلك بتقييد محدد التنسيق إلى قاعدة محددة مثل container span.item.، وتحديث المكوّن بإضافة الخاصية className ليصبح بالشكل </ "span className="item">.

إن كان لتطبيقك قاعدة تنسيق محددة تستهدف العنصر <div> الخاص بالمكوّن next/image مثل container span.، فقد لا تجده القاعدة بعد الآن. بإمكانك في هذه الحالة تحديث المحدد ليصبح container span.، أو يُفضّل إضافة العنصر <"div className="wrapper> ليغلّف المكوّن <Image> ومن ثم استهدف هذا الغلاف بقاعدة مثل container .wrapper..

لن تتغير الخاصية className وستبقى قادرًا على تمريرها إلى العنصر الداخلي <img>. لمزيد من المعلومات راجع صفحة تحسين الصور في توثيق Next.js.

استخدام WebSocket في تأسيس اتصالات HMR في Next.js

استخدمت سابقًا تقنية دفع التحديثات من الخادم إلى العميل عبر اتصال HTTP أو ما يُعرف بالأحداث المرسلة من قبل الخادم SSE، وذلك لاستقبال تحديثات HMR (الاستبدال السريع للوحدات Hot Modules Replacement). تُستخدم الآن اتصالات مقبس ويب WebSocket.

في بعض الحالات التي تُستخدم فيها خوادم وسيطة لإرسال الطلبات إلى خادم تطوير Next.js، لا بد من التأكد من صحة تخديم الطلب عند ترقيته. إذ قد تحتاج أن تضيف مثلًا الإعدادات التالية عند استخدام الخادم الوسيط nginx:

location /_next/webpack-hmr {
    proxy_pass http://localhost:3000/_next/webpack-hmr;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

أما في خوادم أخرى مثل express، فقد تحتاج إلى استخدام الدالة app.all للتاكد من صحة تمرير الطلب. إليك مثالًا:

app.all('/_next/webpack-hmr', (req, res) => {
  nextjsRequestHandler(req, res)
})

إلغاء دعم الإصدار الرابع من Webpack

إن كنت تستخدم الإصدار الخامس من webpack فتجاوز هذه الفقرة.

تستخدم Next.js النسخة 11 برنامج التحزيم webpack 5 افتراضيًا أثناء تصريف التطبيقات. وتوقف دعم النسخة 4.

إن كنت لا تزال تستخدم webpack 4 في تطبيقاتك بوضع راية التحييد في ملف الإعدادات، سترى الآن رسالة خطأ تشير إلى موضوع رفع الدعم عن هذه النسخة.

إلغاء الخيار target

إن لم تستخدم الخيار target في ملف الإعدادات next.config.js يمكنك تجاوز هذه الفقرة.

ألغي الخيار لمصلحة الدعم المدمج لتعقب الاعتماديات اللازمة لتشغيل الصفحة. فخلال عملية البناء next build، تتعقب Next.js تلقائيًا كل صفحة واعتمادياتها لتحديد كل الملفات التي يحتاجها التطبيق لنشر نسخة إنتاج منه.

راجع صفحة تعقب ملفات الخرج من توثيق Next.js لمعلومات أكثر، إن كنت تستخدم الخيار target مضبوطًا على القيمة serverless.

الترقية من النسخة 10 إلى 11

ترقية React إلى أحدث نسخة

إنّ أدنى نسخة مدعومة من React هي 17.0.2. نفِّذ الأمر التالي لترقية الإصدار الذي لديك:

npm install react@latest react-dom@latest

أو باستخدام yarn:

yarn add react@latest react-dom@latest

ترقية Next.js إلى الإصدار 11

نفِّذ الأمر التالي:

npm install next@11

أو:

yarn add next@11

برنامج Webpack 5

يُعد Webpack 5 المحزّم الافتراضي لنسخ Next.js الآن. إن لم تستخدم تهيئة خاصة لهذا المحزّم في تطبيقك ستستخدم Next.js المحزّم Webpack 5. أما إن كنت تستخدم إعدادات خاصة، راجع توثيق استخدام مع Next.js.

مسح distDir سيكون الخيار الافتراضي الآن

ستُمسح محتويات المجلد الذي يضم خرج عملية البناء افتراضيًا (وهو next. افتراضيًا) ما عدا ذاكرة Next.js المؤقتة. فإن كان يتعلق تطبيقك بهذه الناحية، تستطيع تعطيل هذه الميزة الافتراضية الجديدة بإضافة الراية cleanDistDir: false ضمن الملف next.config.js.

دعم استخدام PORT عند تنفيذ الأمرين next dev و next start

تدعم استخدام متغير البيئة لضبط المنفذ الذي سيعمل عليه التطبيق. ينصح باستخدام p- و port-- حتى الآن، لكن حين تُمنع من استخدام p- يمكنك الآن استخدام PORT. إليك مثالًا:

PORT=4000 next start

تخصيص إعدادات next.config.js لإدراج الصور

تدعم النسخة الإدراج الساكن للصور من خلال المكوّن next/image. وتعتمد على معالجة الصورة المُدرجة. إن أضفت سابقًا الحزمتين next-images أو next-optimized-images، فبإمكانك الانتقال إلى الدعم المدمج الجديد باستخدام next/image أو إلغاء الميزة:

module.exports = {
  images: {
    disableStaticImages: true,
  },
}

إزالة التابع ()super.componentDidCatch من pages/_app.js

ألغي التابع العائد ()super.componentDidCatch منذ الإصدار 9 ولم يعد هنالك أي حاجة لاستخدامه، وقد أزيل في النسخة 11. إن احتوت الصفحة pages/_app.js تابع مخصص componentDidCatch، يمكنك إزالة super.componentDidCatch لأنك لن تحتاجه بعد الآن.

إزالة Container من الصفحة pages/_app.js

ألغي هذا التصدير منذ الإصدار 9 ولم يعد هنالك حاجة إلى استخدامه، وقد أزيل في النسخة 11. إن أدرجت الصفحة pages/_app.js العنصر Container من المكوّن next/app يمكن إزالته.

إزالة استخدام الخاصية props.url من مكوّنات الصفحة.

ألغي استخدام هذه الخاصية في الإصدار 4، ومنذ ذلك الوقت بدأت تظهر تنبيهات إلى هذا الموضوع أثناء تطوير التطبيق. لكن مع ظهور الدالتين getStaticProps و getServerSideProps لم يعد يُسمح باستخدام props.url. وقد ألغي تمامًا في الإصدار 11.

إزالة الخاصية unsized من المكوّن next/image

ألغيت الخاصية unsized في المكوّن next/image ابتداءً من النسخة 10.0.1، ويمكنك استخدام layout="fill" بدلًا منها. أزيلت هذه الخاصية تمامًا في النسخة 11.

إزالة الخاصية modules من المكوّن next/dynamic

ألغيت الخاصيتان modules و render العائدتان للمكوّن next/dynamic ابتداءً من النسخة 9.5، وتعرض Next.js تنبيهًا أنهما ملغيّتان. والسبب في ذلك جعل المكوّن next/dynamic قريبًا من React.lazy في الواجهة البرمجية API. أُزيلت الخاصيتان تمامًا في النسخة 11.

لم يُشر إلى هذا الخيار في توثيق Next.js منذ النسخة 8 لهذا من غير المحتمل أن تراه مستخدمًا في أي تطبيق.

إزالة Head.rewind

لم يعد للتابع Head.rewind استخدام منذ النسخة 9.5 وأزيل في النسخة 11. بإمكانك إزالة هذا التابع بأمان إن كنت قد استخدمته.

استثناء الإعدادات المحلية Moment.js افتراضيًا

يتضمن الملف "Moment.js" ترجمة للكثير من الإعدادات المحلية افتراضيًا. وتستثني Next.js الآن افتراضيًا هذه الملفات لتحسين حجم تجميعة التطبيقات التي تستخدمها. ولهذا عليك أن تستخدم الشيفرة التالية لتضمين أي إعداد محلي:

import moment from 'moment'
import 'moment/locale/ja'

moment.locale('ja')

تستطيع تعطيل هذا الخيار الافتراضي بإضافة excludeDefaultMomentLocales: false إلى ملف التهيئة next.config.js. لكن عليك الانتباه بأن تعطيله غير محبّذ إطلاقًا لأنه يؤثر على إجراءات التحسين التي تساهم كثيرًا في تقليل حجم الملف "Moment.js".

تحديث استخدام router.events

إن كنت تصل إلى router.events خلال التصيير فلن تتمكن من ذلك بعد الآن في Next.js 11 خلال التصيير المسبق. تأكد من استخدام useEffect للوصول إلى router.events:

useEffect(() => {
  const handleRouteChange = (url, { shallow }) => {
    console.log(
      `App is changing to ${url} ${
        shallow ? 'with' : 'without'
      } shallow routing`
    )
  }

  router.events.on('routeChangeStart', handleRouteChange)

  // إن لم يكن المكوّن مثبتًا، فألغ الوصول إلى 
  // `off` الحدث باستخدام التابع 
  return () => {
    router.events.off('routeChangeStart', handleRouteChange)
  }
}, [router])

إن كنت تستخدم router.router.events في تطبيقك وهي خاصية داخلية لم تكن عامة، تأكد من استخدام router.events أيضًا.

استخدام React 16 وReact 17

أضافت React 17 تحويلات JSX Transform جديدة أتاحت إمكانية استخدام الإدراج import React from 'react' في Next.js عند استخدام بيئة React. تستخدم Next.js التحويل الجديد تلقائيًا مع النسخة 17 من React، والذي لا يجعل المتغير React متغيرًا عامًا لأن ذلك أدى إلى آثار جانبية غير مقصودة سابقًا. بالإمكان الآن استخدام تحويلات Codemode لإصلاح الحالات التي تستخدم فيها React دون إدراج.

الترقية من الإصدار 9 إلى 10 في Next.js

لا توجد تغييرات كبيرة بين الإصدارين 9 و 10، وكل ما عليك للترقية هو تنفيذ الأمر التالي:

npm install next@10

أو:

yarn add next@10

الترقية من الإصدار 8 إلى 9 في Next.js

تمهيد

نشر نسخة الإنتاج على Vercel

إن كنت قد هيأت routes في ملف vercel.json لتكون ديناميكية، بالإمكان إزالة هذه القواعد عند الانتقال إلى الإصدار 9 لوجود ميزة التوجيه الديناميكي. لا تتطلب الوجهات الديناميكية في الإصدار 9 أية تهيئة مخصصة عند النشر على Vercel بل تُهيأ تلقائيًا.

التحقق من التطبيقات المخصصة pages/_app.js

إن اطلعت سابقًا على المثال الذي أوردناه في صفحة التطبيقات المخصصة باستخدام App"، سترى أنه من الممكن إزالة الدالة getInitialProps.

من المهم جدًا إزالة getInitialProps من التطبيقات المخصصة pages/_app.js عندما يكون ذلك ممكنًا لاستخدام ميزات Next.js الجديدة. فليس للدالة getInitialProps مثلًا عمل في هذه الشيفرة وبالإمكان إزالتها:

class MyApp extends App {
  // أزل هذه الشيفرة،فليس لهاوظيفة
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

  render() {
    // الخ
  }
}

تغييرات مفصلية

لا ضرورة لاستخدام التوجيه zeit/next-typescript@

تتجاهل في هذا الإصدار التوجيه zeit/next-typescript@ وتنبهك إلى ضرورة إزالته.

  • أزل الإضافة zeit/next-typescript@ من الملف next.config.js.
  • أزل الإشارات المرجعية إلى zeit/next-typescript@ في الملف babelrc. إن وجد.
  • أزل الملحق fork-ts-checker-webpack-plugin من الملف next.config.js.
  • تُنشر تعريفات TypeScript ضمن حزمة next، لهذا عليك إزالة types/next@ لمنع حدوث تعارض.
  • تختلف الأنواع التالية من:
import { NextContext } from 'next'
import { NextAppContext, DefaultAppIProps } from 'next/app'
import { NextDocumentContext, DefaultDocumentIProps } from 'next/document'

إلى:

import { NextPageContext } from 'next'
import { AppContext, AppInitialProps } from 'next/app'
import { DocumentContext, DocumentInitialProps } from 'next/document'

ملاحظة: أعدَّ هذه القائمة مجتمع Next لمساعدتك على الترقية، فإن وجدت اختلافات أخرى يمكن إرسال طلب سحب pull-request على هذه القائمة (في GitHub) لمساعدة بقية المستخدمين.

تصدير المفتاح config

لم يعد بالإمكان تصدير متغير اسمه config من الصفحة كالتالي:

export { config }
// أو
export const config ...

يُستخدم هذا المتغيّر المُصدّر الآن لتخصيص إعداد Next.js على مستوى الصفحة مثل حالة استخدام AMP أو موجهات API.

عليك إعادة تسمية أي متغير config عند تصديره إن كان لا يتعلق بإعدادات Next.js

لا يصيّر next/dynamic أي شيء افتراضيًا أثناء التحميل

على الرغم من ذلك، يمكنك تخصيص هذا السلوك بضبط قيمة الخاصية loading:

import dynamic from 'next/dynamic'

const DynamicComponentWithCustomLoading = dynamic(
  () => import('../components/hello2'),
  {
    loading: () => <p>Loading</p>,
  }
)

إزالة withAmp لصالح كائن تهيئة مُصدّر

تعتمد Next.js في هذا الإصدار مفهوم التهيئة على مستوى الصفحات، لهذا أزيل مكوّن المستوى الأعلى withAmp. يمكن تهجير migrate هذا الإعداد تلقائيًا بتنفيذ الشيفرة التالية في جذر مشروعك:

curl -L https://github.com/vercel/next-codemod/archive/master.tar.gz | tar -xz --strip=2 next-codemod-master/transforms/withamp-to-config.js npx jscodeshift -t ./withamp-to-config.js pages/**/*.js

لتنفيذ هذا التهجير يدويًا أو متابعة ما يولّده تحويل codemode، ألق نظرة على التالي: قبل:

import { withAmp } from 'next/amp'

function Home() {
  return <h1>My AMP Page</h1>
}

export default withAmp(Home)
// or
export default withAmp(Home, { hybrid: true })

بعد:

export default function Home() {
  return <h1>My AMP Page</h1>
}

export const config = {
  amp: true,
  // or
  amp: 'hybrid',
}

لن تصدر next export الصفحات إلى index.html

صُدِّر الملف pages/about.js سابقًا إلى out/about/index.html. لكنه يُصدَّر الآن إلى out/about.html.

يمكنك العودة إلى السلوك السابق بإضافة الإعداد التالي إلى next.config.js:

// next.config.js
module.exports = {
  trailingSlash: true,
}

معاملة مختلف مكونات المجلد /pages/api

تُعد جميع الملفات في هذا المجلد وجهات API، ولن يتضمن تجميعات خاصة بواجهة العميل.

الميزات الملغاة في Next.js

إلغاء تحميل عدة وحدات برمجية معًا من خلال next/dynamic

وذلك كي يشابه المكوّن next/dynamic الكائنات (React.lazy و Suspense) في React.

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

قبل:

import dynamic from 'next/dynamic'

const HelloBundle = dynamic({
  modules: () => {
    const components = {
      Hello1: () => import('../components/hello1').then((m) => m.default),
      Hello2: () => import('../components/hello2').then((m) => m.default),
    }

    return components
  },
  render: (props, { Hello1, Hello2 }) => (
    <div>
      <h1>{props.title}</h1>
      <Hello1 />
      <Hello2 />
    </div>
  ),
})

function DynamicBundle() {
  return <HelloBundle title="Dynamic Bundle" />
}

export default DynamicBundle

بعد:

import dynamic from 'next/dynamic'

const Hello1 = dynamic(() => import('../components/hello1'))
const Hello2 = dynamic(() => import('../components/hello2'))

function HelloBundle({ title }) {
  return (
    <div>
      <h1>{title}</h1>
      <Hello1 />
      <Hello2 />
    </div>
  )
}

function DynamicBundle() {
  return <HelloBundle title="Dynamic Bundle" />
}

export default DynamicBundle

المصادر