مرحبا يا هبر!
يسمح لك كل متصفح حديث الآن بالعمل مع
وحدات ES6 .
للوهلة الأولى ، يبدو أن هذا شيء عديم الفائدة تمامًا - بعد كل شيء ، نحن نستخدم جميع هواة الجمع الذين يستبدلون الواردات بتحدياتهم الداخلية. ولكن إذا كنت تتعمق في المواصفات ، اتضح أنه بفضلها يمكنك إعطاء تجميع منفصل للمتصفحات الحديثة.
تحت القطة قصة عن كيف تمكنت من تقليل حجم التطبيق بنسبة 11 ٪ دون المساس بالمتصفحات القديمة وأعصابي.
ميزات وحدات ES6
وحدات ES6 هي نظام معياري معروف ومستخدم على نطاق واسع للجميع:
import { someFunc } from 'path/to/helpers.js'
export function someFunc() { }
لاستخدام هذا النظام المعياري في المتصفحات ، تحتاج إلى إضافة نوع الوحدة إلى كل علامة برنامج نصي. سترى المتصفحات الأقدم أن النوع مختلف عن النص / جافا سكريبت ، ولن ينفذ الملف بتنسيق JavaScript.
<script type="module" src="/path/to/someFile.js"></script>
تحتوي المواصفات أيضًا على سمة ترميز لعلامات البرنامج النصي.
ستتجاهل المتصفحات التي تدعم
وحدات ES6 هذا النص البرمجي ، وستقوم المتصفحات القديمة بتنزيله وتنفيذه.
<script nomodule src="/path/to/someFileFallback.js"></script>
اتضح أنه يمكنك ببساطة إنشاء مجموعتين: الأولى بنوع الوحدة للمتصفحات الحديثة (البناء الحديث) ، والأخرى مع الرمز للمتصفحات القديمة (بناء احتياطي):
<script type="module" src="/path/to/someFile.js"></script> <script nomodule src="/path/to/someFileFallback.js"></script>
لماذا هو ضروري
قبل إرسال مشروع إلى الإنتاج ، يجب علينا:
- قم بإضافة polyphiles.
- تحويل الرمز الحديث إلى رمز أقدم.
في مشاريعي ، أحاول دعم الحد الأقصى لعدد المتصفحات ، وأحيانًا حتى
IE 10 . لذلك ، تتكون قائمة الملفات المتعددة الخاصة بي من أشياء أساسية مثل es6.promise ، es6.object.values ، إلخ. لكن المتصفحات التي تحتوي على
وحدات ES6 تدعم جميع طرق ES6 ، ولا تحتاج إلى كيلوبايتات إضافية من الرقائق المتعددة.
تترك عملية النقل أيضًا علامة ملحوظة على حجم الملف: يستخدم babel / preset-env 25 محولًا لتغطية معظم المتصفحات ، وكل منها يزيد من حجم الشفرة. في الوقت نفسه ، بالنسبة للمتصفحات التي تدعم
وحدات ES6 ، يتم تقليل عدد المحولات إلى 9.
لذلك ، في التجميع للمتصفحات الحديثة ، يمكننا إزالة ملفات غير ضرورية وتقليل عدد المحولات ، مما سيؤثر بشكل كبير على حجم الملفات الناتجة!
كيفية إضافة بولي فايلز
قبل الذهاب لإعداد Modern Build للمتصفحات الحديثة ، من الجدير بالذكر كيف أقوم بإضافة polyfill إلى المشروع.
عادة ، تستخدم المشاريع Core-js لإضافة جميع أنواع البوليفيل الممكنة.
بالطبع ، لا تريد جميع ملفات 88 كيلوبايت من هذه المكتبة ، ولكن فقط تلك المطلوبة لقائمة المستعرضات الخاصة بك. تتوفر هذه الميزة باستخدام babel / preset-env وخيار useBuiltIns. إذا قمت بتعيينه على الإدخال ، فسيتم استبدال استيراد Core-js باستيراد الوحدات الفردية التي تحتاجها المتصفحات:
module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'entry', }] ], };
import 'core-js';
import "core-js/modules/es6.array.copy-within"; import "core-js/modules/es6.array.fill"; import "core-js/modules/es6.array.find";
ولكن من خلال هذا التحول ، تخلصنا فقط من جزء من البوليفيلات القديمة غير الضرورية. لا يزال لدينا polyphiles لـ TypedArray و WeakMap وأشياء غريبة أخرى لم يتم استخدامها مطلقًا في المشروع.
للتغلب على هذه المشكلة تمامًا ، بالنسبة لخيار useBuiltIns ، أضبط القيمة على الاستخدام. في مرحلة التجميع ، سيقوم babel / preset-env بتحليل الملفات لاستخدام الميزات غير المتاحة في المستعرضات المحددة ، وإضافة ملفات متعددة إليها:
module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage', }] ], };
function sortStrings(strings) { return strings.sort(); } function createResolvedPromise() { return Promise.resolve(); }
import "core-js/modules/es6.array.sort"; import "core-js/modules/es6.promise"; function sortStrings(strings) { return strings.sort(); } function createResolvedPromise() { return Promise.resolve(); }
في المثال أعلاه ، أضاف babel / preset-env ملفًا متعددًا إلى دالة الفرز. لا يمكنك معرفة في JavaScript نوع الكائن الذي سيتم تمريره إلى الوظيفة - سيكون مصفوفة أو كائن فئة مع وظيفة الفرز ، ولكن babel / preset-env يحدد السيناريو الأسوأ لنفسه ويدرج ملف متعدد.
الحالات التي تكون فيها babel / preset-env خاطئة تحدث طوال الوقت. لإزالة polyphiles غير الضرورية ، تحقق من وقت لآخر من تلك التي تستوردها ، واحذف منها غير الضرورية باستخدام خيار الاستبعاد:
module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage',
أنا لا أعتبر وحدة وقت تشغيل المولد ، حيث أستخدم المزامنة السريعة ( وأنا أنصح الجميع ).إنشاء بناء حديث
لنقم بإعداد البناء الحديث.
تأكد من أن لدينا ملف قائمة مستعرضات في المشروع يصف جميع المتصفحات الضرورية:
/* .browserslistrc */ > 0.5% IE 10
أضف متغير البيئة BROWSERS_ENV أثناء البناء ، والذي يمكن أن يأخذ القيم الاحتياطية (للبناء الاحتياطي) والحديث (للبناء الحديث):
/* package.json */ { "scripts": { /* ... */ "build": "NODE_ENV=production webpack /.../", "build:fallback": "BROWSERS_ENV=fallback npm run build", "build:modern": "BROWSERS_ENV=modern npm run build" }, /* ... */ }
الآن قم بتغيير تكوين babel / preset-env. لتحديد المستعرضات المدعومة في الإعداد المسبق ، هناك أهداف خيار. لديها اختصار خاص - بقايا. عند استخدامه ، سيقوم babel / preset-env تلقائيًا باستبدال المتصفحات التي تدعم
وحدات ES6 .
const isModern = process.env.BROWSERS_ENV === 'modern'; module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage',
ستقوم Babel / preset-env بكل العمل نيابة عنا: ستختار فقط المواد المتعددة والتحويلات الضرورية.
الآن يمكننا بناء مشروع للمتصفحات الحديثة أو القديمة مجرد أمر من وحدة التحكم!
ربط الحديث والبناء الاحتياطي
والخطوة الأخيرة هي الجمع بين البنيات الحديثة والرجعية في واحد.
أخطط لإنشاء مثل هذا المشروع:
في index.html سيكون هناك روابط لملفات جافا سكريبت الضرورية من التجميعين:
/* index.html */ <html> <head> </head> <body> <script type="module" src="/modern/js/app.540601d23b6d03413d5b.js"></script> <script nomodule src="/fallback/js/app.4d03e1af64f68111703e.js"></script> </body> </html>
يمكن تقسيم هذه الخطوة إلى ثلاثة أجزاء:
- بناء الحديث والبناء الاحتياطي في أدلة مختلفة.
- الحصول على معلومات حول مسارات ملفات جافا سكريبت الضرورية.
- إنشاء index.html بروابط لجميع ملفات جافا سكريبت.
دعنا نبدأ!
بناء الحديث والبناء الاحتياطي في أدلة مختلفة
بادئ ذي بدء ، دعنا نتخذ أسهل خطوة - سوف نجمع Modern & Fallback Build في دلائل مختلفة داخل دليل dist.
من المستحيل ببساطة تحديد الدليل المطلوب لـ output.path ، نظرًا لأننا نحتاج إلى حزمة ويب تحتوي على مسارات للملفات المتعلقة بالدليل dist (يوجد index.html في هذا الدليل ، وسيتم ضخ كل التبعيات الأخرى بالنسبة إليه).
قم بإنشاء وظيفة خاصة لتوليد مسارات الملفات:
const path = require('path'); const isModern = process.env.BROWSERS_ENV === 'modern'; const prefix = isModern ? 'modern' : 'fallback'; module.exports = relativePath => ( path.join(prefix, relativePath) );
const getFilePath = require('path/to/getFilePath'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { mode: 'production', output: { path: 'dist', filename: getFilePath('js/[name].[contenthash].js'), }, plugins: [ new MiniCssExtractPlugin({ filename: getFilePath('css/[name].[contenthash].css'), }), ], }
بدأ المشروع في التجمع في أدلة مختلفة للبناء الحديث و Fallback.
الحصول على معلومات حول مسارات ملفات جافا سكريبت الضرورية
للحصول على معلومات حول الملفات التي تم جمعها ، قم بتوصيل المكون الإضافي webpack-manifest-plugin. في نهاية التجميع ، سيضيف ملف manifest.json مع بيانات عن مسارات الملفات:
const getFilePath = require('path/to/getFilePath'); const WebpackManifestPlugin = require('webpack-manifest-plugin'); module.exports = { mode: 'production', plugins: [ new WebpackManifestPlugin({ fileName: getFilePath('manifest.json'), }), ], }
الآن لدينا معلومات حول الملفات التي تم جمعها:
{ "app.js": "/fallback/js/app.4d03e1af64f68111703e.js", }
إنشاء index.html بروابط لجميع ملفات جافا سكريبت
الشيء الوحيد المتبقي هو إضافة index.html وإدخال المسارات إلى الملفات الضرورية فيه.
لإنشاء ملف html ، سأستخدم المكون الإضافي html-webpack-plugins أثناء الإنشاء الحديث. سيقوم html-webpack-plugin بإدخال المسارات إلى الملفات الحديثة نفسها ، وسأحصل على المسارات إلى الملفات الاحتياطية من الملف الذي تم إنشاؤه في الخطوة السابقة ولصقه في HTML باستخدام مكون إضافي صغير لحزمة الويب:
const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModernBuildPlugin = require('path/to/ModernBuildPlugin'); module.exports = { mode: 'production', plugins: [ ...(isModern ? [
تحديث الحزمة. json:
/* package.json */ { "scripts": { /* ... */ "build:full": "npm run build:fallback && npm run build:modern" }, /* ... */ }
باستخدام npm run build: الأمر الكامل ، سننشئ ملف html واحدًا باستخدام Modern and Fallback Build. سيتلقى أي متصفح الآن جافا سكريبت يمكنه تنفيذه.
أضف بناء حديث إلى تطبيقك
لاختبار الحل الخاص بي على شيء حقيقي ، دفعته إلى أحد مشاريعي. استغرق إعداد التهيئة أقل من ساعة ، وانخفض حجم ملفات JavaScript بنسبة 11٪. نتيجة رائعة مع تنفيذ بسيط.
شكرا لقراءة المقال حتى النهاية!
المواد المستخدمة