ในฐานะ front-end "siege lion" Webpack นั้นคุ้นเคยกันดีอยู่แล้ว Webpack สามารถทำสิ่งต่าง ๆ มากมายเกินไป มันสามารถรวมทรัพยากรทั้งหมดไว้เป็นแพ็คเกจ (รวมถึง JS, TS, JSX, รูปภาพ, แบบอักษร, CSS และอื่น ๆ ) และวางไว้ในการอ้างอิง . ช่วยให้คุณสามารถอ้างอิงการพึ่งพาเพื่อใช้ทรัพยากรได้ตามความต้องการของคุณ Webpack ทำงานได้อย่างยอดเยี่ยมในการแปลทรัพยากรไฟล์หลายรายการในส่วนหน้าและวิเคราะห์การพึ่งพาโมดูลที่ซับซ้อน เรายังปรับแต่งตัวโหลดและโหลดทรัพยากรของเราเองได้อย่างอิสระ แล้ว Webpack จะนำบรรจุภัณฑ์ไปใช้อย่างไร วันนี้มาลองดูครับ.
1. ข้อกำหนดคืออะไร?
เมื่อพูดถึง need สิ่งแรกที่นึกถึงคือการนำเข้า คือการนำเข้าไวยากรณ์มาตรฐานของ es6
- need คือการเรียกรันไทม์ ดังนั้นในทางทฤษฎีแล้ว need สามารถใช้ได้ทุกที่ในโค้ด
- การนำเข้าคือเวลาคอมไพล์ ดังนั้นจะต้องวางไว้ที่จุดเริ่มต้นของไฟล์
เมื่อเราใช้ Webpack เพื่อคอมไพล์ เราจะใช้ babel เพื่อแปลการนำเข้าเป็น need . AMD และ CMD ยังใช้วิธีการที่ต้องการในการอ้างอิง
ตัวอย่างเช่น:
var add = need('./a.js');พูดง่ายๆ ก็คือ
add(1,2)
required จริงๆ แล้วเป็นฟังก์ชัน และ ./a.js
ที่อ้างอิงเป็นเพียงพารามิเตอร์ของฟังก์ชัน
2. การส่งออกคืออะไร?
ที่นี่เราถือว่าการส่งออกเป็นวัตถุ คุณสามารถดูการใช้งานเฉพาะของการส่งออก MDN
ได้ มาดูโครงสร้างรหัสหลังบรรจุภัณฑ์ของเราก่อน เราจะพบว่าข้อกำหนดดังกล่าวและการส่งออกจะปรากฏขึ้นหลังบรรจุภัณฑ์
เบราว์เซอร์บางประเภทไม่สามารถดำเนินการได้ซึ่งจำเป็นต้องมีการส่งออก คุณต้องใช้งานและส่งออกด้วยตนเองเพื่อให้แน่ใจว่าโค้ดทำงานได้ตามปกติ รหัสแพ็กเกจเป็นฟังก์ชันที่ดำเนินการด้วยตนเอง พารามิเตอร์มีข้อมูลการพึ่งพาและรหัสของไฟล์
ภาพวาดการออกแบบโดยรวมมีดังนี้:
ขั้นตอนที่ 1: เขียนไฟล์คอนฟิกูเรชันของเรา
ไฟล์คอนฟิกูเรชันจะกำหนดค่ารายการแพ็กเกจและเอาต์พุตแพ็กเกจทางออกเพื่อเตรียมพร้อมสำหรับไฟล์ที่สร้างขึ้นในภายหลัง
const path = need("เส้นทาง"); โมดูล.ส่งออก = { รายการ: "./src/index.js", เอาท์พุท: { path: path.resolve(__dirname, "./dist"),//ที่อยู่ไฟล์ที่ส่งออกหลังจากการแพ็กเกจต้องใช้เส้นทางที่แน่นอน ดังนั้นจึงต้องระบุเส้นทาง ชื่อไฟล์:"main.js" - โหมด: "การพัฒนา"
ขั้นตอนที่ 2: แนวคิดโดยรวมของการวิเคราะห์โมดูล
: โดยสรุปคือการใช้ไฟล์ fs เพื่ออ่านไฟล์รายการและรับเส้นทางของไฟล์ที่ต้องพึ่งพาการนำเข้าผ่าน AST หากไฟล์ที่ต้องพึ่งพายังคงอยู่ มีการขึ้นต่อกัน ทำซ้ำต่อไปจนกว่าการวิเคราะห์การขึ้นต่อกันจะชัดเจน และคงอยู่ในแผนที่
รายละเอียดโดยละเอียด : บางคนอาจสงสัยว่าเหตุใดจึงใช้ AST เนื่องจาก AST เกิดมาพร้อมกับฟังก์ชันนี้ ImportDeclaration สามารถช่วยให้เรากรองไวยากรณ์การนำเข้าได้อย่างรวดเร็ว แน่นอนว่าคุณสามารถใช้การจับคู่แบบปกติได้เช่นกัน สตริงหลังจากถูกอ่าน โดยการเขียน regex ที่ยอดเยี่ยมนั้นมีประโยชน์สำหรับการรับเส้นทางการพึ่งพาไฟล์ แต่ก็ยังไม่สวยงามพอ
ไฟล์ 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 (เนื้อหา { sourceType: "โมดูล" }); const dirname = path.dirname (รายการไฟล์); ผู้อยู่ในอุปการะ const = {}; สำรวจ (ast, { ImportDeclaration ({ โหนด }) { //กรองการนำเข้าออก const newPathName = "./" + path.join (dirname, node.source.value); ผู้อยู่ในอุปการะ [node.source.value] = newPathName; - - const { รหัส } = TransformerFromAst (ast, null, { ค่าที่ตั้งไว้ล่วงหน้า: ["@babel/preset-env"] - กลับ { ไฟล์รายการ, อยู่ในความอุปการะ, รหัส }
ผลลัพธ์มีดังนี้:
ใช้การเรียกซ้ำหรือการวนซ้ำเพื่อนำเข้าไฟล์ทีละไฟล์สำหรับการวิเคราะห์การพึ่งพา โปรดทราบว่าเราใช้ for loop เพื่อวิเคราะห์การขึ้นต่อกันทั้งหมด สาเหตุที่การวนซ้ำสามารถวิเคราะห์การขึ้นต่อกันทั้งหมดได้ก็คือความยาวของโมดูลจะเปลี่ยนไป การขึ้นต่อกันใหม่ modules.length จะเปลี่ยนไป
สำหรับ (ให้ i = 0; i < this.modules.length; i++) { รายการ const = this.modules [i]; const { ผู้อยู่ในอุปการะ } = รายการ; ถ้า (อยู่ในความอุปการะ) { สำหรับ (ให้ j อยู่ในความอุปการะ) { this.modules.push(this.parse(ผู้อยู่ในอุปการะ[j])); - - }
ขั้นตอนที่ 3: เขียนฟังก์ชัน WebpackBootstrap + สร้างไฟล์เอาต์พุต
เขียน ฟังก์ชัน WebpackBootstrap : สิ่งแรกที่เราต้องทำที่นี่คือฟังก์ชัน WebpackBootstrap หลังจากการคอมไพล์ การนำเข้าซอร์สโค้ดของเราจะถูกแยกวิเคราะห์เนื่องจากเบราว์เซอร์ ไม่รู้จัก need ดังนั้นเราต้องประกาศก่อน อย่างไรก็ตาม เมื่อเขียนฟังก์ชัน คุณต้องใส่ใจกับการแยกขอบเขตเพื่อป้องกันมลภาวะที่แปรผัน นอกจากนี้เรายังจำเป็นต้องประกาศการส่งออกในโค้ดของเราเพื่อให้แน่ใจว่ามีการส่งออกอยู่แล้วเมื่อมีการดำเนินการโค้ด
สร้างไฟล์เอาต์พุต : เราได้เขียนที่อยู่ของไฟล์ที่สร้างขึ้นในไฟล์กำหนดค่าแล้ว จากนั้นใช้ fs.writeFileSync เพื่อเขียนลงในโฟลเดอร์เอาต์พุต
ไฟล์ (รหัส) { const filePath = path.join (this.output.path, this.output.filename) const newCode = JSON.stringify (รหัส); // สร้างเนื้อหาไฟล์บันเดิล const Bundle = `(function(modules){ ฟังก์ชั่นต้องการ (โมดูล) { ฟังก์ชั่น pathRequire (relativePath) { ส่งคืนต้องการ (โมดูล [โมดูล] .ผู้พึ่งพา [relativePath]) - const ส่งออก={}; (ฟังก์ชั่น (ต้องการ, ส่งออก, รหัส) { ประเมินผล(รหัส) })(pathRequire,exports,modules[module].code); ส่งคืนการส่งออก - ต้องการ('${this.entry}') })(${รหัสใหม่})`; // WebpackBoostrap //สร้างไฟล์. วางไว้ในไดเร็กทอรี dist fs.writeFileSync(filePath,bundle,'utf-8') -
ขั้นตอนที่ 4: วิเคราะห์ลำดับการดำเนินการ
เราสามารถเรียกใช้ผลลัพธ์ที่จัดทำแพ็คเกจได้ในคอนโซลของเบราว์เซอร์ หากทำงานได้ตามปกติ ควรพิมพ์ hello Webpack
จากการข้างต้น เราควรมีความเข้าใจพื้นฐานเกี่ยวกับกระบวนการทั่วไปของ Webpack การใช้ AST เพื่อแยกวิเคราะห์โค้ดเป็นเพียงวิธีการสาธิตนี้ ไม่ใช่การใช้งานจริงของ Webpack มีวิธีแยกวิเคราะห์ AST ของตัวเอง ซึ่งก็คือ เปลี่ยนแปลงตลอดเวลา ระบบนิเวศของ Webpack สมบูรณ์มาก เด็ก ๆ ที่สนใจสามารถพิจารณาคำถามสามข้อต่อไปนี้: