الحفاظ على التحكم: دليل 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: {
لقد عالجنا بشكل استباقي مشكلتين مع المقتطف أعلاه:
قدمنا
resolve-url-loader
بعدsass-loader
لجعل الواردات النسبية تعمل من ملفات@import
ed Sass.حددنا خيار
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 وقسم المكونات الإضافية للعثور على المزيد من الوصفات التي تنطبق على أهدافك. شكرا لقرائتك!