Ana içeriğe geç

Hızlı Başlangıç

Hızlı Başlangıç

Merhaba! Fastify'ı incelediğiniz için teşekkürler!

Bu belge, framework ve özelliklerine nazik bir giriş yapmayı amaçlamaktadır. Diğer doküman bölümüne bağlantılar ve örneklerle birlikte temel bir önsöz niteliğindedir.

Haydi başlayalım!

Kurulum

npm ile yükleyin:

npm i fastify

yarn ile yükleyin:

yarn add fastify

İlk sunucunuz

İlk sunucumuzu yazalım:

// Framework'ü isteyin ve örneğini oluşturun

// ESM
import Fastify from 'fastify'

const fastify = Fastify({
logger: true
})
// CommonJs
const fastify = require('fastify')({
logger: true
})

// Bir route (yol) tanımlayın
fastify.get('/', function (request, reply) {
reply.send({ hello: 'world' })
})

// Sunucuyu çalıştırın!
fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Sunucu artık ${address} üzerinde dinliyor
})

ECMAScript Modüllerini (ESM) projenizde kullanıyorsanız, "type": "module" ifadesini package.json dosyanıza eklediğinizden emin olun.

{
"type": "module"
}

async/await kullanmayı mı tercih ediyorsunuz? Fastify bunu kutudan çıkar çıkmaz destekler.

// ESM
import Fastify from 'fastify'

const fastify = Fastify({
logger: true
})
// CommonJs
const fastify = require('fastify')({
logger: true
})

fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})

/**
* Sunucuyu çalıştırın!
*/
const start = async () => {
try {
await fastify.listen({ port: 3000 })
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()

Harika, bu kolaydı.

Ne yazık ki, karmaşık bir uygulama yazmak bu örnekten çok daha fazla kod gerektirir. Yeni bir uygulama oluştururken yaşanan klasik bir sorun, birden fazla dosyayı, asenkron başlatmayı ve kodunuzun mimarisini nasıl yöneteceğinizdir.

Fastify, yukarıda belirtilen tüm sorunları ve daha fazlasını çözmeye yardımcı olacak kolay bir platform sunmaktadır!

Not

Yukarıdaki örnekler ve bu belgede sonraki örnekler, yalnızca localhost 127.0.0.1 arayüzünde dinleyecek şekilde varsayılan olarak ayarlanmıştır. Tüm mevcut IPv4 arayüzlerinde dinlemek için örneği şu şekilde düzenleyebilirsiniz:

fastify.listen({ port: 3000, host: '0.0.0.0' }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`sunucu ${address} üzerinde dinliyor`)
})

Benzer şekilde, yalnızca yerel bağlantıları kabul etmek için ::1 belirtin. Ya da tüm IPv6 adreslerinde bağlantıları kabul etmek için :: belirtin ve işletim sistemi destekliyorsa, tüm IPv4 adreslerinde de bağlantıları kabul edin.

Docker (veya başka bir tür) konteynerine dağıtım yaparken 0.0.0.0 veya :: kullanmak, uygulamayı dışa aktarmanın en kolay yöntemidir.

İlk eklentiniz

JavaScript'te her şey bir nesne olduğu gibi, Fastify'da her şey bir eklentidir.

Buna derinlemesine inmeye başlamadan önce, nasıl çalıştığını görelim!

Temel sunucumuzu tanımlayalım, ancak route'u giriş noktasının içine değil, bir dış dosyada tanımlayacağız (route declaration belgesine göz atın).

// ESM
import Fastify from 'fastify'
import firstRoute from './our-first-route.js'
/**
* @type {import('fastify').FastifyInstance} Fastify örneği
*/
const fastify = Fastify({
logger: true
})

fastify.register(firstRoute)

fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Sunucu artık ${address} üzerinde dinliyor
})
// CommonJs
/**
* @type {import('fastify').FastifyInstance} Fastify örneği
*/
const fastify = require('fastify')({
logger: true
})

fastify.register(require('./our-first-route'))

fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Sunucu artık ${address} üzerinde dinliyor
})
// our-first-route.js

/**
* Route'ları kapsülleme
* @param {FastifyInstance} fastify Kapsüllenmiş Fastify Örneği
* @param {Object} options eklenti seçenekleri, https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options adresine bakın
*/
async function routes (fastify, options) {
fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})
}

// ESM
export default routes;

// CommonJs
module.exports = routes

Bu örnekte, Fastify framework'ünün temelini oluşturan register API'sini kullandık. Route'ları, eklentileri vb. eklemenin tek yoludur.

Bu kılavuzun başında, Fastify'ın uygulamanızın asenkron başlatılmasına yardımcı olan bir temel sağladığını belirtmiştik. Bu neden önemlidir?

Veri depolama işlemini yönetmek için bir veritabanı bağlantısına ihtiyaç duyulan bir senaryoyu düşünün. Veritabanı bağlantısının, sunucu bağlantıları kabul etmeden önce mevcut olması gerekmektedir. Bu sorunu nasıl çözeriz?

Tipik bir çözüm, karmaşık bir geridönüş veya vaatler kullanmaktır - bu sistem, framework API'sini diğer kütüphaneler ve uygulama koduyla karıştıracaktır.

Fastify, bunu minimum çabayla içsel olarak yönetmektedir!

Yukarıdaki örneği bir veritabanı bağlantısıyla yeniden yazalım.

Öncelikle fastify-plugin ve @fastify/mongodb'yi yükleyin:

npm i fastify-plugin @fastify/mongodb

server.js

// ESM
import Fastify from 'fastify'
import dbConnector from './our-db-connector.js'
import firstRoute from './our-first-route.js'

/**
* @type {import('fastify').FastifyInstance} Fastify örneği
*/
const fastify = Fastify({
logger: true
})
fastify.register(dbConnector)
fastify.register(firstRoute)

fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Sunucu artık ${address} üzerinde dinliyor
})
// CommonJs
/**
* @type {import('fastify').FastifyInstance} Fastify örneği
*/
const fastify = require('fastify')({
logger: true
})

fastify.register(require('./our-db-connector'))
fastify.register(require('./our-first-route'))

fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Sunucu artık ${address} üzerinde dinliyor
})

our-db-connector.js

// ESM
import fastifyPlugin from 'fastify-plugin'
import fastifyMongo from '@fastify/mongodb'

/**
* @param {FastifyInstance} fastify
* @param {Object} options
*/
async function dbConnector (fastify, options) {
fastify.register(fastifyMongo, {
url: 'mongodb://localhost:27017/test_database'
})
}

// Eklenti fonksiyonunu fastify-plugin ile sarmak, eklenti içinde tanımlanan dekoratörleri
// ve kancaları ana kapsama açar.
export default fastifyPlugin(dbConnector)

// CommonJs
/**
* @type {import('fastify-plugin').FastifyPlugin}
*/
const fastifyPlugin = require('fastify-plugin')


/**
* MongoDB veritabanına bağlanır
* @param {FastifyInstance} fastify Kapsüllenmiş Fastify Örneği
* @param {Object} options eklenti seçenekleri, https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options adresine bakın
*/
async function dbConnector (fastify, options) {
fastify.register(require('@fastify/mongodb'), {
url: 'mongodb://localhost:27017/test_database'
})
}

// Eklenti fonksiyonunu fastify-plugin ile sarmak, eklenti içinde tanımlanan dekoratörleri
// ve kancaları ana kapsama açar.
module.exports = fastifyPlugin(dbConnector)

our-first-route.js

/**
* Kapsüllenmiş route'ları sunan bir eklenti
* @param {FastifyInstance} fastify kapsüllenmiş fastify örneği
* @param {Object} options eklenti seçenekleri, https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options adresine bakın
*/
async function routes (fastify, options) {
const collection = fastify.mongo.db.collection('test_collection')

fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})

