الحفاظ على التحكم: دليل Webpack و React ، Pt. 2

نشرت: 2022-03-11

في الجزء الأول من هذا البرنامج التعليمي React-Webpack ، ناقشنا كيفية تكوين أدوات التحميل وإجراء التحسين. الآن ، سوف ندخل في تقنيات أكثر تقدمًا تتعلق بحالات استخدام تهيئة React / Webpack المحددة.

اكتب سكريبت وتفاعل مع Webpack: أدخل Babel

هناك عدة طرق يمكنك من خلالها استخدام TypeScript في مشروع React الخاص بك. بينما يعد ts-loader خيارًا جيدًا ، أود التركيز على كيفية تحويل TypeScript باستخدام @babel/preset-typescript لأن العديد من المكتبات تنشر إضافات Babel لأداء تحسين وقت الترجمة. بالإضافة إلى معالجة ملفات TypeScript ، سيسمح لنا باستخدام ملحقات Babel التي توفرها مكتبات مختلفة مثل المكوّنات المصممة أو React-intl.

أول شيء يتعين علينا القيام به هو تثبيت تبعيات TypeScript و Babel:

 npm install -D typescript @babel/preset-typescript @types/react @types/react-dom

سننشئ بعد ذلك ملف تكوين TypeScript باستخدام برنامج سطر الأوامر tsc :

 ./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules

سينشئ الأمر أعلاه tsconfig.json مناسبًا لكتابة التعليمات البرمجية لبيئة المتصفح. يفرض الخيار --isolatedModules بعض القيود التي تتأكد من أن الكود الذي تكتبه سيكون متوافقًا مع @babel/plugin-transform-typescript . يعد هذا الخيار مفيدًا حتى يقوم IDE الخاص بك بتحذيرك عندما تكتب رمزًا بطريقة لن يتمكن Babel من تحويلها.

بعد ذلك ، سنقوم بتحديث babel.config.js من خلال تقديم إعداد مسبق جديد:

 @@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",

