Prerender-SPA-Plugin v3 ile Vue.js Uygulamalarını Önceden Oluşturma
Tek Sayfalı Uygulamalar (SPA’lar), modern web geliştirmenin temel taşlarından biri haline gelmiştir. Vue.js, React ve Angular gibi güçlü framework’ler sayesinde geliştiriciler, zengin, etkileşimli ve dinamik kullanıcı deneyimleri sunan uygulamalar oluşturabilirler. Ancak, SPA’ların getirdiği bazı zorluklar da bulunmaktadır, özellikle Arama Motoru Optimizasyonu (SEO), ilk içerik boyama (First Contentful Paint – FCP) performansı ve sosyal medya paylaşımları gibi alanlarda. Bu zorlukların üstesinden gelmek için önceden oluşturma (prerendering) tekniği, giderek daha fazla popülerlik kazanmaktadır. Bu makalede, Vue.js uygulamalarınızı prerender-spa-plugin‘in v3 sürümünü kullanarak nasıl önceden oluşturacağınızı, bu sürecin avantajlarını, dezavantajlarını ve en iyi uygulamalarını detaylı bir şekilde inceleyeceğiz.
Tek Sayfalı Uygulamaların Zorlukları ve Önceden Oluşturmanın Çözümleri
SPA’lar, tarayıcıda JavaScript aracılığıyla dinamik olarak içerik oluşturan uygulamalardır. Bu yaklaşım, sayfa yenilemeleri olmadan hızlı geçişler ve akıcı bir kullanıcı deneyimi sağlar. Ancak, bu dinamik yapı bazı önemli sorunlara yol açabilir:
SEO Sorunları
Geleneksel olarak, arama motoru tarayıcıları (crawler’lar), bir web sayfasını ziyaret ettiklerinde HTML içeriğini okur ve dizine ekler. SPA’lar ise genellikle başlangıçta boş veya minimal bir HTML dosyası (örneğin, yalnızca bir
etiketi) sunar. İçerik, JavaScript yüklendikten ve çalıştırıldıktan sonra DOM’a eklenir. Modern arama motorları (özellikle Google), JavaScript’i işleme konusunda önemli ilerlemeler kaydetmiş olsa da, bu süreç zaman alıcı olabilir ve her zaman mükemmel sonuçlar vermeyebilir. Diğer arama motorları veya daha eski tarayıcılar için bu durum ciddi bir dezavantajdır. Sonuç olarak, uygulamanızın içeriği arama motorları tarafından doğru bir şekilde dizine eklenmeyebilir, bu da organik trafik kaybına yol açar.
Performans ve İlk İçerik Boyama (FCP)
Kullanıcı bir SPA’yı ziyaret ettiğinde, tarayıcı önce HTML, CSS ve JavaScript dosyalarını indirir. JavaScript dosyaları büyük olabilir ve tarayıcının bunları indirmesi, ayrıştırması ve çalıştırması zaman alabilir. Bu süre zarfında kullanıcı, boş bir beyaz ekran veya yükleme göstergesi görebilir. Bu durum, “İlk İçerik Boyama” (FCP) süresini uzatır ve kötü bir kullanıcı deneyimi yaratır. Hızlı yüklenen sayfalar, kullanıcı memnuniyetini artırır ve hemen çıkma oranlarını düşürür.
Sosyal Medya Paylaşımları
Sosyal medya platformları (Facebook, Twitter, LinkedIn vb.), bir bağlantı paylaşıldığında sayfanın önizlemesini oluşturmak için genellikle kendi tarayıcılarını (scraper’larını) kullanır. Bu scraper’lar, genellikle JavaScript’i tam olarak çalıştırmaz veya beklenen şekilde işlemez. Bu da, paylaşılan bağlantıların boş başlıklar, eksik açıklamalar veya yanlış resimlerle görünmesine neden olabilir, bu da sosyal medya pazarlaması ve paylaşılabilirliği açısından olumsuz bir etki yaratır.
Önceden Oluşturmanın Çözümü
Önceden oluşturma (prerendering), bu sorunlara zarif bir çözüm sunar. Uygulamanızın belirli rotalarını derleme (build) zamanında statik HTML dosyalarına dönüştürerek çalışır. Yani, her bir önceden oluşturulmuş rota için, JavaScript çalışmadan önce bile içeriği dolu olan ayrı bir HTML dosyası oluşturulur.
* SEO için: Arama motoru tarayıcıları, doğrudan içeriği dolu HTML dosyalarını görür ve dizine ekler.
* Performans için: Kullanıcılar, JavaScript’in yüklenmesini beklemeden anında içeriği görür. Bu, FCP süresini önemli ölçüde iyileştirir. JavaScript daha sonra yüklenir ve uygulamanın etkileşimli hale gelmesini sağlar (hidrasyon).
* Sosyal Medya için: Sosyal medya scraper’ları, zengin meta etiketleri ve doğru içeriğe sahip HTML dosyalarını okuyabilir, böylece paylaşımlarınız doğru şekilde görünür.
Önceden Oluşturma (Prerendering) Nedir?
Önceden oluşturma, bir web uygulamasının belirli rotalarının statik HTML dosyalarına dönüştürülmesi işlemidir. Bu işlem, uygulamanın derleme aşamasında gerçekleşir. Bir tarayıcı ortamı (genellikle Headless Chrome gibi bir başsız tarayıcı) kullanılarak belirtilen rotalar ziyaret edilir, sayfa tamamen yüklendikten sonra oluşturulan HTML çıktısı alınır ve statik bir dosya olarak kaydedilir.
SSR (Sunucu Taraflı Oluşturma) ile Farkı
Önceden oluşturma, genellikle Sunucu Taraflı Oluşturma (SSR) ile karıştırılır, ancak aralarında önemli farklar vardır:
* SSR (Server-Side Rendering): Her bir kullanıcı isteği için sunucuda sayfa oluşturulur. Bu, dinamik ve kullanıcıya özel içerik için idealdir. Ancak, sunucu tarafında ek yük ve daha karmaşık bir kurulum gerektirir.
* Prerendering: Uygulama derleme zamanında (build time) yalnızca belirli rotalar için statik HTML dosyaları oluşturulur. Bu dosyalar daha sonra bir CDN veya basit bir statik dosya sunucusu üzerinden sunulur. Sunucu tarafında ek bir işlem yükü yoktur.
Ne Zaman Hangisini Kullanmalı?
* Prerendering: İçeriği çoğunlukla statik olan, nadiren değişen veya kişiselleştirme gerektirmeyen sayfalar (hakkımızda, iletişim, blog gönderileri, ürün sayfaları gibi) için mükemmeldir. Kurulumu daha basittir ve daha ucuz barındırma seçenekleri sunar.
* SSR: İçeriği sıkça değişen, kullanıcıya özel dinamik veriler içeren veya çok sayıda rotaya sahip uygulamalar (sosyal medya akışları, e-ticaret sepetleri, kullanıcı panelleri gibi) için daha uygundur.
Prerender-SPA-Plugin’e Giriş
prerender-spa-plugin, Vue.js (veya herhangi bir SPA framework’ü) uygulamalarını derleme zamanında önceden oluşturmak için tasarlanmış bir Webpack eklentisidir. Bu eklenti, Headless Chrome’u (Puppeteer aracılığıyla) kullanarak uygulamanızın belirtilen rotalarını ziyaret eder, JavaScript çalıştırıldıktan sonra ortaya çıkan HTML’yi yakalar ve bunu statik HTML dosyaları olarak kaydeder.
prerender-spa-plugin v3 sürümü, Puppeteer tabanlı bir render motoru kullanır. Bu, modern JavaScript özelliklerini ve tarayıcı davranışlarını daha iyi desteklemesini sağlar. Ayrıca, daha esnek konfigürasyon seçenekleri ve hata ayıklama yetenekleri sunar.
Vue.js Projesinde Kurulum ve Temel Yapılandırma
Standart bir Vue CLI projesinde prerender-spa-plugin‘i entegre etmek oldukça basittir.
1. Kurulum
Öncelikle, eklentiyi projenize geliştirme bağımlılığı olarak yüklemeniz gerekir:
npm install prerender-spa-plugin@^3.0.0 --save-dev
veya
yarn add prerender-spa-plugin@^3.0.0 --dev
@^3.0.0 eklemek, özellikle v3 sürümünü yüklemenizi sağlar, çünkü v2 ile v3 arasında bazı API farklılıkları bulunmaktadır.
2. Vue.config.js Dosyasını Yapılandırma
Vue CLI, Webpack yapılandırmasını vue.config.js dosyası aracılığıyla özelleştirmenize olanak tanır. Bu dosyada, prerender-spa-plugin‘i Webpack eklentileri listesine ekleyeceğiz. Eğer vue.config.js dosyanız yoksa, projenizin kök dizininde oluşturun.
// vue.config.js
const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
module.exports = {
// Vue CLI'nin kendi Webpack yapılandırmasını genişletmek için configureWebpack kullanırız.
configureWebpack: () => {
if (process.env.NODE_ENV !== 'production') return {}; // Sadece production build'ında çalıştır
return {
plugins: [
new PrerenderSPAPlugin({
// prerendered dosyalarının kaydedileceği dizin
staticDir: path.resolve(__dirname, 'dist'),
// Önceden oluşturulacak rotalar
routes: ['/', '/hakkimizda', '/iletisim'],
// Renderer yapılandırması (Puppeteer varsayılan olarak kullanılır)
renderer: new PrerenderSPAPlugin.PuppeteerRenderer({
// Sayfa yüklendikten sonra belirli bir DOM olayını beklemek için
// renderAfterDocumentEvent: 'render-ready',
// Sayfa yüklendikten sonra belirli bir öğenin var olmasını beklemek için
// renderAfterElementExists: '#app',
// Sayfa yüklendikten sonra belirli bir süre beklemek için (milisaniye cinsinden)
renderAfterTime: 5000, // Örnek: 5 saniye bekle
// Puppeteer'a özel argümanlar
args: ['--no-sandbox', '--disable-setuid-sandbox'],
// Headless modda çalıştır (varsayılan: true)
// headless: false, // Hata ayıklama için false yapılabilir
})
})
]
};
}
};
Açıklama:
* path.resolve(__dirname, 'dist'): staticDir seçeneği, önceden oluşturulmuş HTML dosyalarının kaydedileceği dizini belirtir. Vue CLI’nin varsayılan çıktı dizini dist olduğundan, bu yolu kullanırız.
* routes: ['/', '/hakkimizda', '/iletisim']: Bu, önceden oluşturulmasını istediğiniz URL yollarının bir dizisidir. Her bir rota için ayrı bir HTML dosyası oluşturulacaktır (örneğin, /dist/index.html, /dist/hakkimizda/index.html, /dist/iletisim/index.html).
* renderer: new PrerenderSPAPlugin.PuppeteerRenderer({...}): Bu, eklentinin sayfaları nasıl oluşturacağını yapılandırdığımız yerdir. PuppeteerRenderer varsayılan ve önerilen render motorudur.
* renderAfterTime: 5000: Bu, sayfanın tamamen yüklendiğinden emin olmak için kritik bir seçenektir. Uygulamanızın tüm JavaScript’ini çalıştırması ve veri çekme işlemlerini tamamlaması için yeterli bir süre tanır. Eğer verileriniz asenkron olarak yükleniyorsa, bu süreyi artırmanız gerekebilir. Alternatif olarak, renderAfterDocumentEvent veya renderAfterElementExists seçeneklerini kullanabilirsiniz.
* args: ['--no-sandbox', '--disable-setuid-sandbox']: Özellikle CI/CD ortamlarında veya Linux sunucularında Puppeteer’ın doğru çalışması için bu argümanlar genellikle gereklidir. Güvenlik nedeniyle --no-sandbox kullanılması tavsiye edilir.
Bu yapılandırma ile, npm run build komutunu çalıştırdığınızda, Webpack uygulamanızı derleyecek ve ardından prerender-spa-plugin devreye girerek belirtilen rotalar için statik HTML dosyalarını dist dizinine kaydedecektir.
Gelişmiş Yapılandırma Seçenekleri
prerender-spa-plugin v3, daha karmaşık senaryolar için bir dizi gelişmiş yapılandırma seçeneği sunar.
Renderer Seçenekleri (PrerenderSPAPlugin.PuppeteerRenderer)
* renderAfterDocumentEvent: 'my-custom-event': Uygulamanızda belirli bir DOM olayını tetikledikten sonra prerendering’in bitmesini bekler. Örneğin, Vue uygulamanız tüm verileri yükledikten sonra document.dispatchEvent(new Event('render-ready')) şeklinde bir olay tetikleyebilirsiniz. Bu, renderAfterTime‘dan daha güvenilir bir yöntemdir.
* renderAfterElementExists: '#app-root' veya renderAfterElementExists: '.my-content-loaded-class': Belirli bir DOM öğesinin sayfada görünmesini bekler. Bu, içeriğin yüklendiğini gösteren bir elementiniz olduğunda kullanışlıdır.
* maxAttempts: 3: Bir rota için oluşturma işlemi başarısız olursa kaç kez yeniden deneneceğini belirtir.
* timeout: 60000: Bir rotanın oluşturulması için maksimum bekleme süresi (milisaniye). Varsayılan 60 saniyedir.
* headless: true/false: Puppeteer’ın başsız modda (arka planda) mı yoksa görsel bir pencerede mi çalışacağını belirler. false olarak ayarlamak, hata ayıklama sırasında ne olduğunu görmenizi sağlar.
* inject: { foo: 'bar' }: Prerender edilen sayfaya global değişkenler enjekte eder. Bu değişkenlere window.foo gibi erişilebilir. Bu, prerender sırasında uygulamanızın davranışını değiştirmek için kullanılabilir.
* skipThirdPartyRequests: true: Performansı artırmak için üçüncü taraf isteklerini (örneğin, CDN’lerden gelen fontlar, analitik betikleri) engeller. Bu, prerendering süresini kısaltabilir.
* viewport: { width: 1280, height: 800 }: Puppeteer tarafından kullanılan viewport boyutlarını ayarlar.
Genel Plugin Seçenekleri
* postProcess: (context) => { ... }: Prerendered HTML üzerinde son işlem yapmak için kullanılır. context nesnesi html, route, originalRoute, outputPath gibi bilgileri içerir. Örneğin, belirli script etiketlerini kaldırmak veya ek meta etiketleri eklemek için kullanılabilir.
postProcess: (context) => {
// Google Analytics scriptini kaldır
context.html = context.html.replace(/');
return context;
}
* minify: { ... }: Prerendered HTML’yi sıkıştırmak için html-minifier seçeneklerini kullanır. Bu, dosya boyutunu küçültür.
minify: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
decodeEntities: true,
keepClosingSlash: true,
sortAttributes: true
}
Pratik Örnek Uygulama
Şimdi, basit bir Vue.js uygulaması üzerinde prerender-spa-plugin‘in nasıl çalıştığını adım adım görelim.
1. Vue Projesi Oluşturma
Eğer henüz bir Vue projeniz yoksa, Vue CLI ile yeni bir proje oluşturun:
vue create my-prerender-app
cd my-prerender-app
Router’ı (Vue Router) eklemeyi unutmayın.
2. Basit Bileşenler ve Rotalar Oluşturma
src/views dizininde veya benzer bir yerde birkaç basit bileşen oluşturalım:
src/views/Home.vue
Uygulamamızın ana sayfası.
Hakkımızda |
İletişim
src/views/About.vue
Bu, şirketimiz hakkında bilgi veren sayfadır.
src/views/Contact.vue
Bizimle iletişime geçmek için bu sayfayı kullanın.
src/router/index.js (Vue Router yapılandırması)
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import About from '../views/About.vue';
import Contact from '../views/Contact.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/hakkimizda',
name: 'About',
component: About
},
{
path: '/iletisim',
name: 'Contact',
component: Contact
}
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
3. prerender-spa-plugin Kurulumu ve Yapılandırması
Yukarıdaki kurulum adımlarını izleyerek prerender-spa-plugin‘i yükleyin ve vue.config.js dosyanızı yapılandırın.
// vue.config.js
const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
module.exports = {
configureWebpack: () => {
if (process.env.NODE_ENV !== 'production') return {};
return {
plugins: [
new PrerenderSPAPlugin({
staticDir: path.resolve(__dirname, 'dist'),
routes: ['/', '/hakkimizda', '/iletisim'], // Oluşturduğumuz rotalar
renderer: new PrerenderSPAPlugin.PuppeteerRenderer({
renderAfterTime: 5000,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
})
})
]
};
}
};
4. Uygulamayı Derleme
Şimdi uygulamayı derleyin:
npm run build
Derleme işlemi tamamlandıktan sonra, dist klasörünü inceleyin. Şunları görmelisiniz:
* dist/index.html (Ana sayfa için)
* dist/hakkimizda/index.html (Hakkımızda sayfası için)
* dist/iletisim/index.html (İletişim sayfası için)
Bu HTML dosyalarını bir metin düzenleyici ile açtığınızda, içlerinde ilgili Vue bileşenlerinin statik HTML içeriğini göreceksiniz. Örneğin, dist/hakkimizda/index.html dosyasının içeriği şöyle bir şey içerecektir:
My Prerender App
Bu, şirketimiz hakkında bilgi veren sayfadır.
div id="app" etiketinin içinde artık uygulamanın içeriği yer almaktadır. Bu, arama motorlarının ve sosyal medya scraper’larının doğrudan okuyabileceği statik HTML’dir. JavaScript yüklendikten sonra Vue.js, bu önceden oluşturulmuş DOM üzerinde “hidrasyon” yaparak uygulamayı etkileşimli hale getirecektir.
En İyi Uygulamalar ve Dikkat Edilmesi Gerekenler
prerender-spa-plugin kullanırken dikkate almanız gereken bazı en iyi uygulamalar ve potansiyel tuzaklar vardır:
Dinamik Rotalar ve Veri Çekme
* Sabit Rotalar İçin Ideal: Prerendering, önceden bilinen ve nispeten statik içerik sunan rotalar için en uygundur. Örneğin, bir blog uygulamasında her blog gönderisi için ayrı bir rota (örneğin /blog/post-1, /blog/post-2) varsa, bu rotaların her birini routes dizisine manuel olarak eklemeniz gerekir.
* API Verilerinin Beklenmesi: Uygulamanız API’lerden veri çekiyorsa, prerendering işlemi bu veriler yüklendikten sonra tamamlanmalıdır. Aksi takdirde, oluşturulan HTML boş içerik içerebilir. renderAfterTime, renderAfterDocumentEvent veya renderAfterElementExists seçeneklerini kullanarak tüm verilerin yüklenmesini beklediğinizden emin olun. renderAfterDocumentEvent genellikle en güvenilir yöntemdir; tüm asenkron işlemler bittikten sonra özel bir olay tetikleyebilirsiniz.
* Sunucu Tarafında Kullanılan Veri: Bazı durumlarda, prerendering sırasında uygulamanızın sunucu tarafında kullanılan verileri (örneğin, API anahtarları) kullanması gerekebilir. inject seçeneği ile bu tür verileri sayfaya enjekte edebilirsiniz, ancak hassas bilgileri doğrudan ifşa etmemeye dikkat edin.
Client-Side Hydration (Müşteri Tarafı Hidrasyon)
* Tutarlılık: Prerendered HTML, uygulamanızın istemci tarafında oluşturduğu DOM yapısıyla birebir aynı olmalıdır. Küçük farklılıklar bile Vue.js’nin hidrasyon işlemini bozabilir ve uygulamanın yeniden oluşturulmasına neden olabilir, bu da performans avantajını ortadan kaldırır. Özellikle v-if, v-show gibi direktiflerin prerender sırasında nasıl davrandığına dikkat edin.
* window Nesnesi: Prerendering, Node.js ortamında (Puppeteer aracılığıyla) gerçekleştiği için, window veya document gibi tarayıcıya özgü global nesnelere doğrudan erişmeye çalışan kodlar hata verebilir. Bu tür kodları yalnızca tarayıcı ortamında çalışacak şekilde koşullu olarak sarmalayın.
Derleme Süresi ve Kaynak Tüketimi
* Artan Derleme Süresi: Her bir rotanın Headless Chrome’da oluşturulması zaman alacaktır. Çok sayıda rotanız varsa, derleme süresi önemli ölçüde uzayabilir.
* Bellek Tüketimi: Puppeteer, özellikle çok sayıda rota için veya karmaşık sayfalar oluştururken önemli miktarda bellek tüketebilir. CI/CD ortamlarında bellek limitlerini göz önünde bulundurun.
* Sadece Üretim Ortamı: configureWebpack içinde process.env.NODE_ENV !== 'production' kontrolünü kullanarak prerender-spa-plugin‘in yalnızca üretim derlemelerinde çalışmasını sağlamak iyi bir uygulamadır. Geliştirme sırasında prerendering’e ihtiyacınız yoktur.
Hata Ayıklama
* headless: false: Hata ayıklama sırasında PuppeteerRenderer yapılandırmasında headless: false yaparak Puppeteer’ın görsel bir pencerede çalışmasını sağlayabilirsiniz. Bu, bir sayfanın neden doğru şekilde oluşturulmadığını veya belirli bir öğenin neden bulunamadığını görmenize yardımcı olur.
* console.log: Prerendering sırasında tarayıcı konsoluna yazılan mesajlar, derleme çıktısında görünecektir. Bu, sorunları teşhis etmek için kullanılabilir.
Deployment (Dağıtım)
* Statik Sunucular: Prerendered bir Vue.js uygulaması, herhangi bir statik dosya sunucusu (Nginx, Apache, Netlify, Vercel, Firebase Hosting, GitHub Pages vb.) üzerinden kolayca dağıtılabilir. dist klasöründeki tüm dosyaları sunucuya yüklemeniz yeterlidir.
* URL Yapısı: Prerender-spa-plugin, /hakkimizda rotası için /hakkimizda/index.html şeklinde bir dizin yapısı oluşturur. Bu, birçok statik sunucunun varsayılan olarak /hakkimizda isteğini /hakkimizda/index.html‘e yönlendirmesiyle uyumludur.
Sınırlamalar
prerender-spa-plugin güçlü bir araç olsa da, her senaryo için uygun değildir:
* Yüksek Derecede Dinamik İçerik: Her kullanıcı için farklı veya sürekli değişen içerik sunan uygulamalar için prerendering uygun değildir. Bu tür durumlar için SSR veya istemci tarafında dinamik yükleme daha iyi seçeneklerdir.
* Çok Sayıda Dinamik Rota: Yüz binlerce ürün sayfası gibi çok sayıda dinamik rotaya sahip bir e-ticaret sitesi için tüm rotaları derleme zamanında prerender etmek pratik veya verimli olmayabilir.
* Etkileşimden Sonra Değişen İçerik: Eğer sayfanın önemli bir kısmı kullanıcı etkileşiminden sonra (örneğin, bir form gönderildikten sonra) değişiyorsa, prerendered HTML bu değişiklikleri yansıtmayacaktır.
Sonuç
prerender-spa-plugin v3, Vue.js uygulamalarınızın SEO performansını, ilk yükleme hızını ve sosyal medya paylaşımlarını önemli ölçüde iyileştirmek için harika bir araçtır. Özellikle içeriği nispeten statik olan bloglar, kurumsal web siteleri, ürün sayfaları veya pazarlama odaklı açılış sayfaları gibi senaryolar için idealdir.
Bu eklentiyi kullanarak, uygulamanızın en önemli rotalarını derleme zamanında statik, içeriği dolu HTML dosyalarına dönüştürebilirsiniz. Bu sayede, arama motorları içeriğinizi kolayca dizine ekleyebilir, kullanıcılar boş bir ekran yerine anında içerikle karşılaşır ve sosyal medya paylaşımlarınız daha çekici hale gelir. prerender-spa-plugin‘in esnek yapılandırma seçenekleri sayesinde, uygulamanızın özel ihtiyaçlarına göre prerendering sürecini optimize edebilirsiniz. Doğru kullanıldığında, bu eklenti modern SPA geliştirme sürecinde önemli bir performans ve erişilebilirlik artışı sağlayabilir.