fastify.get('/animals', async (request, reply) => {
const result = await collection.find().toArray()
if (result.length === 0) {
throw new Error('Hiçbir belge bulunamadı')
}
return result
})

fastify.get('/animals/:animal', async (request, reply) => {
const result = await collection.findOne({ animal: request.params.animal })
if (!result) {
throw new Error('Geçersiz değer')
}
return result
})

const animalBodyJsonSchema = {
type: 'object',
required: ['animal'],
properties: {
animal: { type: 'string' },
},
}

const schema = {
body: animalBodyJsonSchema,
}

fastify.post('/animals', { schema }, async (request, reply) => {
// Müşteri tarafından gönderilen veriyi almak için `request.body` nesnesini kullanabiliriz
const result = await collection.insertOne({ animal: request.body.animal })
return result
})
}

module.exports = routes

Vay, bu hızlıydı!

Şimdi bazı yeni kavramlar tanıttığımız için burada neler yaptığımızı özetleyelim.

Gördüğünüz gibi, hem veritabanı bağlayıcısı hem de route'ların kaydı için register kullandık.

Bu, Fastify'ın en iyi özelliklerinden biridir; eklentilerinizi tanımladığınız sırayla yükleyecek ve mevcut olan her eklenti yüklendiğinde, bir sonraki eklentiyi yalnızca yükleyecektir. Bu şekilde, veritabanı bağlayıcısını ilk eklentide kaydedebilir ve ikinci eklentide kullanabiliriz (plugin kapsamını anlamak için buraya okuyun).

Eklenti yükleme, fastify.listen(), fastify.inject() veya fastify.ready() çağrıldığında başlar.

MongoDB eklentisi, Fastify örneğine özel nesneler eklemek için decorate API'sini kullanır ve bu nesneleri her yerde kullanılabilir hale getirir. Kolay kod yeniden kullanımı sağlamak ve kod veya mantık tekrarını azaltmak için bu API'nin kullanılması teşvik edilmektedir.

Fastify eklentilerinin nasıl çalıştığını, yeni eklentiler geliştirmeyi ve uygulamanın asenkron başlatılmasıyla ilgili karmaşıklıklarla başa çıkmak için Fastify API'sinin tamamını nasıl kullanacağınıza dair daha fazla bilgi edinmek için eklenti rehberine göz atın.

Eklentilerinizin Yükleme Sırası

Uygulamanızın tutarlı ve tahmin edilebilir bir davranış sergilemesini sağlamak için, kodunuzu her zaman aşağıda gösterildiği gibi yüklemenizi öneririz:

└── eklentiler (Fastify ekosisteminden)
└── kendi eklentileriniz (kendi özel eklentileriniz)
└── dekoratörler
└── kancalar
└── hizmetleriniz

Bu şekilde, mevcut kapsamda tanımlanan tüm özelliklere her zaman erişiminiz olacaktır.

Daha önce tartışıldığı gibi, Fastify, uygulamanızı tekil ve bağımsız hizmetler olarak oluşturmanıza yardımcı olmak için sağlam bir kapsülleme modeli sunar. Sadece belirli bir route alt kümesi için bir eklenti kaydetmek istiyorsanız, yukarıdaki yapıyı tekrar etmeniz yeterlidir.

└── eklentiler (Fastify ekosisteminden)
└── kendi eklentileriniz (kendi özel eklentileriniz)
└── dekoratörler
└── kancalar
└── hizmetleriniz

└── hizmet A
│ └── eklentiler (Fastify ekosisteminden)
│ └── kendi eklentileriniz (kendi özel eklentileriniz)
│ └── dekoratörler
│ └── kancalar
│ └── hizmetleriniz

└── hizmet B
└── eklentiler (Fastify ekosisteminden)
└── kendi eklentileriniz (kendi özel eklentileriniz)
└── dekoratörler
└── kancalar
└── hizmetleriniz

Verilerinizi Doğrulayın

Veri doğrulama son derece önemlidir ve framework'ün temel bir kavramıdır.

