การเข้าถึงคุกกี้ HTTP แบบไม่พร้อมกัน

Victor Costan

Cookie Store API คืออะไร

Cookie Store API จะแสดงคุกกี้ HTTP แก่ Service Worker และนำเสนอทางเลือกแบบไม่พร้อมกันสำหรับ document.cookie API นี้ช่วยให้คุณทำสิ่งต่อไปนี้ได้ง่ายขึ้น

  • หลีกเลี่ยงการกระตุกในเทรดหลักด้วยการใช้คุกกี้แบบไม่พร้อมกัน
  • หลีกเลี่ยงการโหวตสําหรับคุกกี้ เนื่องจากสามารถสังเกตการเปลี่ยนแปลงของคุกกี้ได้
  • เข้าถึงคุกกี้จาก Service Worker

อ่านคำอธิบาย

สถานะปัจจุบัน

ขั้นตอน สถานะ
1. สร้างคําอธิบาย เสร็จสมบูรณ์
2. สร้างฉบับร่างแรกของข้อกําหนด เสร็จสมบูรณ์
**3. รวบรวมความคิดเห็นและปรับปรุงข้อกำหนด** **กำลังดำเนินการ**
4. ช่วงทดลองใช้จากต้นทาง หยุดชั่วคราว
5. เปิดตัว ยังไม่เริ่ม

ฉันจะใช้ที่เก็บคุกกี้แบบแอซิงค์ได้อย่างไร

เปิดใช้ช่วงทดลองใช้จากต้นทาง

หากต้องการลองใช้ในเครื่อง คุณเปิดใช้ API ในบรรทัดคำสั่งได้

chrome --enable-blink-features=CookieStore

การส่ง Flag นี้ในบรรทัดคำสั่งจะเปิดใช้ API ทั่วโลกใน Chrome สําหรับเซสชันปัจจุบัน

หรือจะเปิดใช้ Flag #enable-experimental-web-platform-features ใน chrome://flags ก็ได้

คุณ (อาจ) ไม่ต้องใช้คุกกี้

ก่อนจะเจาะลึกเกี่ยวกับ API ใหม่ เราขอแจ้งให้ทราบว่าคุกกี้ยังคงเป็นรูปแบบการจัดเก็บข้อมูลฝั่งไคลเอ็นต์ที่เลวร้ายที่สุดของแพลตฟอร์มเว็บ และควรใช้เป็นทางเลือกสุดท้าย เรื่องนี้ไม่ได้เกิดขึ้นโดยบังเอิญ คุกกี้เป็นกลไกการจัดเก็บข้อมูลฝั่งไคลเอ็นต์แรกของเว็บ และเราได้เรียนรู้อะไรมากมายนับตั้งแต่นั้น

เหตุผลหลักในการหลีกเลี่ยงคุกกี้ ได้แก่

  • คุกกี้จะนำสคีมาพื้นที่เก็บข้อมูลไปไว้ใน Back-end API คำขอ HTTP แต่ละรายการจะมีสแนปชอตของโถคุกกี้ ซึ่งช่วยให้วิศวกรแบ็กเอนด์ของเราแนะนำทรัพยากร Dependency สำหรับรูปแบบคุกกี้ปัจจุบันได้โดยง่าย เมื่อเกิดกรณีนี้ขึ้น ฟรอนท์เอนด์ของคุณจะไม่สามารถเปลี่ยนสคีมาพื้นที่เก็บข้อมูล โดยไม่ได้ทำให้การเปลี่ยนแปลงที่ตรงกันกับแบ็กเอนด์ใช้งานได้

  • คุกกี้มีรูปแบบการรักษาความปลอดภัยที่ซับซ้อน ฟีเจอร์แพลตฟอร์มเว็บสมัยใหม่เป็นไปตามนโยบายต้นทางเดียวกัน ซึ่งหมายความว่าแอปพลิเคชันแต่ละรายการจะมีแซนด์บ็อกซ์ของตัวเอง และแยกจากแอปพลิเคชันอื่นๆ ที่ผู้ใช้อาจใช้งานอยู่โดยสิ้นเชิง ขอบเขตของคุกกี้ทำให้เรื่องความปลอดภัยมีความซับซ้อนมากขึ้นอย่างมาก และแค่การพยายามสรุปเรื่องดังกล่าวก็จะทำให้บทความนี้ยาวขึ้นเป็น 2 เท่า

  • คุกกี้มีต้นทุนด้านประสิทธิภาพสูง เบราว์เซอร์ต้องใส่สแนปชอตของคุกกี้ของคุณในคําขอ HTTP ทุกรายการ ดังนั้นการเปลี่ยนแปลงคุกกี้ทุกครั้งจะต้องนำไปใช้กับพื้นที่เก็บข้อมูลและกองซ้อนเครือข่าย เบราว์เซอร์สมัยใหม่มีการใช้งานที่เก็บคุกกี้ที่มีการเพิ่มประสิทธิภาพสูง แต่เราไม่สามารถทำให้คุกกี้มีประสิทธิภาพเท่ากับกลไกพื้นที่เก็บข้อมูลอื่น ซึ่งไม่จำเป็นต้องพูดคุยกับสแต็กเครือข่าย

