Zephyrnet Logosu

Sonraki (veya Herhangi Bir SSR Çerçevesi) ile Web Bileşenlerini Kullanma

Tarih:

Benim de önceki yazı güzel, erişilebilir ve belki de beklenmedik bir şekilde Web Bileşenleri. Bu, herhangi bir JavaScript çerçevesi ile kullanılabilecekleri anlamına gelir. React'in Web Bileşeni birlikte çalışabilirliği şu anda idealden daha az olsa da, geçici çözümler var.

Ancak Web Bileşenlerinin ciddi bir eksikliği, sunucu tarafı işleme (SSR) için mevcut destek eksikliğidir. Çalışmalarda Bildirici Gölge DOM (DSD) adı verilen bir şey var, ancak bunun için mevcut destek oldukça az ve aslında DSD için özel işaretleme yaymak için web sunucunuzdan satın alma gerektiriyor. Şu anda için yapılan bir iş var Next.js görmek için sabırsızlanıyorum. Ancak bu gönderi için, Next.js gibi herhangi bir SSR çerçevesinden Web Bileşenlerini nasıl yöneteceğimize bakacağız. bugün.

Önemsiz miktarda el işi yaparak sona ereceğiz ve hafifçe bu süreçte sayfamızın başlangıç ​​performansını zedelemek. Daha sonra bu performans maliyetlerini nasıl en aza indireceğimize bakacağız. Ancak hata yapmayın: Bu çözümde ödünler yoktur, bu nedenle başka türlü beklemeyin. Daima ölçün ve profilleyin.

Sorun

Dalmadan önce, bir dakikanızı ayıralım ve sorunu gerçekten açıklayalım. Web Bileşenleri neden sunucu tarafı işleme ile iyi çalışmıyor?

Next.js gibi uygulama çerçeveleri, React kodunu alır ve onu esasen "dizileştirmek" için bir API üzerinden çalıştırır, yani bileşenlerinizi düz HTML'ye dönüştürür. Böylece React bileşen ağacı, web uygulamasını barındıran sunucuda işlenecek ve bu HTML, web uygulamasının HTML belgesinin geri kalanıyla birlikte kullanıcınızın tarayıcısına gönderilecektir. Bu HTML ile birlikte bazı tüm React bileşenlerinizin koduyla birlikte React'i yükleyen etiketler. Bir tarayıcı bunları işlediğinde etiketler, React bileşen ağacını yeniden oluşturacak ve gönderilen SSR'd HTML ile işleri eşleştirecektir. Bu noktada, tüm efektler çalışmaya başlayacak, olay işleyicileri bağlanacak ve durum aslında… durumu içerecektir. Bu noktada web uygulaması olur interaktif. Bileşen ağacınızı istemcide yeniden işleme ve her şeyi kablolama işlemine denir. hidrasyon.

Peki, bunun Web Bileşenleri ile ne ilgisi var? Peki, bir şeyi render ederken, aynı Ayakkabı Bağı'nı söyle ziyaret ettiğimiz bileşen son kez:


   General 
   Custom 
   Advanced 
   Disabled 

  This is the general tab panel.
  This is the custom tab panel.
  This is the advanced tab panel.
  This is a disabled tab panel.

…Tepki ver (ya da dürüstçe herhangi JavaScript çerçevesi) bu etiketleri görecek ve basitçe iletecektir. React (veya Svelte veya Solid), bu etiketleri güzel biçimlendirilmiş sekmelere dönüştürmekten sorumlu değildir. Bunun kodu, bu Web Bileşenlerini tanımlayan, sahip olduğunuz kodun içinde saklanır. Bizim durumumuzda, bu kod Shoelace kitaplığındadır, ancak kod herhangi bir yerde olabilir. önemli olan kod çalıştığında.

Normalde, bu Web Bileşenlerini kaydeden kod, bir JavaScript aracılığıyla uygulamanızın normal koduna çekilir. import. Bu, bu kodun JavaScript paketinize gireceği ve hidrasyon sırasında yürütüleceği anlamına gelir; bu, kullanıcınızın SSR'd HTML'yi ilk kez görmesi ile hidrasyonun gerçekleşmesi arasında, bu sekmelerin (veya bu konuda herhangi bir Web Bileşeni) doğru içeriği oluşturmayacağı anlamına gelir. . Ardından, hidrasyon gerçekleştiğinde, uygun içerik görüntülenecek ve bu Web Bileşenlerinin etrafındaki içeriğin hareket etmesine ve düzgün biçimlendirilmiş içeriğe uymasına neden olacaktır. Bu bir olarak bilinir tarzı olmayan içeriğin flaşıveya FOUC. Teoride, bunların hepsinin arasına işaretleme yapıştırabilirsiniz. etiketler, bitmiş çıktıyla eşleşecek şekilde etiketlenir, ancak pratikte bu neredeyse imkansızdır, özellikle Shoelace gibi bir üçüncü taraf bileşen kitaplığı için.

