การเขย่าต้นไม้: คู่มืออ้างอิง
เผยแพร่แล้ว: 2022-03-10ก่อนเริ่มต้นการเดินทางเพื่อเรียนรู้ว่าการเขย่าต้นไม้คืออะไรและจะตั้งค่าตัวเราให้ประสบความสำเร็จได้อย่างไร เราต้องเข้าใจว่าโมดูลใดบ้างในระบบนิเวศ JavaScript
ตั้งแต่เริ่มแรก โปรแกรม JavaScript ได้เติบโตขึ้นในความซับซ้อนและจำนวนงานที่ดำเนินการ ความจำเป็นในการแบ่งงานดังกล่าวออกเป็นขอบเขตของการดำเนินการแบบปิดนั้นชัดเจน ส่วนงานหรือค่าเหล่านี้เป็นสิ่งที่เราเรียกว่า โมดูล จุดประสงค์หลักคือเพื่อป้องกันการทำซ้ำและเพื่อใช้ประโยชน์จากการนำกลับมาใช้ใหม่ ดังนั้น สถาปัตยกรรมจึงถูกคิดค้นขึ้นเพื่อให้มีขอบเขตชนิดพิเศษดังกล่าว เพื่อแสดงค่านิยมและงาน และใช้ค่านิยมและงานภายนอก
หากต้องการเจาะลึกลงไปว่าโมดูลคืออะไรและทำงานอย่างไร ฉันขอแนะนำ "ES Modules: A Cartoon Deep-Dive" แต่เพื่อให้เข้าใจถึงความแตกต่างของการเขย่าต้นไม้และการใช้โมดูล คำจำกัดความข้างต้นน่าจะเพียงพอแล้ว
การเขย่าต้นไม้หมายความว่าอย่างไร?
พูดง่ายๆ ก็คือ การเขย่าต้นไม้หมายถึงการลบโค้ดที่ไม่สามารถเข้าถึงได้ (หรือที่เรียกว่าโค้ดที่ไม่ทำงาน) ออกจากบันเดิล ตามที่เอกสารของ Webpack เวอร์ชัน 3 ระบุไว้:
“คุณสามารถจินตนาการถึงใบสมัครของคุณเป็นต้นไม้ได้ ซอร์สโค้ดและไลบรารีที่คุณใช้จริงแสดงถึงใบไม้สีเขียวที่มีชีวิตของต้นไม้ รหัสที่ตายแล้วหมายถึงใบสีน้ำตาลที่ตายแล้วของต้นไม้ที่กินหมดในฤดูใบไม้ร่วง เพื่อกำจัดใบไม้ที่ตายแล้ว คุณต้องเขย่าต้นไม้ให้มันตกลงมา”
คำนี้ได้รับความนิยมครั้งแรกในชุมชนส่วนหน้าโดยทีม Rollup แต่ผู้เขียนภาษาไดนามิกทั้งหมดกำลังดิ้นรนกับปัญหาตั้งแต่ก่อนหน้านี้มาก แนวคิดของอัลกอริธึมเขย่าต้นไม้สามารถสืบย้อนไปถึงช่วงต้นทศวรรษ 1990 เป็นอย่างน้อย
ในพื้นที่ JavaScript การสั่นต้นไม้เกิดขึ้นได้ตั้งแต่ข้อกำหนดโมดูล ECMAScript (ESM) ใน ES2015 ซึ่งก่อนหน้านี้รู้จักกันในชื่อ ES6 ตั้งแต่นั้นมา การสั่นต้นไม้ถูกเปิดใช้งานโดยค่าเริ่มต้นในบันเดิลส่วนใหญ่ เนื่องจากมันลดขนาดเอาต์พุตโดยไม่เปลี่ยนพฤติกรรมของโปรแกรม
สาเหตุหลักคือ ESM เป็นแบบคงที่โดยธรรมชาติ ลองแยกแยะว่าหมายถึงอะไร
โมดูล ES กับ CommonJS
CommonJS เกิดขึ้นก่อนข้อกำหนด ESM ในอีกไม่กี่ปี มันมาเพื่อแก้ไขปัญหาการขาดการสนับสนุนโมดูลที่ใช้ซ้ำได้ในระบบนิเวศ JavaScript CommonJS มีฟังก์ชัน require()
ที่ดึงโมดูลภายนอกตามพาธที่ให้มา และเพิ่มไปยังขอบเขตระหว่างรันไทม์
ที่ require
นั้นเป็น function
ที่เหมือนกับโปรแกรมอื่น ๆ ซึ่งทำให้ยากพอที่จะประเมินผลการโทรในเวลาคอมไพล์ ยิ่งไปกว่านั้น การเพิ่ม require
call ที่ใดก็ได้ในโค้ดนั้นสามารถทำได้ — รวมอยู่ในการเรียกใช้ฟังก์ชันอื่น ภายในคำสั่ง if/else ในคำสั่ง switch เป็นต้น
ด้วยการเรียนรู้และการดิ้นรนที่เกิดจากการนำสถาปัตยกรรม CommonJS มาใช้อย่างกว้างขวาง ข้อกำหนด ESM ได้ตกลงบนสถาปัตยกรรมใหม่นี้ ซึ่งโมดูลจะถูกนำเข้าและส่งออกโดย import
และ export
คำหลักที่เกี่ยวข้อง ดังนั้นจึงไม่มีการเรียกใช้งานอีกต่อไป ESM ยังได้รับอนุญาตเฉพาะเป็นการประกาศระดับบนสุดเท่านั้น การซ้อนรายการเหล่านี้ในโครงสร้างอื่นเป็นไปไม่ได้ เนื่องจากเป็น แบบคงที่ ESM ไม่ได้ขึ้นอยู่กับการดำเนินการรันไทม์
ขอบเขตและผลข้างเคียง
อย่างไรก็ตาม มีอุปสรรคอีกประการหนึ่งที่การเขย่าต้นไม้ต้องเอาชนะเพื่อหลีกเลี่ยงการบวม นั่นคือผลข้างเคียง ฟังก์ชันถือว่ามีผลข้างเคียงเมื่อเปลี่ยนแปลงหรืออาศัยปัจจัยภายนอกขอบเขตของการดำเนินการ ฟังก์ชันที่มีผลข้างเคียงถือว่า ไม่บริสุทธิ์ ฟังก์ชันบริสุทธิ์จะให้ผลลัพธ์เหมือนเดิมเสมอ โดยไม่คำนึงถึงบริบทหรือสภาพแวดล้อมที่มีการเรียกใช้
const pure = (a:number, b:number) => a + b const impure = (c:number) => window.foo.number + c
Bundlers ตอบสนองวัตถุประสงค์ของพวกเขาโดยการประเมินรหัสที่ให้มามากที่สุดเท่าที่เป็นไปได้เพื่อตรวจสอบว่าโมดูลบริสุทธิ์หรือไม่ แต่การประเมินโค้ดระหว่างเวลาคอมไพล์หรือเวลาในการรวมกลุ่มสามารถทำได้เพียงเท่านี้ ดังนั้น จึงสันนิษฐานว่าไม่สามารถกำจัดบรรจุภัณฑ์ที่มีผลข้างเคียงได้อย่างถูกต้อง แม้ว่าจะเข้าถึงไม่ได้ก็ตาม
ด้วยเหตุนี้ ผู้รวมกลุ่มจึงยอมรับคีย์ภายในไฟล์ package.json
ของโมดูล ซึ่งช่วยให้นักพัฒนาสามารถประกาศว่าโมดูลไม่มีผลข้างเคียงหรือไม่ ด้วยวิธีนี้ ผู้พัฒนาสามารถเลือกไม่รับการประเมินโค้ดและบอกใบ้ถึงผู้รวมกลุ่ม รหัสภายในแพ็คเกจใดแพ็คเกจหนึ่งสามารถถูกกำจัดได้หากไม่มีการนำเข้าที่เข้าถึงได้หรือ require
คำสั่งเชื่อมโยงไปยังมัน ซึ่งไม่เพียงแต่ทำให้เป็นชุดที่บางกว่าเท่านั้น แต่ยังสามารถเร่งเวลาในการคอมไพล์ได้อีกด้วย
{ "name": "my-package", "sideEffects": false }
ดังนั้น หากคุณเป็นผู้พัฒนาแพ็คเกจ ให้ใช้ sideEffects
ก่อนที่จะเผยแพร่ และแน่นอน ให้แก้ไขทุกครั้งที่เผยแพร่เพื่อหลีกเลี่ยงการเปลี่ยนแปลงที่ไม่คาดคิด
นอกเหนือจากคีย์ root sideEffects
แล้ว ยังสามารถกำหนดความบริสุทธิ์แบบไฟล์ต่อไฟล์ได้ด้วยการใส่คำอธิบายประกอบความคิดเห็นแบบอินไลน์ /*@__PURE__*/
ในการเรียกเมธอดของคุณ
const x = */@__PURE__*/eliminated_if_not_called()
ฉันถือว่าคำอธิบายประกอบแบบอินไลน์นี้เป็นช่องทางหลบหนีสำหรับนักพัฒนาสำหรับผู้บริโภค ซึ่งต้องทำในกรณีที่แพ็คเกจไม่ได้ประกาศผล sideEffects: false
หรือในกรณีที่ไลบรารีแสดงผลข้างเคียงต่อวิธีการเฉพาะ
การเพิ่มประสิทธิภาพ Webpack
ตั้งแต่เวอร์ชัน 4 เป็นต้นไป Webpack จำเป็นต้องมีการกำหนดค่าที่น้อยลงเรื่อยๆ เพื่อให้ได้แนวทางปฏิบัติที่ดีที่สุด ฟังก์ชันการทำงานสำหรับปลั๊กอินสองสามตัวได้ถูกรวมเข้ากับแกนหลักแล้ว และเนื่องจากทีมพัฒนาให้ความสำคัญกับขนาดมัดอย่างมาก พวกเขาจึงทำให้การเขย่าต้นไม้เป็นเรื่องง่าย
หากคุณไม่ได้เป็นคนจรจัดมากหรือหากแอปพลิเคชันของคุณไม่มีกรณีพิเศษ การสั่นไหวของโครงสร้างการพึ่งพาของคุณก็เป็นเรื่องของบรรทัดเดียว
ไฟล์ webpack.config.js
มีคุณสมบัติรูทชื่อ mode
เมื่อใดก็ตามที่มูลค่าของคุณสมบัตินี้คือ production
มันจะสั่นคลอนและปรับโมดูลของคุณให้เหมาะสมอย่างเต็มที่ นอกจากการกำจัดโค้ดที่ไม่ทำงานด้วย TerserPlugin
แล้ว mode: 'production'
จะเปิดใช้งานชื่อ mangled ที่กำหนดไว้สำหรับโมดูลและส่วนต่างๆ และจะเปิดใช้งานปลั๊กอินต่อไปนี้:
- การใช้การพึ่งพาแฟล็ก
- ธงรวมชิ้น
- การต่อโมดูล
- ไม่มีการปล่อยข้อผิดพลาด
ไม่ใช่โดยบังเอิญที่ค่าทริกเกอร์คือ production
คุณจะไม่ต้องการให้การพึ่งพาของคุณได้รับการปรับให้เหมาะสมอย่างสมบูรณ์ในสภาพแวดล้อมการพัฒนาเพราะจะทำให้ปัญหายากขึ้นมากในการดีบัก ดังนั้นผมขอแนะนำว่าควรดำเนินการด้วยวิธีใดวิธีหนึ่งจากสองวิธี
ในอีกด้านหนึ่ง คุณสามารถส่งแฟล็ก mode
ไปยังอินเตอร์เฟสบรรทัดรับคำสั่ง Webpack:
# This will override the setting in your webpack.config.js webpack --mode=production
หรือ คุณสามารถใช้ตัวแปร process.env.NODE_ENV
ใน webpack.config.js
:
mode: process.env.NODE_ENV === 'production' ? 'production' : development
ในกรณีนี้ คุณต้องไม่ลืมส่ง --NODE_ENV=production
ในไปป์ไลน์การปรับใช้ของคุณ
ทั้งสองวิธีเป็นนามธรรมที่อยู่ด้านบนของ definePlugin
ที่รู้จักกันมากจาก Webpack เวอร์ชัน 3 และต่ำกว่า ตัวเลือกใดที่คุณเลือกไม่ได้สร้างความแตกต่างอย่างแน่นอน
Webpack เวอร์ชัน 3 และต่ำกว่า
เป็นเรื่องที่ควรค่าแก่การกล่าวขวัญว่าสถานการณ์จำลองและตัวอย่างในส่วนนี้อาจใช้ไม่ได้กับ Webpack เวอร์ชันล่าสุดและบันเดิลอื่นๆ ส่วนนี้พิจารณาการใช้งาน UglifyJS เวอร์ชัน 2 แทน Terser UglifyJS เป็นแพ็คเกจที่ Terser ถูกแยกออกมา ดังนั้นการประเมินรหัสอาจแตกต่างกันระหว่างพวกเขา
เนื่องจาก Webpack เวอร์ชัน 3 และต่ำกว่าไม่รองรับคุณสมบัติ sideEffects
ใน package.json
แพ็คเกจทั้งหมดจะต้องได้รับการประเมินอย่างสมบูรณ์ก่อนที่โค้ดจะถูกกำจัด เพียงอย่างเดียวทำให้วิธีการนี้มีประสิทธิภาพน้อยลง แต่ต้องคำนึงถึงคำเตือนหลายประการเช่นกัน
ดังที่กล่าวไว้ข้างต้น คอมไพเลอร์ไม่มีทางค้นพบด้วยตัวเองเมื่อแพ็คเกจกำลังยุ่งเกี่ยวกับขอบเขตส่วนกลาง แต่นั่นไม่ใช่สถานการณ์เดียวที่จะข้ามการสั่นของต้นไม้ได้ มีสถานการณ์คลุมเครือ
ใช้ตัวอย่างแพ็คเกจนี้จากเอกสารของ Webpack:
// transform.js import * as mylib from 'mylib'; export const someVar = mylib.transform({ // ... }); export const someOtherVar = mylib.transform({ // ... });
และนี่คือจุดเริ่มต้นของกลุ่มผู้บริโภค:
// index.js import { someVar } from './transforms.js'; // Use `someVar`...
ไม่มีทางระบุได้ว่า mylib.transform
กระตุ้นผลข้างเคียงหรือไม่ ดังนั้นจะไม่มีการลบรหัสใดๆ
ต่อไปนี้คือสถานการณ์อื่นๆ ที่มีผลลัพธ์ที่คล้ายคลึงกัน:
- เรียกใช้ฟังก์ชันจากโมดูลบุคคลที่สามที่คอมไพเลอร์ไม่สามารถตรวจสอบได้
- ฟังก์ชันการส่งออกซ้ำที่นำเข้าจากโมดูลของบุคคลที่สาม
เครื่องมือที่อาจช่วยให้คอมไพเลอร์ทำงานแบบ tree-shaking ได้คือ babel-plugin-transform-imports จะแยกสมาชิกทั้งหมดและการส่งออกที่มีชื่อออกเป็นการส่งออกเริ่มต้น ทำให้โมดูลสามารถประเมินเป็นรายบุคคลได้
// before transformation import { Row, Grid as MyGrid } from 'react-bootstrap'; import { merge } from 'lodash'; // after transformation import Row from 'react-bootstrap/lib/Row'; import MyGrid from 'react-bootstrap/lib/Grid'; import merge from 'lodash/merge';
นอกจากนี้ยังมีคุณสมบัติการกำหนดค่าที่เตือนนักพัฒนาเพื่อหลีกเลี่ยงคำสั่งนำเข้าที่ลำบาก หากคุณใช้ Webpack เวอร์ชัน 3 ขึ้นไป และคุณได้ทำ Due Diligence ด้วยการกำหนดค่าพื้นฐานและเพิ่มปลั๊กอินที่แนะนำแล้ว แต่บันเดิลของคุณยังดูบวมๆ อยู่ เราขอแนะนำให้คุณลองใช้แพ็กเกจนี้ดู
ขอบเขตการยกและรวบรวมครั้ง
ในช่วงเวลาของ CommonJS บันเดิลส่วนใหญ่จะห่อแต่ละโมดูลภายในการประกาศฟังก์ชันอื่นและแมปไว้ในอ็อบเจ็กต์ นั่นไม่แตกต่างจากวัตถุแผนที่ใด ๆ ที่นั่น:
(function (modulesMap, entry) { // provided CommonJS runtime })({ "index.js": function (require, module, exports) { let { foo } = require('./foo.js') foo.doStuff() }, "foo.js": function(require, module, exports) { module.exports.foo = { doStuff: () => { console.log('I am foo') } } } }, "index.js")
นอกเหนือจากการวิเคราะห์แบบสแตติกที่ยากแล้ว สิ่งนี้ยังเข้ากันไม่ได้กับ ESM โดยพื้นฐานแล้ว เนื่องจากเราพบว่าเราไม่สามารถห่อคำสั่ง import
และ export
ได้ ดังนั้น ทุกวันนี้ Bundlers ยกทุกโมดูลขึ้นสู่ระดับบนสุด:
// moduleA.js let $moduleA$export$doStuff = () => ({ doStuff: () => {} }) // index.js $moduleA$export$doStuff()
แนวทางนี้เข้ากันได้กับ ESM อย่างสมบูรณ์ นอกจากนี้ยังช่วยให้การประเมินโค้ดสามารถระบุโมดูลที่ไม่ได้ถูกเรียกและวางได้อย่างง่ายดาย คำเตือนของแนวทางนี้คือ ระหว่างการคอมไพล์ มันต้องใช้เวลามากกว่านั้นมาก เพราะมันกระทบกับทุกคำสั่งและเก็บบันเดิลไว้ในหน่วยความจำระหว่างกระบวนการ นั่นเป็นเหตุผลใหญ่ที่ว่าทำไมประสิทธิภาพของการรวมกลุ่มจึงกลายเป็นเรื่องที่น่ากังวลมากขึ้นสำหรับทุกคน และเหตุใดภาษาที่คอมไพล์แล้วจึงถูกนำไปใช้ประโยชน์ในเครื่องมือสำหรับการพัฒนาเว็บ ตัวอย่างเช่น esbuild เป็นบันเดิลที่เขียนใน Go และ SWC เป็นคอมไพเลอร์ TypeScript ที่เขียนด้วย Rust ซึ่งรวมเข้ากับ Spark ซึ่งเป็นบันเดิลที่เขียนด้วย Rust ด้วย
เพื่อให้เข้าใจการยกขอบเขตได้ดีขึ้น ฉันขอแนะนำเอกสารประกอบของ Parcel เวอร์ชัน 2 เป็นอย่างยิ่ง
หลีกเลี่ยงการคลอดก่อนกำหนด
มีปัญหาเฉพาะเรื่องหนึ่งที่น่าเสียดายค่อนข้างบ่อยและอาจทำลายล้างจากการสั่นของต้นไม้ได้ กล่าวโดยย่อ จะเกิดขึ้นเมื่อคุณทำงานกับตัวโหลดพิเศษ โดยผสานรวมคอมไพเลอร์ต่างๆ เข้ากับบันเดิลของคุณ ชุดค่าผสมทั่วไปคือ TypeScript, Babel และ Webpack — ในการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมด
ทั้ง Babel และ TypeScript มีคอมไพเลอร์ของตัวเอง และตัวโหลดที่เกี่ยวข้องก็อนุญาตให้นักพัฒนาใช้งานได้ เพื่อการผสานรวมที่ง่ายดาย และภัยคุกคามที่ซ่อนอยู่ในนั้น
คอมไพเลอร์เหล่านี้เข้าถึงโค้ดของคุณ ก่อน การเพิ่มประสิทธิภาพโค้ด และไม่ว่าจะโดยค่าเริ่มต้นหรือการกำหนดค่าผิดพลาด คอมไพเลอร์เหล่านี้มักจะส่งออกโมดูล CommonJS แทนที่จะเป็น ESM ตามที่กล่าวไว้ในส่วนก่อนหน้านี้ โมดูล CommonJS เป็นไดนามิก ดังนั้นจึงไม่สามารถประเมินได้อย่างเหมาะสมสำหรับการกำจัด dead-code
สถานการณ์นี้กลายเป็นเรื่องธรรมดามากขึ้นในปัจจุบัน ด้วยการเติบโตของแอป "isomorphic" (เช่น แอปที่เรียกใช้โค้ดเดียวกันทั้งฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์) เนื่องจาก Node.js ยังไม่มีการสนับสนุนมาตรฐานสำหรับ ESM เมื่อคอมไพเลอร์กำหนดเป้าหมายไปยังสภาพแวดล้อมของ node
คอมไพเลอร์จะส่งออก CommonJS
ดังนั้น อย่าลืม ตรวจสอบโค้ดที่อัลกอริทึมการเพิ่มประสิทธิภาพของคุณได้รับ
รายการตรวจสอบการเขย่าต้นไม้
เมื่อคุณทราบรายละเอียดเกี่ยวกับวิธีการรวมกลุ่มและการเขย่าต้นไม้แล้ว เรามาวาดรายการตรวจสอบที่คุณสามารถพิมพ์เองได้ในที่ที่สะดวกเมื่อคุณกลับมายังการใช้งานปัจจุบันและฐานโค้ด หวังว่านี่จะช่วยคุณประหยัดเวลาและช่วยให้คุณปรับให้เหมาะสมไม่เพียงแค่ประสิทธิภาพที่รับรู้ของโค้ดของคุณเท่านั้น แต่ยังอาจถึงเวลาสร้างไปป์ไลน์ของคุณอีกด้วย!
- ใช้ ESM และไม่เพียงแต่ในฐานโค้ดของคุณเองเท่านั้น แต่ยังสนับสนุนแพ็คเกจที่ส่งออก ESM เป็นวัสดุสิ้นเปลืองด้วย
- ตรวจสอบให้แน่ใจว่าคุณรู้ว่าการอ้างอิงใด (ถ้ามี) ของคุณไม่ได้ประกาศ
sideEffects
หรือตั้งค่าให้เป็นtrue
- ใช้คำอธิบายประกอบแบบอินไลน์เพื่อประกาศการเรียกใช้เมธอดที่ บริสุทธิ์ เมื่อใช้แพ็กเกจที่มีผลข้างเคียง
- หากคุณกำลังส่งออกโมดูล CommonJS ตรวจสอบให้แน่ใจว่าได้เพิ่มประสิทธิภาพบันเดิลของคุณ ก่อนที่จะ แปลงคำสั่งนำเข้าและส่งออก
การเขียนแพ็คเกจ
หวังว่า ณ จุดนี้เราทุกคนเห็นพ้องกันว่า ESM เป็นหนทางข้างหน้าในระบบนิเวศ JavaScript เช่นเคยในการพัฒนาซอฟต์แวร์ แม้ว่าทรานสิชั่นอาจทำได้ยาก โชคดีที่ผู้เขียนแพ็คเกจสามารถใช้มาตรการที่ไม่หยุดชะงักเพื่ออำนวยความสะดวกในการโยกย้ายที่รวดเร็วและราบรื่นสำหรับผู้ใช้ของพวกเขา
ด้วยส่วนเสริมเล็กๆ น้อยๆ ใน package.json
แพ็คเกจของคุณจะสามารถบอกสภาพแวดล้อมที่แพ็คเกจรองรับแก่ผู้รวมกลุ่มได้และวิธีที่พวกเขารองรับได้ดีที่สุด นี่คือรายการตรวจสอบจาก Skypack:
- รวมการส่งออก ESM
- เพิ่ม
"type": "module"
- ระบุจุดเริ่มต้นผ่าน
"module": "./path/entry.js"
(แบบแผนของชุมชน)
และนี่คือตัวอย่างที่เกิดขึ้นเมื่อปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดทั้งหมด และคุณต้องการสนับสนุนทั้งสภาพแวดล้อมของเว็บและ Node.js:
{ // ... "main": "./index-cjs.js", "module": "./index-esm.js", "exports": { "require": "./index-cjs.js", "import": "./index-esm.js" } // ... }
นอกจากนี้ ทีมงาน Skypack ยังได้แนะนำ คะแนนคุณภาพแพ็คเกจ เป็นเกณฑ์มาตรฐานเพื่อพิจารณาว่าแพ็คเกจที่กำหนดได้รับการตั้งค่าสำหรับการมีอายุยืนยาวและแนวปฏิบัติที่ดีที่สุดหรือไม่ เครื่องมือนี้เป็นโอเพ่นซอร์สบน GitHub และสามารถเพิ่มเป็น devDependency
ให้กับแพ็คเกจของคุณเพื่อดำเนินการตรวจสอบอย่างง่ายดายก่อนเผยแพร่แต่ละครั้ง
ห่อ
ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับคุณ หากเป็นเช่นนั้น ให้พิจารณาแบ่งปันกับเครือข่ายของคุณ ฉันหวังว่าจะได้โต้ตอบกับคุณในความคิดเห็นหรือบน Twitter
แหล่งข้อมูลที่เป็นประโยชน์
บทความและเอกสารประกอบ
- “ES Modules: A Cartoon Deep-Dive”, ลิน คลาร์ก, Mozilla Hacks
- “ต้นไม้สั่น”, Webpack
- “การกำหนดค่า”, Webpack
- “การเพิ่มประสิทธิภาพ”, Webpack
- “Scope Hoisting” เอกสารของ Parcel version 2
โครงการและเครื่องมือ
- Terser
- babel-plugin-transform-imports
- Skypack
- เว็บแพ็ค
- พัสดุ
- ม้วน
- esbuild
- SWC
- ตรวจสอบแพ็คเกจ