4 điểm bởi GN⁺ 2024-03-26 | 1 bình luận | Chia sẻ qua WhatsApp
  • Jampack là một công cụ hậu xử lý nhận đầu ra của Static Site Generator để tối ưu hóa trải nghiệm người dùng và điểm số Core Web Vitals, chứ không phải bundler hay framework
  • Tự động chuyển <img><picture> trong HTML thành ảnh responsive, đồng thời thêm các định dạng như WebP·AVIF, srcset, sizes, width, height, loading="lazy", decoding="async"...
  • Ảnh CDN có thể được xử lý responsive bằng srcset dựa trên tham số URL, còn ảnh bên ngoài có thể được tải xuống dưới _jampack để chuyển thành ảnh cục bộ đã tối ưu hóa
  • Tài nguyên above-the-fold được xử lý với mức ưu tiên cao, ảnh nhỏ được inline vào HTML, còn ảnh và iframe below-the-fold thì được lazy load
  • Áp dụng bằng cách chạy npx @divriots/jampack ./dist trên thư mục kết quả build của site tĩnh, và thực hiện nén CSS·JS·HTML·SVG·ảnh ở pass thứ hai

Vai trò của Jampack

  • Jampack nhận đầu ra do Static Site Generator, tức SSG, tạo ra làm đầu vào và tối ưu hóa website tĩnh
  • Mục tiêu là cải thiện trải nghiệm người dùng và điểm số Core Web Vitals
  • README phân biệt Jampack là “không phải bundler cũng không phải framework”
  • Bài giới thiệu có tại Read the introduction blog post

Tối ưu hóa hình ảnh

  • <img> thông thường sẽ được chuyển thành ảnh responsive
    • Tạo file WebP cho src gốc và thêm srcset
    • Thêm các thuộc tính như sizes="100vw", loading="lazy", decoding="async", width, height
  • Phần tử <picture> được chuyển thành cấu trúc responsive bao gồm nhiều định dạng ảnh
    • Thêm <source type="image/avif"> cho AVIF
    • Thêm <source type="image/webp"> cho WebP
    • <img> gốc cũng có srcset, sizes, loading, decoding, width, height
  • Tính năng tối ưu hóa ảnh được dẫn tiếp tới tài liệu optimize-images, nhưng liên kết tương ứng trong README là đường dẫn tương đối

Xử lý ảnh CDN và ảnh bên ngoài

  • Ảnh CDN có thể giữ nguyên URL từ xa nhưng vẫn thêm srcset responsive
    • Ví dụ tạo nhiều ứng viên theo độ rộng bằng cách gắn các tham số w, fit=min, auto=format vào URL ảnh Unsplash
    • Ảnh gốc cũng được thêm loading="lazy", decoding="async", sizes="100vw"
  • Ảnh bên ngoài có thể được tải xuống rồi chuyển thành file cục bộ đã tối ưu hóa
    • Ví dụ chuyển ảnh Unsplash bên ngoài thành đường dẫn như _jampack/ab99b9d280ce4cf7cfc810b59f3a7739.jpg.webp
    • Ảnh đã chuyển đổi bao gồm width, height, srcset, sizes, loading, decoding

Above-the-fold và tối ưu hóa CSS·liên kết

  • Jampack tối ưu riêng các tài nguyên above-the-fold
    • Ảnh được tải với mức ưu tiên cao hơn
    • Ảnh nhỏ được nhúng vào HTML
  • Tài nguyên below-the-fold được lazy load
    • Ảnh và iframe là đối tượng áp dụng lazy load
  • Critical CSS được inline vào HTML
    • Mục đích là tránh FOUC có thể xảy ra trong lúc tải và parse stylesheet
    • Phần CSS còn lại sẽ được lazy load
  • Prefetch liên kết là tính năng để tăng tốc cho lần chuyển trang tiếp theo
    • Có thể xử lý động khi liên kết đi vào viewport bằng quicklink

Nén tài nguyên và cách chạy

  • Jampack nén mọi tài nguyên chưa bị đụng tới trong pass thứ hai, đồng thời giữ nguyên tên và định dạng
  • Các công cụ nén theo phần mở rộng gồm:
  • Khi website tĩnh nằm trong thư mục dist, chạy bằng lệnh sau
npx @divriots/jampack ./dist

Trường hợp sử dụng và ý nghĩa tên gọi