Web Bileşeni kayıt kodumuzu taşıma

Dolayısıyla sorun şu ki, Web Bileşenlerini yapmaları gereken şeyi yapacak kod, hidrasyon gerçekleşene kadar aslında çalışmayacak. Bu gönderi için, bu kodu daha erken çalıştırmaya bakacağız; aslında hemen. Web Bileşeni kodumuzu özel olarak paketlemeye ve doğrudan belgemizin kodlarına manuel olarak bir komut dosyası eklemeye bakacağız. böylece hemen çalışır ve çalışana kadar belgenin geri kalanını engeller. Bu normalde yapılması korkunç bir şeydir. Sunucu tarafı oluşturmanın tüm amacı, değil JavaScript'imiz işlenene kadar sayfamızın işlenmesini engelleyin. Ancak bir kez yapıldığında, belge başlangıçta sunucudan HTML'mizi oluşturduğundan, Web Bileşenlerinin kaydedileceği ve hem anında hem de eşzamanlı olarak doğru içeriği yayınlayacağı anlamına gelir.

Bizim durumumuzda, biz sadece Web Bileşeni kayıt kodumuzu bir engelleme komut dosyasında çalıştırmak istiyoruz. Bu kod çok büyük değil ve sonraki ziyaretlere yardımcı olmak için bazı önbellek başlıkları ekleyerek performansı önemli ölçüde düşürmeye çalışacağız. Bu mükemmel bir çözüm değil. Bir kullanıcı sayfanıza ilk kez göz attığında, bu komut dosyası yüklenirken her zaman engellenir. Sonraki ziyaretler güzel bir şekilde önbelleğe alınır, ancak bu ödün olmayabilir sizin için uygun olabilir - e-ticaret, kimse? Her neyse, profilleyin, ölçün ve uygulamanız için doğru kararı verin. Ayrıca, gelecekte Next.js'nin DSD ve Web Bileşenlerini tam olarak desteklemesi tamamen mümkün.

Başlarken

İnceleyeceğimiz tüm kodlar bu GitHub deposu ve burada Vercel ile konuşlandırıldı. Web uygulaması, hidrasyon üzerine renk ve içerik değiştiren metinle birlikte bazı Ayakkabı Bağı bileşenlerini işler. Ayakkabı Bağı bileşenleri zaten düzgün bir şekilde oluşturulurken metnin “Hidratlı” olarak değiştiğini görebilmeniz gerekir.

Özel donatılacak Web Bileşeni kodu

İlk adımımız, tüm Web Bileşeni tanımlarımızı içe aktaran tek bir JavaScript modülü oluşturmaktır. Kullandığım Ayakkabı Bağı bileşenleri için kodum şöyle görünüyor:

import { setDefaultAnimation } from "@shoelace-style/shoelace/dist/utilities/animation-registry";

import "@shoelace-style/shoelace/dist/components/tab/tab.js";
import "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js";
import "@shoelace-style/shoelace/dist/components/tab-group/tab-group.js";

import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";

setDefaultAnimation("dialog.show", {
  keyframes: [
    { opacity: 0, transform: "translate3d(0px, -20px, 0px)" },
    { opacity: 1, transform: "translate3d(0px, 0px, 0px)" },
  ],
  options: { duration: 250, easing: "cubic-bezier(0.785, 0.135, 0.150, 0.860)" },
});
setDefaultAnimation("dialog.hide", {
  keyframes: [
    { opacity: 1, transform: "translate3d(0px, 0px, 0px)" },
    { opacity: 0, transform: "translate3d(0px, 20px, 0px)" },
  ],
  options: { duration: 250, easing: "cubic-bezier(0.785, 0.135, 0.150, 0.860)" },
});

için tanımları yükler. ve bileşenleri ve iletişim kutusu için bazı varsayılan animasyonları geçersiz kılar. Yeterince basit. Ancak buradaki ilginç kısım, bu kodu uygulamamıza sokmak. Biz yapamam sadece import bu modül. Bunu yapsaydık, normal JavaScript paketlerimizde toplanır ve hidrasyon sırasında çalışırdı. Bu, kaçınmaya çalıştığımız FOUC'a neden olur.

Next.js'de bazı şeyleri özel paketlemek için bir dizi web paketi kancası olsa da, kullanacağım Hayatları yerine. İlk önce şununla kurun: npm i vite ve sonra bir vite.config.js dosya. Benimki şuna benziyor:

import { defineConfig } from "vite";
import path from "path";