Gelen talepleri doğrulamak için Fastify, JSON Şeması kullanır.

Route'lar için doğrulamayı gösteren bir örneğe bakalım:

/**
* @type {import('fastify').RouteShorthandOptions}
* @const
*/
const opts = {
schema: {
body: {
type: 'object',
properties: {
someKey: { type: 'string' },
someOtherKey: { type: 'number' }
}
}
}
}

fastify.post('/', opts, async (request, reply) => {
return { hello: 'world' }
})

Bu örnek, route'a bir options nesnesi geçirmenin nasıl yapılacağını gösterir; bu nesne, route, body, querystring, params ve headers için tüm şemaları içeren bir schema anahtarını kabul eder.

Daha fazla bilgi edinmek için Doğrulama ve Serileştirme bağlantısına göz atın.

Verilerinizi Serileştirin

Fastify, JSON için birinci sınıf destek sunar. JSON gövdelerini ayrıştırmak ve JSON çıktısını serileştirmek için son derece optimize edilmiştir.

JSON serileştirmesini hızlandırmak için (evet, yavaştır!) aşağıdaki örnekte gösterildiği gibi şema seçeneğinin response anahtarını kullanabilirsiniz:

/**
* @type {import('fastify').RouteShorthandOptions}
* @const
*/
const opts = {
schema: {
response: {
200: {
type: 'object',
properties: {
hello: { type: 'string' }
}
}
}
}
}

fastify.get('/', opts, async (request, reply) => {
return { hello: 'world' }
})

Şemayı belirttiğinizde, serileştirmeyi 2-3 kat hızlandırabilirsiniz. Bu ayrıca, potansiyel olarak hassas verilerin sızdırılmasını önlemeye yardımcı olur, çünkü Fastify yalnızca yanıt şemasında bulunan verileri serileştirecektir. Daha fazla bilgi edinmek için Doğrulama ve Serileştirme bağlantısına göz atın.

İstek Yüklerini Ayrıştırma

Fastify, 'application/json' ve 'text/plain' istek yüklerini doğal olarak ayrıştırır ve sonuç, Fastify request nesnesinden request.body içinde erişilebilir.

Aşağıdaki örnek, bir isteğin ayrıştırılmış gövdesini istemciye geri döner:

/**
* @type {import('fastify').RouteShorthandOptions}
*/
const opts = {}
fastify.post('/', opts, async (request, reply) => {
return request.body
})

Fastify'ın varsayılan ayrıştırma işlevselliği ve diğer içerik türlerini desteklemek hakkında daha fazla bilgi edinmek için Content-Type Ayrıştırıcı belgesine göz atın.

Sunucunuzu Genişletin

Fastify, son derece genişletilebilir ve minimal olacak şekilde tasarlanmıştır; bizler sade bir framework'ün harika uygulamalar oluşturmak için yeterli olduğuna inanıyoruz.

Diğer bir deyişle, Fastify "pil dahil" bir framework değildir ve harika bir ekosisteme dayanır!

Sunucunuzu CLI'dan Test Edin

Fastify, bir test framework'ü sunmaz, ancak Fastify'ın özelliklerini ve mimarisini kullanan testlerinizi yazmanız için bir yol öneririz.

Daha fazla bilgi için test belgeleri bağlantısına göz atın!

Sunucunuzu CLI'dan Çalıştırın

Fastify, ayrıca fastify-cli sayesinde CLI entegrasyonuna sahiptir.

Öncelikle fastify-cli'yi yükleyin:

npm i fastify-cli

Ayrıca -g ile küresel olarak da yükleyebilirsiniz.

Ardından, package.json dosyanıza aşağıdaki satırları ekleyin:

{
"scripts": {
"start": "fastify start server.js"
}
}

Ve sunucu dosyanızı/da oluşturun:

// server.js
'use strict'

module.exports = async function (fastify, opts) {
fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})
}

Ardından sunucunuzu şu şekilde çalıştırın:

npm start

Slaytlar ve Videolar