وقم بتمكين امتداد الملف .ts في webpack.config.js :

 @@ -11,7 +11,7 @@ module.exports = function(_env, argv) { return { devtool: isDevelopment && "cheap-module-source-map", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "assets/js/[name].[contenthash:8].js", @@ -20,7 +20,7 @@ module.exports = function(_env, argv) { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", @@ -61,6 +61,9 @@ module.exports = function(_env, argv) { } ] }, + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"] + }, plugins: [ isProduction && new MiniCssExtractPlugin({

التكوين أعلاه كافٍ لتكون قادرًا على تحويل الكود الخاص بنا ولكنه لا يتحقق من صحته بالفعل. سنحتاج إلى إجراء فحص النوع في عملية منفصلة متوازية باستخدام fork-ts-checker-webpack-plugin .

أولاً ، نحتاج إلى تثبيته:

 npm install -D fork-ts-checker-webpack-plugin

بعد ذلك ، سنضيفه إلى قسم plugins في webpack.config.js :

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -78,6 +79,9 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new ForkTsCheckerWebpackPlugin({ + async: false }) ].filter(Boolean), optimization: {

سيؤدي تحديد غير async: false إلى منع Webpack من إرسال تعليمات برمجية غير صالحة وإظهار أخطاء تجميع في تراكب عند تشغيل خادم تطوير.

ملاحظة: قد تكون مهتمًا أيضًا بوحدات ماكرو Babel ، والتي تكتسب قوة دفع.

CSS ، مُحسَّن عبر Webpack

في المقالة السابقة ، غطينا التصميم الأساسي باستخدام css-loader . هناك عدة طرق يمكننا من خلالها تحسين هذا التكوين.

سيستفيد التكوين المقترح من تقنيات CSS Modules و Sass و PostCSS. على الرغم من أنها تكمل بعضها البعض من بعض النواحي ، إلا أنك لست بحاجة إلى استخدامها جميعًا في نفس الوقت. الإعداد النهائي سيتم تمكين جميع المكونات الإضافية المذكورة أعلاه ، وسنترك الأمر لك لترك شيء ما خارجًا إذا كنت متأكدًا من أنك "لن تحتاجه".

وحدات CSS

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

تم تضمين دعم CSS Modules بالفعل في css-loader . سنحتاج الآن إلى إضافة قاعدة جديدة لتوضيح متى تكون وحدات CSS قيد الاستخدام:

 @@ -33,11 +33,25 @@ module.exports = function(_env, argv) { }, { test: /\.css$/, use: [ isProduction ? MiniCssExtractPlugin.loader : "style-loader", "css-loader" ] }, + { + test: /\.module.css$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + modules: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

مع ذلك ، ستتم معالجة أي ملف ينتهي .module.css مع تمكين وحدات CSS النمطية.

PostCSS

PostCSS هو إطار عمل معالجة CSS قابل للتوسيع مع مكتبة ضخمة من المكونات الإضافية التي يمكنك استخدامها لتوسيع بناء جملة CSS أو إجراء التحسين أو توفير احتياطيات للمتصفحات القديمة.

أولاً ، سنقوم بتثبيت التبعيات الضرورية:

 npm install -D postcss-loader postcss-import postcss-preset-env

وتحديث تكوين CSS لدينا:

 @@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {

سنقوم بتكوين PostCSS باستخدام المكونات الإضافية التالية:

  • postcss-import : يُمكِّن PostCSS من معالجة جمل @import
  • postcss-preset-env : يطبق polyfill لدعم ميزات CSS الحديثة في معظم المتصفحات

قم بإنشاء ملف يسمى postcss.config.js وقم بتعبئته بما يلي:

 module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };

يمكنك التحقق من دليل المكون الإضافي PostCSS للحصول على امتدادات أخرى قد تجدها مفيدة وإضافتها إلى التكوين الخاص بك.

ساس / SCSS

Sass هو إطار معالجة CSS شائع آخر. على عكس PostCSS ، تأتي Sass مع "بطاريات مضمنة". من خارج الصندوق ، يقدم Sass دعمًا للقواعد المتداخلة والمزج وقواعد إعادة الكتابة للتوافق مع الإصدارات السابقة. بينما تهدف PostCSS إلى الحفاظ على بناء جملة CSS القياسي ، قد تختلف بنية Sass عن مواصفات CSS. على الرغم من ذلك ، يعد Sass حلاً واسع الانتشار لدرجة أن استخدامه لتأليف CSS قد يكون مجرد خيار أسهل - ولكنه خيار يعتمد على متطلباتك.

أولاً ، سنقوم بتثبيت التبعيات الضرورية:

 npm install -D sass-loader node-sass resolve-url-loader

بعد ذلك ، أضف أداة تحميل جديدة إلى تكوين Webpack الخاص بنا:

 @@ -38,6 +38,25 @@ module.exports = function(_env, argv) { "css-loader" ] }, + { + test: /\.s[ac]ss$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 2 + } + }, + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

لقد عالجنا بشكل استباقي مشكلتين مع المقتطف أعلاه:

  1. قدمنا resolve-url-loader بعد sass-loader لجعل الواردات النسبية تعمل من ملفات @import ed Sass.

  2. حددنا خيار importLoaders لـ css-loader لمعالجة ملفات @import -ed باستخدام أدوات التحميل التي تتبعها.

باستخدام التكوين أعلاه ، يمكننا البدء في تأليف أنماطنا باستخدام Sass / SCSS بالإضافة إلى PostCSS و CSS Modules التي وصفناها من قبل. على الرغم من أنه يمكن تمكين كل هذه الخيارات في وقت واحد ، إلا أنك لست مضطرًا لاستخدامها جميعًا داخل نفس المشروع ، لذا يمكنك اختيار الأداة الوحيدة التي تناسب متطلباتك.

عمال الويب

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

يجعل Webpack من السهل استخدام العاملين على الويب مع worker-loader ، والذي يجمع ملفات العمال في دليل الإخراج ويوفر فئة عامل إلى ملف المستهلك.

أولاً ، نحتاج إلى تثبيت worker-loader :

 npm install -D worker-loader

ثم قم بإضافته إلى ملف التكوين الخاص بنا:

 @@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [

الآن ، كل ما عليك القيام به لبدء استخدام العاملين على الويب هو إنشاء مثيل لفئة تم استيرادها من ملف ينتهي .worker.js الذي يقوم بتنفيذ Worker API العادي.

عمال الخدمة

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

يعمل Webpack على تسهيل تكوين عمال الخدمة لتطبيقك باستخدام الوحدة النمطية workbox-webpack-plugin. أولاً ، نحتاج إلى تثبيته:

 npm install -D workbox-webpack-plugin

بعد ذلك ، سنضيف المكون الإضافي إلى قسم plugins في تكوين Webpack الخاص بنا:

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -75,6 +76,11 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new WorkboxPlugin.GenerateSW({ + swDest: "service-worker.js", + clientsClaim: true, + skipWaiting: true }) ].filter(Boolean), optimization: {

يستخدم التكوين أعلاه الخيارات التالية:

  • يحدد swDest اسم ملف الإخراج لملف العامل الذي تم إنشاؤه.
  • clientsClaim يوجه عامل الخدمة للسيطرة على الصفحة مباشرة بعد التسجيل والبدء في تقديم الموارد المخزنة مؤقتًا بدلاً من انتظار إعادة تحميل الصفحة التالية.
  • يجعل skipWaiting التحديثات لعامل الخدمة سارية المفعول على الفور بدلاً من انتظار تدمير جميع المثيلات النشطة.

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

أخيرًا ، نحتاج إلى تسجيل عامل الخدمة عندما يفتح المستخدم تطبيقنا:

 @@ -2,3 +2,9 @@ import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render(<h3>React App</h3>, document.getElementById("root")); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker.register("/service-worker.js"); + }); +}

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

التكوين المتقدم لحزمة ويب React: إضفاء ميزة على مشروعك

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

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