باعتبارها "أسد الحصار" للواجهة الأمامية، فإن Webpack مألوف جدًا ويمكنه القيام بالعديد من الأشياء، ويمكنه تجميع جميع الموارد (بما في ذلك JS وTS وJSX والصور والخطوط وCSS وما إلى ذلك) ووضعها في التبعيات. ، مما يسمح لك بالرجوع إلى التبعيات لاستخدام الموارد وفقًا لاحتياجاتك. لقد قام Webpack بعمل ممتاز في ترجمة موارد الملفات المتعددة على الواجهة الأمامية وتحليل تبعيات الوحدة المعقدة، ويمكننا أيضًا تخصيص المُحمل وتحميل مواردنا الخاصة بحرية. تعال وألقي نظرة اليوم.
1. ما هو المطلوب؟
عندما يتعلق الأمر بالطلب، فإن أول ما يتبادر إلى الذهن هو الاستيراد، وهو معيار بناء جملة لـ es6
- يتطلب الأمر استدعاء وقت التشغيل، لذلك يمكن استخدامه نظريًا في أي مكان في الكود -
الاستيراد هو وقت الترجمة استدعاء، لذلك يجب وضعه في بداية الملف؛
عندما نستخدم Webpack للتجميع، سنستخدم babel لترجمة الاستيراد إلى require في CommonJS، والذي يُستخدم لتحميل الوحدات تستخدم AMD وCMD أيضًا الطريقة المطلوبة للرجوع إليها.
على سبيل المثال:
var add = require('./a.js');بعبارات بسيطة،
add(1,2)
require هي في الواقع دالة، والمرجع ./a.js
هو مجرد معلمة للدالة.
2. ما هي الصادرات؟
هنا يمكننا التفكير في الصادرات ككائن. يمكنك رؤية الاستخدام المحدد لتصدير MDN.
دعونا نلقي نظرة أولاً على بنية الكود بعد التعبئة والتغليف، ويمكننا أن نجد أن المتطلبات والصادرات ستظهر بعد التعبئة.
لا يمكن لجميع المتصفحات تنفيذ عمليات التصدير المطلوبة، ويجب عليك تنفيذ عمليات التصدير والتصدير بنفسك لضمان التشغيل العادي للتعليمات البرمجية. التعليمات البرمجية المعبأة هي وظيفة ذاتية التنفيذ، تحتوي المعلمات على معلومات التبعية ورمز الملف الذي يتم تنفيذه ينفذ التعليمات البرمجية من خلال التقييم.
الرسم التصميمي العام هو كما يلي:
الخطوة 1: اكتب ملف التكوين الخاص بنا.
يقوم ملف التكوين بتكوين الإدخال المعبأ ومخرجات الخروج المعبأة للتحضير للملفات التي تم إنشاؤها لاحقًا.
مسار ثابت = يتطلب ("مسار")؛ وحدة التصدير = { الإدخال: "./src/index.js"، الإخراج: { المسار: path.resolve(__dirname, "./dist"),// يتطلب إخراج عنوان الملف بعد التعبئة مسارًا مطلقًا، لذا فإن المسار مطلوب اسم الملف: "main.js" }, الوضع: "التطوير"
الخطوة 2: الفكرة العامة لتحليل الوحدة
: باختصار، يتم استخدام ملف fs لقراءة ملف الإدخال والحصول على مسار الملف المعتمد على الاستيراد من خلال AST إذا كان الملف التابع لا يزال لديه تبعيات، استمر في التكرار حتى يصبح تحليل التبعية واضحًا، ويتم الحفاظ عليه في الخريطة.
تفصيل تفصيلي : قد يتساءل بعض الأشخاص عن سبب استخدام AST، لأن AST ولد مع هذه الوظيفة، ويمكن أن يساعدنا إعلان الاستيراد الخاص به في تصفية بنية الاستيراد بسرعة السلسلة بعد قراءتها. من خلال الكتابة، يعد التعبير العادي الرائع مفيدًا للحصول على مسارات تبعية الملف، ولكنه ليس أنيقًا بدرجة كافية.
ملف Index.js
{str} من "./a.js"؛ console.log(`${str} Webpack`)
استيراد
ملف a.js
{ b} من "./b.js"تصدير ملف const str = "hello"
b.js
تصدير const b="bbb"
تحليل وحدة Webpack: استخدم @babel/parser الخاص بـ AST لتحويل السلسلة المقروءة من الملف إلى شجرة AST، و@babel/traverse لـ بناء الجملة تحليل واستخدام ImportDeclaration لتصفية الواردات والعثور على تبعيات الملف.
محتوى const = fs.readFileSync(entryFile, "utf-8"); const ast = parser.parse(content, { sourceType: "module" }); const dirname = path.dirname(entryFile); تابعون ثابتون = {}; اجتياز (أست، { إعلان الاستيراد({ العقدة }) { // تصفية الواردات const newPathName = "./" + path.join(dirname,node.source.value); التابعون[node.source.value] = newPathName; } }) const {code} = TransformFromAst(ast, null, { الإعدادات المسبقة: ["@babel/preset-env"] }) يعود { ملف إدخال, المعالين, شفرة }
وكانت النتائج كما يلي:
استخدم العودية أو الحلقة لاستيراد الملفات واحدًا تلو الآخر لتحليل التبعية. لاحظ هنا أننا نستخدم حلقة for لتحليل جميع التبعيات. السبب وراء قدرة الحلقات على تحليل جميع التبعيات هو أن طول الوحدات يتغير عندما تكون هناك تبعيات تبعيات جديدة، Modules.length سوف تتغير.
for (let i = 0; i < this.modules.length; i++) { عنصر ثابت = this.modules[i]; const { المعالين } = العنصر؛ إذا (المعالين) { لـ (دع j في المعالين) { this.modules.push(this.parse(dependents[j])); } } }
الخطوة 3: كتابة وظيفة WebpackBootstrap + إنشاء ملف الإخراج.
كتابة وظيفة WebpackBootstrap : أول شيء يتعين علينا القيام به هنا هو وظيفة WebpackBootstrap، بعد التجميع، سيتم تحليل استيراد كود المصدر الخاص بنا إلى require لا يتعرف على المتطلبات، لذا يجب أن نعلن عنها أولاً، فالطلب هو طريقة عند كتابة الوظائف، تحتاج أيضًا إلى الانتباه إلى عزل النطاق لمنع التلوث المتغير. نحتاج أيضًا إلى الإعلان عن عمليات التصدير في الكود الخاص بنا للتأكد من أن عمليات التصدير موجودة بالفعل عند تنفيذ الكود.
إنشاء ملف الإخراج : لقد كتبنا بالفعل عنوان الملف الذي تم إنشاؤه في ملف التكوين، ثم استخدم fs.writeFileSync لكتابته في مجلد الإخراج.
ملف (كود) { const filePath = path.join(this.output.path, this.output.filename) const newCode = JSON.stringify(code); // إنشاء محتوى ملف الحزمة const Bundle = `(function(modules){ تتطلب الوظيفة (الوحدة النمطية) { مسار الوظيفةRequire(relativePath){ يتطلب الإرجاع (الوحدات [الوحدة النمطية]. التابعون [relativePath]) } الصادرات الثابتة = {}؛ (وظيفة (تتطلب، الصادرات، رمز) { تقييم (رمز) })(pathRequire,exports,modules[module].code); عودة الصادرات } تتطلب('${this.entry}') })(${newCode})`; // WebpackBoostrap // إنشاء ملف. ضعه في دليل التوزيع fs.writeFileSync(filePath,bundle,'utf-8') }
الخطوة 4: تحليل تسلسل التنفيذ
يمكننا تشغيل النتيجة المجمعة في وحدة تحكم المتصفح إذا كانت تعمل بشكل طبيعي، فيجب طباعة hello Webpack.
من خلال التحليل أعلاه، يجب أن يكون لدينا فهم أساسي للعملية العامة لـ Webpack. إن استخدام AST لتحليل الكود هو مجرد طريقة لهذا العرض التوضيحي، وليس التنفيذ الحقيقي لـ Webpack له طريقة تحليل AST الخاصة به نظام Webpack البيئي دائم التغير، ويمكن للأطفال المهتمين التفكير في الأسئلة الثلاثة التالية: