กลับไปที่บทความ
JavaScript Frontend React Web History

จาก jQuery ถึง React: วิวัฒนาการ 20 ปีของ Frontend

พลากร วรมงคล
30 กันยายน 2567 11 นาที

“เขียน JavaScript ตั้งแต่ 1999 jQuery รู้สึกเหมือนเวทมนตร์ React รู้สึกหลีกเลี่ยงไม่ได้ นี่คือเรื่องราวว่าเราจากการจัดการ DOM ไปยัง declarative UIs และเหตุใดอนาคตอาจไม่ใช่ React”

jQuery Era (2000-2012)

โปรเจกต์ web แรกที่แท้จริงของฉันคือฟอร์มที่มี client-side validation ในปี 1999 ฉันเขียน DOM manipulation ใน vanilla JavaScript—เจ็บปวดมาก ทุก browser ต้องการ workarounds IE 5 ไม่ support getElementById Netscape และ Internet Explorer มี event models ที่แตกต่างไปจากที่เดียว CSS float layouts ต้องการ careful management

จากนั้น jQuery มาถึงในปี 2006 และ web เปลี่ยนไปข้ามคืน

// Before jQuery: checking checkboxes
function toggleAll() {
  var checkboxes = document.getElementsByTagName('input');
  for (var i = 0; i < checkboxes.length; i++) {
    if (checkboxes[i].type === 'checkbox') {
      checkboxes[i].checked = !checkboxes[i].checked;
    }
  }
}

// jQuery made it this:
$('input[type=checkbox]').prop('checked', function() {
  return !this.checked;
});

ครั้งแรก JavaScript รู้สึกว่าประสิทธิผล API ที่ใช้งานได้ง่าย—บางครั้งสามวิธีที่จะทำสิ่งเดียวกัน มี “jQuery way” และทุกคนตามมา คุณเลือก elements chain methods และเวทมนตร์เกิด

Community สร้างสิ่งนี้ขึ้น: คุณเรียนรู้ jQuery plugins เชี่ยวชาญ CSS selectors และสามารถสร้าง animated interactive websites ได้เร็วกว่าที่เคย

ปัญหาที่ jQuery ไม่สามารถแก้ได้

แต่ jQuery มี fundamental limitation: มันไม่แยก data จาก presentation เมื่อคุณ toggle checkbox ด้วย jQuery คุณกำลัง mutating DOM directly นี่ใช้งานได้ดีสำหรับ interactions ที่ง่าย มันแตก scale

โดย 2012 single-page applications กลายเป็นที่มา Gmail Google Maps และ Facebook แสดงว่า rich web apps สามารถแข่งขันกับ native applications ได้ แต่การจัดการ state ทั่ว 10,000 lines ของ jQuery event handlers เป็น nightmare

ปัญหา: jQuery ทำให้มันง่ายเกินไปที่จะ couple UI กับ data checkbox appearance เก็บไว้ใน DOM list items เก็บเป็น DOM nodes เมื่อคุณต้องการ update พวกเขา คุณ re-render manually: find element change its class update its text นี่ duplicate business logic ของคุณทั่วสามตัวแทนต่างกัน (data DOM และ mental model)

Enter Angular (2010-2016)

Angular เป็น serious attempt แรกที่ fix นี้ ความคิด: templates bind directly ไปยัง data model เมื่อ data เปลี่ยน template update automatically เมื่อผู้ใช้ interact กับ template data model update two-way binding

// Angular 1: two-way binding magic
app.controller('CheckboxCtrl', function($scope) {
  $scope.items = [{checked: true}, {checked: false}];

  $scope.toggleAll = function() {
    $scope.items.forEach(function(item) {
      item.checked = !item.checked;
    });
  };
});

// The template:
// <input ng-repeat="item in items" ng-model="item.checked" />
// <button ng-click="toggleAll()">Toggle All</button>

นี่เป็นวิপ្លវ คุณไม่ต้องการ manipulate DOM manually anymore Angular digest cycle จะ figure มันออก รู้สึกว่าอัตโนมัติ

ปัญหา: digest cycle เป็น black box ถ้าบางสิ่ง ไม่ update คุณต้อง debug Angular framework เอง Performance ยาก predict two-way binding ดูยอดเยี่ยมจนกว่าคุณมี 500 form fields fight ว่า update อะไร