1 bình luận

 
GN⁺ 2024-03-26
Các ý kiến trên Hacker News
  • Đúng là công cụ tôi đang tìm. Trước đây tôi tự viết script dựa trên Sharp để làm kiểu tối ưu hóa hình ảnh này, nhưng Jampack thay thế hoàn toàn việc đó và hoạt động tốt hơn nhiều
    Sau khi build site tĩnh Quarto rồi chạy Jampack, kích thước thư mục giảm 32%, và hiện chưa thấy nhược điểm đáng chú ý nào
    Theo PageSpeed Insights, trước Jampack thì trên mobile: hiệu năng 52, khả năng truy cập 73, best practices 100, SEO 85; còn desktop: hiệu năng 90, khả năng truy cập 75, best practices 100, SEO 82
    Sau khi áp dụng, kết quả là mobile: hiệu năng 49, khả năng truy cập 80, best practices 100, SEO 92; desktop: hiệu năng 85, khả năng truy cập 82, best practices 100, SEO 91

    • Điểm Lighthouse và PageSpeed Insights có thể dao động. Khi so sánh hiệu năng kiểu này, tốt hơn nên chạy nhiều lần rồi xem giá trị trung vị
      Cũng có tài liệu nói rằng “trung vị điểm Lighthouse của 5 lần chạy ổn định gấp đôi so với 1 lần chạy”: https://developers.google.com/web/tools/lighthouse/variabili...
    • Rất vui vì bạn thích nó. Tuy nhiên tôi đã nghĩ các chỉ số hiệu năng sẽ cải thiện hơn. Nếu được, bạn chia sẻ output site tĩnh trước khi áp dụng Jampack, tôi muốn xem thử
      georges [at] divriots [dot] com
  • Làm tôi nhớ đến module PageSpeed cho Apache và Nginx: https://developers.google.com/speed/pagespeed/module

  • Chà, cái này khá đúng ý tôi. Tôi sẽ dùng thử
    Nếu có ai thấy nó không ổn, mong chỉ ra các khiếm khuyết. Với tôi nó trông giống như biên dịch C thành assembly tối ưu cực cao, và có vẻ là công cụ làm thay rất chắc những việc tôi không muốn tự làm

    • Nếu phải triển khai thứ gì đó kiểu assembly tối ưu cực cao cho HTML và CSS, tôi không chắc chúng ta đang đi đúng hướng
      Theo tôi, nếu viết HTML và CSS đơn giản, trực quan nhất thì trình duyệt trên mọi thiết bị nên cứ render tốt
      Nếu thật sự phải triển khai sản phẩm tối ưu ở mức đó, có lẽ tốt hơn là bỏ qua hẳn HTML và CSS, triển khai WebAssembly được tối ưu cao rồi để developer dùng ngôn ngữ họ muốn
  • Sẽ hay nếu có cách subset font dựa trên phạm vi Unicode trong output của SSG, và cố định các trục OpenType dựa trên font-feature-settings được định nghĩa trong CSS

    • Đúng vậy, có nhiều việc thú vị có thể làm ở mảng font. Trong TODO có việc tự động thêm font hệ thống thay thế với metric phù hợp để tự cải thiện CLS
      Tôi không rõ đó có phải là “cố định trục OpenType dựa trên font-feature-settings” mà bạn nói không, hay bạn có ý khác
      Tôi cũng muốn tối ưu subset font, nhưng chưa rõ mức cải thiện sẽ lớn đến đâu. Không biết bạn từng làm thủ công việc này chưa
    • Nếu dùng font trình duyệt/hệ thống thì có thể tối ưu xuống kích thước font 0, nên tôi tự hỏi có cần làm không
  • Khái niệm xác định CSS quan trọng cần inline thay vì để trong stylesheet riêng khá thú vị
    Tôi đã kỳ vọng có cách phân biệt CSS quan trọng và không quan trọng một cách nguyên tắc. Ví dụ các hiệu ứng tương tác người dùng như :hover thì luôn xem là không quan trọng
    Nhưng thư viện được dùng lại render trang rồi ước đoán tốt nhất xem quy tắc nào có thể được coi là quan trọng, nên hơi tiếc: https://github.com/GoogleChromeLabs/critters

    • Nếu CSS dưới 50KB thì cứ inline là được. Nếu có CSS vượt 50KB thì có lẽ bạn đang làm sai gì đó
      Tất nhiên nếu inline cả font thì tôi hiểu, nhưng nếu chỉ phần style khác mà vượt 50KB thì đa phần là đi sai hướng
      Nói nghiêm túc, inline cực kỳ có lợi cho hiệu năng ngay cả khi so với cache ấm, và ngưỡng để stylesheet hoặc script bên ngoài bắt đầu tốt hơn cao hơn bạn nghĩ, trong các điều kiện thị trường phổ biến có khi lên tới vài trăm KB
      Khái niệm CSS quan trọng có cảm giác như một cách tiếp cận mang tính chủ bại, cố lấy lại một chút hiệu năng đã lãng phí thay vì sửa vấn đề gốc
      Tuy vậy đây không phải là kỹ thuật có hệ thống, mà là phán đoán dựa trên ít kinh nghiệm và quan sát. Tôi mong ai đó đo lường khái niệm này tử tế hơn, nhưng chắc người đó không phải tôi
  • Cái này có vẻ bao phủ nhiều mục đích mà ngay từ đầu mọi người chọn SSG và plugin để làm. Đặc biệt nếu họ chọn Astro hoặc Eleventy thì càng đúng
    Có lý do nào để thích đặt nó thành một bước riêng sau build không? Rebuild trong lúc phát triển sẽ nhanh hơn, nhưng trông như một đánh đổi với khả năng bỏ sót những bug tinh vi phát sinh khi thêm các khai báo như width cho ảnh

  • Với người ghét làm layout web và cũng không chịu học, nhưng thỉnh thoảng vẫn phải làm như tôi, công cụ này trông rất tuyệt

  • Trông ổn. Tuy nhiên cá nhân tôi không thích việc phải chờ ảnh khi cuộn trang xuống dưới màn hình đầu tiên
    Theo mặc định, sau khi nội dung màn hình đầu kết thúc, các nội dung còn lại phía dưới có được tải trong nền không?

    • Không. Nó tận dụng lazy loading native của trình duyệt. Các trình duyệt lớn xử lý thuộc tính loading="lazy" với nghĩa là “đừng tải ảnh/iframe này cho đến khi nó gần xuất hiện”: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/im...
      Tuy nhiên tỷ lệ khung hình được chèn inline, nên layout sẽ không thay đổi sau khi tải xong. Nói cách khác, tránh được tội lỗi lớn nhất của lazy loading
    • Như @lelandfe đã chỉ ra, Jampack dùng loading="lazy" native của trình duyệt
      Hiện chưa có cách thay đổi hành vi này, nhưng có thể thêm tùy chọn preload ảnh dưới màn hình đầu trong nền sau khi toàn bộ trang đã load. Ý tưởng khá hay
      Dù vậy tôi lo nó sẽ tải cả những ảnh không cần thiết ở cuối trang. Nếu là tùy chọn thì mỗi người có thể bật hoặc tắt, nên có vẻ ổn
  • Có những static site generator nào đang được dùng trong môi trường production? Có vẻ công cụ này có thể tối ưu output của chúng tốt hơn
    Ví dụ hôm qua tôi mất cả ngày làm theo ví dụ để chuyển website React của Divjoy thành HTML đơn giản và phục vụ từ S3 bucket. Tôi không ngờ lại khó đến vậy và giờ vẫn còn loay hoay
    Lý tưởng là có thứ gì đó tự động deploy lên S3 bucket và nối luôn domain. Đau ở chỗ tôi đã trả tiền mà developer biến mất, Discord cũng bị bỏ mặc. Vì vậy tôi luôn thích FOSS hơn

    • Có Hugo, Zola, Jekyll, đại loại vậy
      Ở một mức độ nào đó, chúng có một phần các chức năng như vậy
  • Với một dự án của tôi thì không có thay đổi lớn. Ví dụ tổng kích thước bundle giảm, nhưng kích thước gzip lại tăng, nên thực tế là tôi bị lỗ ròng
    Dù vậy phần cải thiện CSS có vẻ thật sự hữu ích
    Ý tưởng trông rất hay, và nếu dự án có hình ảnh thì có lẽ đã có ích

    • Nếu không có ảnh thì đúng là lợi ích bị hạn chế. Ngoài ra vì nó tự động cải thiện khả năng tương thích trình duyệt, kích thước CSS cuối cùng cũng có thể lớn hơn
      Bạn có thể tắt tính năng này bằng cách đặt browserlist thành chuỗi rỗng: https://jampack.divriots.com/features/browser-compatibility/