export default defineConfig({
  build: {
    outDir: path.join(__dirname, "./shoelace-dir"),
    lib: {
      name: "shoelace",
      entry: "./src/shoelace-bundle.js",
      formats: ["umd"],
      fileName: () => "shoelace-bundle.js",
    },
    rollupOptions: {
      output: {
        entryFileNames: `[name]-[hash].js`,
      },
    },
  },
});

Bu, Web Bileşeni tanımlarımızla bir paket dosyası oluşturacaktır. shoelace-dir dosya. şuraya taşıyalım public klasör, böylece Next.js ona hizmet edecek. Ayrıca, sonunda hash ile dosyanın tam adını takip etmeliyiz. İşte dosyayı hareket ettiren ve paket dosyasının adıyla basit bir sabiti dışa aktaran bir JavaScript modülü yazan bir Düğüm betiği (bu birazdan kullanışlı olacaktır):

const fs = require("fs");
const path = require("path");

const shoelaceOutputPath = path.join(process.cwd(), "shoelace-dir");
const publicShoelacePath = path.join(process.cwd(), "public", "shoelace");

const files = fs.readdirSync(shoelaceOutputPath);

const shoelaceBundleFile = files.find(name => /^shoelace-bundle/.test(name));

fs.rmSync(publicShoelacePath, { force: true, recursive: true });

fs.mkdirSync(publicShoelacePath, { recursive: true });
fs.renameSync(path.join(shoelaceOutputPath, shoelaceBundleFile), path.join(publicShoelacePath, shoelaceBundleFile));
fs.rmSync(shoelaceOutputPath, { force: true, recursive: true });

fs.writeFileSync(path.join(process.cwd(), "util", "shoelace-bundle-info.js"), `export const shoelacePath = "/shoelace/${shoelaceBundleFile}";`);

İşte bir eşlik eden npm betiği:

"bundle-shoelace": "vite build && node util/process-shoelace-bundle",

Bu işe yaramalı. Benim için, util/shoelace-bundle-info.js şimdi var ve şuna benziyor:

export const shoelacePath = "/shoelace/shoelace-bundle-a6f19317.js";

Komut dosyasının yüklenmesi

Next.js'ye girelim _document.js dosya ve Web Bileşeni paket dosyamızın adını çekin:

import { shoelacePath } from "../util/shoelace-bundle-info";

Sonra manuel olarak bir etiketi . İşte benim bütünüm _document.js dosya şuna benzer:

import { Html, Head, Main, NextScript } from "next/document";
import { shoelacePath } from "../util/shoelace-bundle-info";

export default function Document() {
  return (
    
      
        
      
      
        
); }

Ve bu işe yaramalı! Ayakkabı Bağı kaydımız bir engelleme komut dosyasında yüklenecek ve sayfamız ilk HTML'yi işlerken hemen kullanıma sunulacaktır.

Performansı arttırmak

Her şeyi olduğu gibi bırakabiliriz ama Ayakkabı Bağı paketimiz için önbelleğe almayı ekleyelim. Next.js yapılandırma dosyamıza aşağıdaki girişi ekleyerek Next.js'ye bu Ayakkabı Bağı paketlerini önbelleğe alınabilir hale getirmesini söyleyeceğiz:

async headers() {
  return [
    {
      source: "/shoelace/shoelace-bundle-:hash.js",
      headers: [
        {
          key: "Cache-Control",
          value: "public,max-age=31536000,immutable",
        },
      ],
    },
  ];
}

Şimdi, sitemize sonraki göz atmalarımızda, Ayakkabı Bağı paketinin güzel bir şekilde önbelleğe alındığını görüyoruz!

DevTools Kaynakları paneli açılır ve yüklenen Ayakkabı Bağı paketini gösterir.

Ayakkabı Bağı paketimiz değişirse, dosya adı değişecektir ( :hash Yukarıdaki kaynak özelliğinden bir kısmı), tarayıcı bu dosyanın önbelleğe alınmadığını görecek ve sadece onu ağdan yeni isteyecektir.

Tamamlayan

Bu çok fazla el işi gibi görünebilir; ve öyleydi. Ne yazık ki Web Bileşenleri, sunucu tarafı işleme için hazır destek sunmaz.

Ancak sağladıkları faydaları unutmamalıyız: Belirli bir çerçeveye bağlı olmayan kaliteli UX bileşenlerini kullanabilmek güzel. Yepyeni çerçevelerle denemeler yapabilmek çok güzel. İçi Dolu, bir tür sekme, mod, otomatik tamamlama veya herhangi bir bileşen bulmaya (veya birlikte kesmeye) gerek kalmadan.

spot_img

En Son İstihbarat

spot_img

Bizimle sohbet

Merhaba! Size nasıl yardım edebilirim?