React และ Paradigm Shift (2013-Present)

React innovation เป็นง่าย: ลืมเกี่ยวกับ updating ทิ้ง UI และสร้างมันตั้งแต่เริ่มต้นใหม่ทุกครั้งอะไรก็ change

นี้ดูแปลก—rebuild entire DOM ทุกครั้ง state เปลี่ยน? แต่ React key insight ถูก virtual DOM คุณไม่ต้องจริงๆ touch browser DOM คุณ render ไปยัง in-memory representation diff มันกับว่า previously rendered และ apply เพียง minimal changes ไปยัง real DOM

// React: declarative, unidirectional
function CheckboxList() {
  const [items, setItems] = useState([
    {id: 1, checked: true},
    {id: 2, checked: false},
  ]);

  const toggleAll = () => {
    setItems(items.map(item => ({
      ...item,
      checked: !item.checked
    })));
  };

  return (
    <>
      {items.map(item => (
        <input
          key={item.id}
          type="checkbox"
          checked={item.checked}
        />
      ))}
      <button onClick={toggleAll}>Toggle All</button>
    </>
  );
}

Elegance: component ของคุณเป็น pure function ของ state นั่น ให้ state เดียวกัน มันเสมอ render output เดียวกัน ไม่มี black-box framework magic data flow explicit และ unidirectional: user action → state change → re-render

นี่ทำให้ reasoning เกี่ยวกับ code dramatically ง่ายขึ้น ไม่มี hunting through event handlers พยายาม figure ว่า state changes propagated ยังไง entire flow อยู่ right there ใน component

Web Components Episode (2015-2020)

ตรงกลาง React rise web platform พยายาม solve นี้ native ด้วย Web Components Custom elements shadow DOM และ HTML templates built into browser

ทฤษฎีเป็นสมบูรณ์: คุณไม่ต้อง React anymore browser จะให้คุณ componentization ฟรี

แต่ Web Components มี limitations shadow DOM break styling custom elements ไม่ integrate ดี ด้วย existing form APIs ecosystem fragmented React integrated ดีกว่า ด้วย JavaScript tooling ที่แล้วเป็น dominant

ที่ไหนตอนนี้ (2024)

วันนี้ React dominates ไม่ใช่เพราะมันสมบูรณ์ แต่เพราะ:

  1. มันทำให้ component composition natural
  2. JSX syntax genuinely ดีกว่า templates
  3. Unidirectional data flow prevent entire classes bugs
  4. Ecosystem stable

แต่มี cracks React heavy (ประมาณ 150kb) Server-side rendering complex mental model breaks down สำหรับ streaming และ incremental updates

New frameworks เกิดขึ้น—Solid Vue Svelte—ที่ take React insights และ simplify พวกเขา generate JavaScript น้อยกว่า พวกเขา handle reactivity ต่างกัน รู้สึก lighter

What Comes Next

ฉันสงสัยว่า อนาคตไม่ใช่ single framework ฉันคิดว่ามัน:

  • Islands architecture: mostly static HTML ด้วย JavaScript sprinkled ใน
  • Signals แทน virtual DOM: fine-grained reactivity ที่ เพียง updated อะไร changed
  • Better platform integration: browsers finally learning จาก React สิ่งที่ developers ต้องการ
  • Less JavaScript: modern networks และ CPUs เร็วพอ ที่ shipping less code beats shipping faster code

แต่ core insight ยังอยู่ที่นี่: code ควร declare UI ดูเหมือนไร given บ้าง state ไม่ imperative instructions วิธี change มัน นั่นไม่ใช่ React-specific นั่นคือ future web

ยี่สิบปีที่แล้ว jQuery ทำให้ web ได้ React ทำให้มันสมเหตุสมผล Whatever comes next จะสร้างบน both

Comments powered by Giscus are not yet configured. Set PUBLIC_GISCUS_REPO_ID and PUBLIC_GISCUS_CATEGORY_ID in apps/web/.env to enable.

PV

เขียนโดย พลากร วรมงคล

Software Engineer Specialist ประสบการณ์กว่า 20 ปี เขียนเกี่ยวกับ Architecture, Performance และการสร้างระบบ Production

เพิ่มเติมเกี่ยวกับผม

บทความที่เกี่ยวข้อง