Otomatik Olarak Satır İçi Girilen Kodun Tuzaklarından Kaçınmak
Yayınlanan: 2022-03-10 Satır içi oluşturma, dosyaların içeriğini doğrudan HTML belgesine dahil etme işlemidir: CSS dosyaları bir style
öğesinin içinde satır içine alınabilir ve JavaScript dosyaları bir script
öğesinin içinde satır içine alınabilir:
<style> /* CSS contents here */ </style> <script> /* JS contents here */ </script>
HTML çıktısında zaten bulunan kodu yazdırarak, satır içi oluşturma, oluşturma engelleme isteklerini önler ve kodu sayfa oluşturulmadan önce yürütür. Bu nedenle, sitenin algılanan performansını (yani bir sayfanın kullanılabilir hale gelmesi için geçen süreyi) iyileştirmek için yararlıdır. Örneğin, siteyi satır içi olarak yüklerken (yaklaşık 14 kb) hemen iletilen verilerin arabelleğini kullanabiliriz. Ekranın üst kısmındaki içerik stilleri (önceki Smashing Magazine sitesinde yapıldığı gibi) dahil olmak üzere kritik stiller ve verilerin geri kalanı teslim edildiğinde ürkek bir düzenin yeniden oluşturulmasını önlemek için yazı tipi boyutları ve düzen genişlikleri ve yükseklikleri .
Ancak, aşırıya kaçıldığında, satır içi kodun sitenin performansı üzerinde olumsuz etkileri olabilir: Kod önbelleğe alınamadığından, aynı içerik müşteriye tekrar tekrar gönderilir ve Hizmet Çalışanları aracılığıyla önbelleğe alınamaz veya önbelleğe alınır ve bir İçerik Dağıtım Ağından erişilir. Ayrıca, bir İçerik Güvenliği Politikası (CSP) uygulanırken satır içi komut dosyalarının güvenli olmadığı kabul edilir. Ardından, sitenin daha hızlı yüklenmesini sağlayan ancak aksi takdirde mümkün olduğunca kaçınılan kritik CSS ve JS bölümlerini satır içine almak mantıklı bir strateji oluşturur.
Bu makalede, satır içi kodun statik varlıklara nasıl dönüştürüleceğini keşfedeceğiz: Satır içi kodun statik varlıklara nasıl dönüştürüleceğini keşfedeceğiz: Kodu HTML çıktısında yazdırmak yerine, onu diske kaydederiz (etkili bir şekilde statik bir dosya oluştururuz) ve ilgili <script>
ekleriz. <script>
veya <link>
etiketini kullanarak dosyayı yükleyin.
Başlayalım!
Önerilen okuma : Bir Süreç Olarak WordPress Güvenliği
Satır İçi İşlemden Ne Zaman Kaçının
Bazı kodların satır içi olması gerekip gerekmediğini belirlemek için sihirli bir reçete yoktur, ancak bazı kodların satır içine alınmaması gerektiğinde oldukça açık olabilir: büyük bir kod yığını içerdiğinde ve hemen gerekli olmadığında.
Örnek olarak, WordPress siteleri, Medya Yöneticisi'ni ( /wp-admin/upload.php
altındaki Medya Kitaplığı sayfasından erişilebilir) oluşturmak için JavaScript şablonlarını satır içine alır ve büyük miktarda kod yazdırır:
43 kb'lık bir alanı kaplayan bu kod parçasının boyutu ihmal edilebilir düzeyde değildir ve sayfanın en altında yer aldığı için hemen gerekli değildir. Bu nedenle, bu kodu statik varlıklar aracılığıyla sunmak veya HTML çıktısı içinde yazdırmak çok mantıklı olacaktır.
Şimdi satır içi kodun statik varlıklara nasıl dönüştürüleceğini görelim.
Statik Dosyaların Oluşturulmasını Tetikleme
İçerikler (satır içine alınacaklar) statik bir dosyadan geliyorsa, kodu satır içine almak yerine bu statik dosyayı istemekten başka yapacak pek bir şey yoktur.
Dinamik kod için ise, içeriğiyle birlikte statik dosyanın nasıl/ne zaman oluşturulacağını planlamalıyız. Örneğin, site yapılandırma seçenekleri sunuyorsa (renk şemasını veya arka plan görüntüsünü değiştirmek gibi), yeni değerleri içeren dosya ne zaman oluşturulmalıdır? Dinamik koddan statik dosyalar oluşturmak için aşağıdaki fırsatlara sahibiz:
- İstek üzerine
Bir kullanıcı içeriğe ilk kez eriştiğinde. - değişimde
Dinamik kodun kaynağı (örneğin bir konfigürasyon değeri) değiştiğinde.
Önce istek üzerine düşünelim. Bir kullanıcı, diyelim ki /index.html
aracılığıyla siteye ilk eriştiğinde, statik dosya (örn. header-colors.css
) henüz mevcut değildir, bu nedenle o zaman oluşturulmalıdır. Olayların sırası aşağıdaki gibidir:
- Kullanıcı
/index.html
ister; - İsteği işlerken sunucu,
header-colors.css
dosyasının var olup olmadığını kontrol eder. Olmadığından kaynak kodunu alır ve dosyayı diskte oluşturur; - İstemciye,
<link rel="stylesheet" type="text/css" href="/staticfiles/header-colors.css">
etiketi dahil olmak üzere bir yanıt döndürür. - Tarayıcı,
header-colors.css
dahil olmak üzere sayfada bulunan tüm kaynakları getirir; - O zamana kadar bu dosya var, bu yüzden sunuluyor.
Bununla birlikte, olayların sırası da farklı olabilir ve bu da tatmin edici olmayan bir sonuca yol açabilir. Örneğin:
- Kullanıcı
/index.html
ister; - Bu dosya tarayıcı (veya başka bir proxy veya Hizmet Çalışanları aracılığıyla) tarafından zaten önbelleğe alınmış olduğundan, istek hiçbir zaman sunucuya gönderilmez;
- Tarayıcı,
header-colors.css
dahil olmak üzere sayfada bulunan tüm kaynakları getirir. Ancak bu görüntü tarayıcıda önbelleğe alınmaz, bu nedenle istek sunucuya gönderilir; - Sunucu henüz
header-colors.css
oluşturmadı (örneğin, henüz yeniden başlatıldı); - Bir 404 döndürür.
Alternatif olarak, /index.html
istenirken değil, /header-colors.css
header-colors.css
oluşturabiliriz. Ancak, bu dosya başlangıçta mevcut olmadığından, istek zaten 404 olarak kabul edilir. Durum kodunu 200 olarak değiştirmek için başlıkları değiştirerek ve görüntünün içeriğini döndürerek, yolumuzu hackleyebilsek bile, bu, işleri yapmanın korkunç bir yolu, bu yüzden bu olasılığı göz önünde bulundurmayacağız (biz bundan çok daha iyiyiz!)
Geriye tek bir seçenek kalıyor: kaynağı değiştikten sonra statik dosyayı oluşturmak.
Kaynak Değiştiğinde Statik Dosya Oluşturma
Lütfen hem kullanıcıya bağlı hem de siteye bağlı kaynaklardan dinamik kod oluşturabileceğimize dikkat edin. Örneğin, tema sitenin arka plan görüntüsünü değiştirmeye izin veriyorsa ve bu seçenek sitenin yöneticisi tarafından yapılandırılırsa, dağıtım sürecinin bir parçası olarak statik dosya oluşturulabilir. Öte yandan, site, kullanıcılarına profilleri için arka plan resmini değiştirmelerine izin veriyorsa, çalışma zamanında statik dosya oluşturulmalıdır.
Özetle, şu iki durumumuz var:
- Kullanıcı Yapılandırması
Kullanıcı bir yapılandırmayı güncellediğinde işlem tetiklenmelidir. - Site yapılandırması
İşlem, yönetici site için bir yapılandırmayı güncellediğinde veya siteyi dağıtmadan önce tetiklenmelidir.
İki durumu bağımsız olarak ele alırsak, #2 için süreci istediğimiz herhangi bir teknoloji yığını üzerinde tasarlayabiliriz. Ancak, iki farklı çözüm değil, her iki durumu da çözebilecek benzersiz bir çözüm uygulamak istiyoruz. Ve #1'den itibaren statik dosya oluşturma sürecinin çalışan sitede tetiklenmesi gerektiğinden, bu işlemi sitenin üzerinde çalıştığı teknoloji yığını etrafında tasarlamak zorlayıcıdır.
Süreci tasarlarken, kodumuzun hem #1 hem de #2'nin özel koşullarını ele alması gerekecek:
- sürüm oluşturma
Yeni bir statik dosya oluşturulduğunda önceki dosyayı geçersiz kılmak için statik dosyaya bir "versiyon" parametresi ile erişilmelidir. #2 siteyle aynı sürüme sahip olabilirken, #1'in her kullanıcı için muhtemelen veritabanına kaydedilmiş dinamik bir sürüm kullanması gerekir. - Oluşturulan dosyanın konumu
#2 tüm site için benzersiz bir statik dosya oluşturur (örneğin/staticfiles/header-colors.css
), #1 ise her kullanıcı için bir statik dosya oluşturur (örneğin/staticfiles/users/leo/header-colors.css
). - Tetikleyici olay
#1 için statik dosyanın çalışma zamanında yürütülmesi gerekirken, #2 için hazırlama ortamımızdaki bir oluşturma işleminin parçası olarak da yürütülebilir. - Dağıtım ve dağıtım
#2'deki statik dosyalar, sitenin dağıtım paketine sorunsuz bir şekilde entegre edilebilir ve hiçbir zorluk yaşamaz; Ancak #1'deki statik dosyalar yapamaz, bu nedenle işlemin bir yük dengeleyicinin arkasındaki birden çok sunucu gibi ek endişeleri ele alması gerekir (statik dosyalar yalnızca 1 sunucuda mı yoksa tümünde mi oluşturulacak ve nasıl?).
Sıradaki süreci tasarlayıp uygulayalım. Oluşturulacak her statik dosya için dosyanın meta verilerini içeren bir nesne oluşturmalı, içeriğini dinamik kaynaklardan hesaplamalı ve son olarak statik dosyayı diske kaydetmeliyiz. Aşağıdaki açıklamalara rehberlik edecek bir kullanım örneği olarak, aşağıdaki statik dosyaları oluşturacağız:
- veritabanına kaydedilen değerlerden bazı stiller ile
header-colors.css
-
welcomeuser-data.js
, bazı değişkenler altında kullanıcı verileri içeren bir JSON nesnesi içerir:window.welcomeUserData = {name: "Leo"};
.
Aşağıda, yığını PHP ve WordPress işlevlerine dayandırmamız gereken WordPress için statik dosyalar oluşturma sürecini anlatacağım. Statik dosyaları yerleştirmeden önce oluşturma işlevi, bir önceki makalede açıkladığım gibi [create_static_files]
kısa kodunu yürüten özel bir sayfa yüklenerek tetiklenebilir.
Daha fazla önerilen okuma : Bir Servis Çalışanı Yapmak: Bir Vaka Çalışması
Dosyayı Nesne Olarak Temsil Etme
Bir dosyayı ilgili tüm özelliklere sahip bir PHP nesnesi olarak modellememiz gerekir, böylece hem /staticfiles/
/staticfiles/users/leo/
belirli bir konuma kaydedebiliriz (örn. dolayısıyla dosya. Bunun için hem dosyanın meta verilerini (dosya adı, dizin, tür: “css” veya “js”, sürüm ve diğer kaynaklara bağımlılıklar) hem de içeriğini döndüren bir Resource
arabirimi oluşturuyoruz.
interface Resource { function get_filename(); function get_dir(); function get_type(); function get_version(); function get_dependencies(); function get_content(); }
Kodu sürdürülebilir ve yeniden kullanılabilir hale getirmek için, tüm Resource uygulamalarımızın devralacağı soyut ResourceBase
sınıfından başlayarak, kademeli olarak özellikler eklemek üzere kaynaklar için bir nesne devralma şeması belirlediğimiz SOLID ilkelerini izleriz:
abstract class ResourceBase implements Resource { function get_dependencies() { // By default, a file has no dependencies return array(); } }
SOLID'den sonra, özellikler farklılık gösterdiğinde alt sınıflar yaratırız. Daha önce belirtildiği gibi, oluşturulan statik dosyanın konumu ve onu talep edecek sürüm oluşturma, dosyanın kullanıcı veya site yapılandırmasıyla ilgili olmasına bağlı olarak farklı olacaktır:
abstract class UserResourceBase extends ResourceBase { function get_dir() { // A different file and folder for each user $user = wp_get_current_user(); return "/staticfiles/users/{$user->user_login}/"; } function get_version() { // Save the resource version for the user under her meta data. // When the file is regenerated, must execute `update_user_meta` to increase the version number $user_id = get_current_user_id(); $meta_key = "resource_version_".$this->get_filename(); return get_user_meta($user_id, $meta_key, true); } } abstract class SiteResourceBase extends ResourceBase { function get_dir() { // All files are placed in the same folder return "/staticfiles/"; } function get_version() { // Same versioning as the site, assumed defined under a constant return SITE_VERSION; } }
Son aşamada, get_content
işlevi aracılığıyla dosya adını, dosya türünü ve dinamik kodu ekleyerek oluşturmak istediğimiz dosyalar için nesneleri uygularız:
class HeaderColorsSiteResource extends SiteResourceBase { function get_filename() { return "header-colors"; } function get_type() { return "css"; } function get_content() { return sprintf( " .site-title a { color: #%s; } ", esc_attr(get_header_textcolor()) ); } } class WelcomeUserDataUserResource extends UserResourceBase { function get_filename() { return "welcomeuser-data"; } function get_type() { return "js"; } function get_content() { $user = wp_get_current_user(); return sprintf( "window.welcomeUserData = %s;", json_encode( array( "name" => $user->display_name ) ) ); } }
Bununla dosyayı bir PHP nesnesi olarak modelledik. Ardından, diske kaydetmemiz gerekiyor.
Statik Dosyayı Diske Kaydetme
Bir dosyayı diske kaydetmek, dilin sağladığı yerel işlevler aracılığıyla kolayca gerçekleştirilebilir. PHP durumunda bu, fwrite
işlevi aracılığıyla gerçekleştirilir. Ek olarak, diskteki dosyanın mutlak yolunu ve ayrıca sitenin köküne göre yolunu sağlayan işlevlere sahip bir ResourceUtils
yardımcı programı sınıfı oluşturuyoruz:
class ResourceUtils { protected static function get_file_relative_path($fileObject) { return $fileObject->get_dir().$fileObject->get_filename().".".$fileObject->get_type(); } static function get_file_path($fileObject) { // Notice that we must add constant WP_CONTENT_DIR to make the path absolute when saving the file return WP_CONTENT_DIR.self::get_file_relative_path($fileObject); } } class ResourceGenerator { static function save($fileObject) { $file_path = ResourceUtils::get_file_path($fileObject); $handle = fopen($file_path, "wb"); $numbytes = fwrite($handle, $fileObject->get_content()); fclose($handle); } }
Ardından, kaynak değiştiğinde ve statik dosyanın yeniden oluşturulması gerektiğinde, dosyayı bir parametre olarak temsil eden nesneyi geçirerek ResourceGenerator::save
yürütürüz. Aşağıdaki kod, "header-colors.css" ve "welcomeuser-data.js" dosyalarını yeniden oluşturur ve diske kaydeder:
// When need to regenerate header-colors.css, execute: ResourceGenerator::save(new HeaderColorsSiteResource()); // When need to regenerate welcomeuser-data.js, execute: ResourceGenerator::save(new WelcomeUserDataUserResource());
Var olduklarında, <script>
ve <link>
etiketleri aracılığıyla yüklenecek dosyaları sıraya koyabiliriz.
Statik Dosyaları Sıralama
Statik dosyaların kuyruğa alınması, WordPress'teki herhangi bir kaynağın kuyruğa alınmasından farklı değildir: wp_enqueue_script
ve wp_enqueue_style
işlevleri aracılığıyla. Ardından, tüm nesne örneklerini yineler ve get_type()
değerlerinin "js"
veya "css"
olmasına bağlı olarak bir kanca veya diğerini kullanırız.
Önce dosyanın URL'sini sağlamak ve türün JS veya CSS olduğunu söylemek için yardımcı işlevler ekliyoruz:
class ResourceUtils { // Continued from above... static function get_file_url($fileObject) { // Add the site URL before the file path return get_site_url().self::get_file_relative_path($fileObject); } static function is_css($fileObject) { return $fileObject->get_type() == "css"; } static function is_js($fileObject) { return $fileObject->get_type() == "js"; } }
ResourceEnqueuer
sınıfının bir örneği, yüklenmesi gereken tüm dosyaları içerecektir; çağrıldığında, enqueue_scripts
ve enqueue_styles
işlevleri, karşılık gelen WordPress işlevlerini (sırasıyla wp_enqueue_script
ve wp_enqueue_style
) yürüterek sıralamayı yapacaktır:
class ResourceEnqueuer { protected $fileObjects; function __construct($fileObjects) { $this->fileObjects = $fileObjects; } protected function get_file_properties($fileObject) { $handle = $fileObject->get_filename(); $url = ResourceUtils::get_file_url($fileObject); $dependencies = $fileObject->get_dependencies(); $version = $fileObject->get_version(); return array($handle, $url, $dependencies, $version); } function enqueue_scripts() { $jsFileObjects = array_map(array(ResourceUtils::class, 'is_js'), $this->fileObjects); foreach ($jsFileObjects as $fileObject) { list($handle, $url, $dependencies, $version) = $this->get_file_properties($fileObject); wp_register_script($handle, $url, $dependencies, $version); wp_enqueue_script($handle); } } function enqueue_styles() { $cssFileObjects = array_map(array(ResourceUtils::class, 'is_css'), $this->fileObjects); foreach ($cssFileObjects as $fileObject) { list($handle, $url, $dependencies, $version) = $this->get_file_properties($fileObject); wp_register_style($handle, $url, $dependencies, $version); wp_enqueue_style($handle); } } }
Son olarak, her dosyayı temsil eden PHP nesnelerinin bir listesiyle ResourceEnqueuer
sınıfının bir nesnesini başlatıyoruz ve kuyruğa almayı yürütmek için bir WordPress kancası ekliyoruz:
// Initialize with the corresponding object instances for each file to enqueue $fileEnqueuer = new ResourceEnqueuer( array( new HeaderColorsSiteResource(), new WelcomeUserDataUserResource() ) ); // Add the WordPress hooks to enqueue the resources add_action('wp_enqueue_scripts', array($fileEnqueuer, 'enqueue_scripts')); add_action('wp_print_styles', array($fileEnqueuer, 'enqueue_styles'));
İşte bu: Sıraya alındığında, site istemciye yüklenirken statik dosyalar istenecektir. Bunun yerine satır içi kod yazdırmaktan ve statik kaynaklar yüklemekten kaçınmayı başardık.
Ardından, ek performans kazanımları için birkaç iyileştirme uygulayabiliriz.
Önerilen okuma : PHPUnit ile WordPress Eklentilerinin Otomatik Test Edilmesine Giriş
Dosyaları Birlikte Paketleme
HTTP/2, dosyaları gruplama ihtiyacını azaltmış olsa da, dosyaların sıkıştırılması (örneğin GZip aracılığıyla) daha etkili olacağından ve tarayıcıların (Chrome gibi) daha büyük bir ek yükü olduğundan, siteyi daha hızlı hale getirir. .
Şimdiye kadar, bir dosyayı PHP nesnesi olarak modelledik, bu nesneyi diğer işlemlere girdi olarak ele almamıza izin verdi. Özellikle, aynı türden tüm dosyaları bir araya toplamak ve tüm bağımsız dosyalar yerine paketlenmiş sürümü sunmak için yukarıdaki aynı işlemi tekrarlayabiliriz. Bunun için, $fileObjects
altındaki her kaynaktan içeriği çıkaran ve yeniden yazdıran, tüm kaynaklardan tüm içeriğin toplanmasını üreten bir get_content
işlevi oluşturuyoruz:
abstract class SiteBundleBase extends SiteResourceBase { protected $fileObjects; function __construct($fileObjects) { $this->fileObjects = $fileObjects; } function get_content() { $content = ""; foreach ($this->fileObjects as $fileObject) { $content .= $fileObject->get_content().PHP_EOL; } return $content; } }
Bu dosya için bir sınıf oluşturarak tüm dosyaları bundled-styles.css
dosyasında toplayabiliriz:
class StylesSiteBundle extends SiteBundleBase { function get_filename() { return "bundled-styles"; } function get_type() { return "css"; } }
Son olarak, tüm bağımsız kaynaklar yerine, daha önce olduğu gibi, bu paketlenmiş dosyaları basitçe sıraya koyarız. CSS için, header-colors.css
, background-image.css
ve font-sizes.css
dosyalarını içeren bir paket oluşturuyoruz, bunun için StylesSiteBundle
bu dosyaların her biri için PHP nesnesiyle başlatıyoruz (ve aynı şekilde JS'yi de oluşturabiliriz). paket dosyası):
$fileObjects = array( // CSS new HeaderColorsSiteResource(), new BackgroundImageSiteResource(), new FontSizesSiteResource(), // JS new WelcomeUserDataUserResource(), new UserShoppingItemsUserResource() ); $cssFileObjects = array_map(array(ResourceUtils::class, 'is_css'), $fileObjects); $jsFileObjects = array_map(array(ResourceUtils::class, 'is_js'), $fileObjects); // Use this definition of $fileEnqueuer instead of the previous one $fileEnqueuer = new ResourceEnqueuer( array( new StylesSiteBundle($cssFileObjects), new ScriptsSiteBundle($jsFileObjects) ) );
Bu kadar. Şimdi çok sayıda dosya yerine yalnızca bir JS dosyası ve bir CSS dosyası talep edeceğiz.
Algılanan performans için son bir iyileştirme, hemen ihtiyaç duyulmayan varlıkların yüklenmesini geciktirerek varlıklara öncelik verilmesini içerir. Bunu bir sonraki ele alalım.
JS Kaynakları için async
/ defer
Nitelikleri
JavaScript dosyasının indirildiği, ayrıştırıldığı ve yürütüldüğü zamanı değiştirmek, kritik JavaScript'e öncelik vermek ve kritik olmayan her şeyi mümkün olduğunca geç göndermek, böylece sitenin görünen yüklemesini azaltmak için <script>
etiketine zaman async
ve defer
nitelikleri ekleyebiliriz. zaman.
Bu özelliği uygulamak için, SOLID ilkelerini izleyerek, is_async
ve is_defer
işlevlerini içeren JSResource
( Resource
öğesinden miras alan) yeni bir arabirim oluşturmalıyız. Ancak bu, sonunda bu öznitelikleri de destekleyen <style>
etiketlerine kapıyı kapatacaktır. Bu nedenle, uyarlanabilirliği göz önünde bulundurarak, daha açık uçlu bir yaklaşım izliyoruz: Her ikisi için de herhangi bir özniteliğe (zaten var olan veya henüz icat edilmemiş olan) eklemek için esnek tutmak için, Resource
arabirimine get_attributes
genel bir yöntemini ekleriz <script>
ve <link>
etiketleri:
interface Resource { // Continued from above... function get_attributes(); } abstract class ResourceBase implements Resource { // Continued from above... function get_attributes() { // By default, no extra attributes return ''; } }
WordPress, kuyruğa alınan kaynaklara ekstra nitelikler eklemek için kolay bir yol sunmuyor, bu yüzden bunu oldukça hileli bir şekilde yapıyoruz, add_script_tag_attributes
işlevi aracılığıyla etiketin içindeki bir dizenin yerini alan bir kanca ekleyerek:
class ResourceEnqueuerUtils { protected static tag_attributes = array(); static function add_tag_attributes($handle, $attributes) { self::tag_attributes[$handle] = $attributes; } static function add_script_tag_attributes($tag, $handle, $src) { if ($attributes = self::tag_attributes[$handle]) { $tag = str_replace( " src='${src}'>", " src='${src}' ".$attributes.">", $tag ); } return $tag; } } // Initize by connecting to the WordPress hook add_filter( 'script_loader_tag', array(ResourceEnqueuerUtils::class, 'add_script_tag_attributes'), PHP_INT_MAX, 3 );
Karşılık gelen nesne örneğini oluştururken bir kaynağın niteliklerini ekleriz:
abstract class ResourceBase implements Resource { // Continued from above... function __construct() { ResourceEnqueuerUtils::add_tag_attributes($this->get_filename(), $this->get_attributes()); } }
Son olarak, welcomeuser-data.js
kaynağının hemen çalıştırılması gerekmiyorsa, onu defer
olarak ayarlayabiliriz:
class WelcomeUserDataUserResource extends UserResourceBase { // Continued from above... function get_attributes() { return "defer='defer'"; } }
Ertelenmiş olarak yüklendiğinden, bir komut dosyası daha sonra yüklenecek ve kullanıcının siteyle etkileşime girebileceği zaman noktasını öne çıkaracaktır. Performans kazanımlarıyla ilgili olarak, artık hazırız!
Rahatlamadan önce çözmemiz gereken bir sorun kaldı: Site birden fazla sunucuda barındırıldığında ne olur?
Bir Yük Dengeleyicinin Arkasındaki Birden Çok Sunucuyla Başa Çıkmak
Sitemiz bir yük dengeleyicinin arkasındaki birkaç sitede barındırılıyorsa ve kullanıcı yapılandırmasına bağlı bir dosya yeniden oluşturulursa, isteği işleyen sunucu bir şekilde yeniden oluşturulan statik dosyayı diğer tüm sunuculara yüklemelidir; aksi takdirde, diğer sunucular o andan itibaren o dosyanın eski bir sürümünü sunacaktır. Bunu nasıl yapabiliriz? Sunucuların birbirleriyle iletişim kurmasını sağlamak sadece karmaşık olmakla kalmaz, aynı zamanda sonuçta mümkün olmayabilir: Site farklı bölgelerden yüzlerce sunucuda çalışırsa ne olur? Açıkçası, bu bir seçenek değil.
Bulduğum çözüm, bir dolaylılık düzeyi eklemektir: statik dosyaları site URL'sinden istemek yerine, buluttaki bir AWS S3 kovası gibi bir konumdan istenirler. Ardından, dosyayı yeniden oluşturduktan sonra, sunucu yeni dosyayı hemen S3'e yükleyecek ve oradan sunacaktır. Bu çözümün uygulanması bir önceki makalemde AWS S3 Üzerinden Verileri Birden Çok Sunucu Arasında Paylaşma bölümünde açıklanmıştır.
Çözüm
Bu makalede, JS ve CSS kodunu satır içine almanın her zaman ideal olmadığını düşündük, çünkü kodun müşteriye tekrar tekrar gönderilmesi gerekir, bu da kod miktarı önemliyse performansı etkileyebilir. Örnek olarak, WordPress'in Media Manager'ı yazdırmak için 43 kb'lık komut dosyalarını nasıl yüklediğini gördük.
Bu nedenle, dinamik JS ve CSS satır içi kodunu statik kaynaklara dönüştürerek web sitesini daha hızlı hale getirmenin bir yolunu tasarladık, bu da birkaç düzeyde önbelleğe almayı iyileştirebilir (istemcide, Service Workers, CDN'de), tüm dosyaları daha fazla bir araya getirmeye olanak tanır çıktıyı sıkıştırırken (örneğin GZip aracılığıyla) oranı iyileştirmek ve tarayıcılarda aynı anda birkaç kaynağı (Chrome'da olduğu gibi) işlemekten kaynaklanan bir ek yükü önlemek için yalnızca bir JS/CSS kaynağına ve ek olarak zaman async
veya defer
nitelikleri eklemeye izin verir. kullanıcı etkileşimini hızlandırmak ve böylece sitenin görünen yükleme süresini iyileştirmek için <script>
etiketine.
Yararlı bir yan etki olarak, kodu statik kaynaklara bölmek aynı zamanda kodun daha okunaklı olmasını sağlar, büyük HTML blokları yerine kod birimleriyle ilgilenir ve bu da projenin daha iyi sürdürülmesine yol açabilir.
Geliştirdiğimiz çözüm PHP'de yapıldı ve WordPress için birkaç özel kod parçası içeriyor, ancak kodun kendisi son derece basit, SOLID ilkelerini izleyerek bu özellikleri uygulayan özellikleri ve nesneleri tanımlayan birkaç arayüz ve bir kaydetme işlevi. diske dosya. Hepsi bukadar. Nihai sonuç, temiz ve kompakttır, başka herhangi bir dil ve platform için yeniden oluşturulması kolaydır ve mevcut bir projeye tanıtılması zor değildir - kolay performans kazanımları sağlar.