ด้วยเหตุนี้ เว็บแอปพลิเคชันสมัยใหม่จึงควรหลีกเลี่ยงการใช้คุกกี้และเก็บตัวระบุเซสชันไว้ใน IndexedDB แทน และเพิ่มตัวระบุลงในส่วนหัวหรือเนื้อหาของคำขอ HTTP ที่เฉพาะเจาะจงอย่างชัดเจนผ่าน fetch API

อย่างไรก็ตาม คุณยังคงอ่านบทความนี้อยู่เนื่องจากคุณมีเหตุผลอันควรในการใช้คุกกี้

API document.cookie อันเลื่องชื่อเป็นสาเหตุที่ทำให้เกิดข้อบกพร่องในแอปพลิเคชันของคุณ ตัวอย่างเช่น เมื่อใดก็ตามที่คุณใช้ document.cookie getter เบราว์เซอร์จะต้องหยุดการเรียกใช้ JavaScript จนกว่าจะมีข้อมูลคุกกี้ที่คุณขอ ซึ่งอาจใช้การข้ามกระบวนการหรือการอ่านดิสก์ และจะทำให้ UI กระตุก

การแก้ปัญหาที่ตรงไปตรงมาคือการเปลี่ยนจาก document.cookie getter ไปใช้ Cookie Store API แบบแอซิงโครนัส

await cookieStore.get('session_id');

// {
//   domain: "example.com",
//   expires: 1593745721000,
//   name: "session_id",
//   path: "/",
//   sameSite: "unrestricted",
//   secure: true,
//   value: "yxlgco2xtqb.ly25tv3tkb8"
// }

คุณสามารถแทนที่ตัวตั้งค่า document.cookie ในลักษณะที่คล้ายกันได้ โปรดทราบว่าระบบจะรับประกันการเปลี่ยนแปลงหลังจากที่ Promise ที่ cookieStore.set แสดงผลได้รับการแก้ไขแล้วเท่านั้น

await cookieStore.set({name: 'opt_out', value: '1'});

// undefined

สังเกตการณ์ อย่าสำรวจ

แอปพลิเคชันยอดนิยมสำหรับการเข้าถึงคุกกี้จาก JavaScript คือการตรวจจับเมื่อผู้ใช้ออกจากระบบและอัปเดต UI ปัจจุบันนี้คุณทำได้โดยโพล document.cookie ซึ่งก่อให้เกิดการกระตุกและส่งผลต่อระยะเวลาการใช้งานแบตเตอรี่

Cookie Store API เป็นอีกทางเลือกหนึ่งในการสังเกตการณ์การเปลี่ยนแปลงของคุกกี้ที่ไม่ต้องใช้แบบสำรวจ

cookieStore.addEventListener('change', event => {
  for (const cookie of event.changed) {
    if (cookie.name === 'session_id') sessionCookieChanged(cookie.value);
  }
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') sessionCookieChanged(null);
  }
});

ยินดีต้อนรับ Service Worker

เนื่องจากการออกแบบแบบซิงค์ document.cookie API จึงยังไม่พร้อมใช้งานสำหรับ Service Worker Cookie Store API ทำงานไม่พร้อมกัน ระบบจึงอนุญาตให้ใช้ใน Service Worker

การโต้ตอบกับคุกกี้จะทํางานในบริบทเอกสารและใน Service Worker ในลักษณะเดียวกัน

// Works in documents and service workers.
async function logOut() {
  await cookieStore.delete('session_id');
}

อย่างไรก็ตาม การสังเกตการเปลี่ยนแปลงของคุกกี้จะแตกต่างออกไปเล็กน้อยใน Service Worker การตื่นตื่น Service Worker อาจใช้พลังงานมากพอสมควร เราจึงต้องอธิบายการเปลี่ยนแปลงคุกกี้ที่ Worker สนใจอย่างชัดเจน

ในตัวอย่างด้านล่าง แอปพลิเคชันที่ใช้ IndexedDB เพื่อแคชข้อมูลผู้ใช้จะตรวจสอบการเปลี่ยนแปลงคุกกี้เซสชัน และทิ้งข้อมูลที่แคชไว้เมื่อผู้ใช้ออกจากระบบ

// Specify the cookie changes we're interested in during the install event.
self.addEventListener('install', event => {
  event.waitUntil(cookieStore.subscribeToChanges([{name: 'session_id'}]));
});

// Delete cached data when the user logs out.
self.addEventListener('cookiechange', event => {
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') {
      indexedDB.deleteDatabase('user_cache');
      break;
    }
  }
});

แนวทางปฏิบัติแนะนำ

เร็วๆ นี้

ความคิดเห็น

หากลองใช้ API นี้ โปรดบอกเราว่าคุณคิดเห็นอย่างไร โปรดส่งความคิดเห็นเกี่ยวกับรูปร่าง API ไปยังที่เก็บข้อมูลจำเพาะและรายงานข้อบกพร่องการใช้งานไปยังคอมโพเนนต์ Blink ของ Blink>Storage>CookiesAPI

เราสนใจที่จะเรียนรู้เกี่ยวกับการวัดประสิทธิภาพและกรณีการใช้งาน ที่นอกเหนือจากที่ระบุไว้ในคำอธิบาย

แหล่งข้อมูลเพิ่มเติม