Ana içeriğe geç

V5 Göç Kılavuzu

V5 Göç Kılavuzu

Bu kılavuz, Fastify v4'ten v5'e geçişe yardımcı olmak amacıyla hazırlanmıştır.

V5'e geçmeden önce, lütfen v4'teki tüm kullanım dışı uyarılarını giderdiğinizden emin olun. Tüm v4 kullanım dışı özellikleri kaldırılmıştır ve güncellemeden sonra çalışmayacaktır.

Uzun Süreli Destek Dönemi

Fastify v5, yalnızca Node.js v20+ sürümünü destekleyecektir. Eğer eski bir Node.js sürümü kullanıyorsanız, Fastify v5'i kullanmak için daha yeni bir sürüme güncellemeniz gerekecektir.

Fastify v4, 30 Haziran 2025'e kadar desteklenmeye devam edecektir. Eğer güncelleme yapamıyorsanız, HeroDevs'ten bir kullanım sonu destek planı satın almayı düşünmelisiniz.

Neden Node.js v20?

Fastify v5, node:test için daha iyi destek gibi v18 ile karşılaştırıldığında önemli farklılıklar sunduğu için yalnızca Node.js v20+ sürümünü destekleyecektir. Bu, daha iyi bir geliştirici deneyimi sunmamızı ve bakım süreçlerini kolaylaştırmamızı sağlar.

Node.js v18, 30 Nisan 2025'te Uzun Süreli Destek'ten ayrılacak, bu nedenle v20'ye geçmeyi planlamalısınız.

Kırıcı Değişiklikler

tehlike

Aşağıda belirtilen değişiklikler, Fastify v5'te uygulamanızın davranışını etkileyebilir. Öğrenmek için dikkatli olun!

querystring, params ve body ile yanıt şemaları için tam JSON Şeması artık gereklidir

V5 ile birlikte, Fastify, querystring, params ve body şeması için tam bir JSON şeması gerektirecektir. jsonShortHand seçeneğinin de kaldırıldığını unutmayın.

Varsayılan JSON Şeması doğrulayıcısı kullanılıyorsa, querystring, params, body ve response şemaları için tam bir JSON şeması sağlamanız gerekecektir; bu şemalar, type özelliğini de içermelidir.

// v4
fastify.get('/route', {
schema: {
querystring: {
name: { type: 'string' }
}
}
}, (req, reply) => {
reply.send({ hello: req.query.name });
});
// v5
fastify.get('/route', {
schema: {
querystring: {
type: 'object',
properties: {
name: { type: 'string' }
},
required: ['name']
}
}
}, (req, reply) => {
reply.send({ hello: req.query.name });
});

Daha fazla detay için #5586 bakabilirsiniz.

bilgi

JSON Şeması doğrulayıcısını, Zod gibi farklı bir format kullanmak için geçersiz kılmak hala mümkündür; bu değişiklik de bunu kolaylaştırır.

Bu değişiklik, @fastify/swagger gibi diğer araçların entegrasyonunu kolaylaştırır.

Yeni logger oluşturucu imzası

Fastify v4'te, Fastify, logger seçeneğinde bir pino logger oluşturmak için seçenekleri ve özel bir logger örneğini kabul etti. Bu durum ciddi bir kafa karışıklığına neden oldu.

Sonuç olarak, logger seçeneği v5'te artık özel bir logger kabul etmeyecek. Özel bir logger kullanmak için, loggerInstance seçeneğini kullanmalısınız:

// v4
const logger = require('pino')();
const fastify = require('fastify')({
logger
});
// v5
const loggerInstance = require('pino')();
const fastify = require('fastify')({
loggerInstance
});

useSemicolonDelimiter varsayılan olarak false

V5 ile birlikte, Fastify örnekleri artık v4'te olduğu gibi sorgu dizesinde noktalı virgül ayırıcılarının kullanılmasını varsayılan olarak desteklemeyecektir. Bu, standart dışı bir davranıştır ve RFC 3986 ile uyumlu değildir.

Eğer hala noktalı virgülleri ayırıcı olarak kullanmak istiyorsanız, sunucu yapılandırmasında useSemicolonDelimiter: true ayarını yapabilirsiniz.

const fastify = require('fastify')({
useSemicolonDelimiter: true
});

Parametreler nesnesinin artık bir prototipi yok

v4'te, parameters nesnesinin bir prototipi vardı; bu v5'te böyle değil. Bu, parameters nesnesinde Object'dan miras alınan özelliklere, toString veya hasOwnProperty gibi, artık erişemeyeceğiniz anlamına gelir.

// v4
fastify.get('/route/:name', (req, reply) => {
console.log(req.params.hasOwnProperty('name')); // true
return { hello: req.params.name };
});
// v5
fastify.get('/route/:name', (req, reply) => {
console.log(Object.hasOwn(req.params, 'name')); // true
return { hello: req.params.name };
});

Bu, uygulamanın güvenliğini artırarak prototip kirlenmesi saldırılarına karşı güçlendirilmesini sağlar.

Tip Sağlayıcılar artık doğrulayıcı ve serileştirici şemaları arasında farklılık gösteriyor

v4'te, tip sağlayıcılar doğrulama ve serileştirme için aynı türleri içeriyordu. v5'te, tip sağlayıcıları iki ayrı türe ayrıldı: ValidatorSchema ve SerializerSchema.

@fastify/type-provider-json-schema-to-ts ve @fastify/type-provider-typebox zaten güncellendi: yeni tipleri almak için en son sürüme yükseltin. Eğer özel bir tip sağlayıcı kullanıyorsanız, aşağıdaki gibi değiştirmeniz gerekecektir:

--- a/index.ts
+++ b/index.ts
@@ -11,7 +11,8 @@ import {
import { FromSchema, FromSchemaDefaultOptions, FromSchemaOptions, JSONSchema } from 'json-schema-to-ts'

export interface JsonSchemaToTsProvider<
Options extends FromSchemaOptions = FromSchemaDefaultOptions
> extends FastifyTypeProvider {
- output: this['input'] extends JSONSchema ? FromSchema<this['input'], Options> : unknown;
+ validator: this['schema'] extends JSONSchema ? FromSchema<this['schema'], Options> : unknown;
+ serializer: this['schema'] extends JSONSchema ? FromSchema<this['schema'], Options> : unknown;
}

.listen() yönteminde değişiklikler

.listen() yönteminin çok sayıda argüman imzası kaldırılmıştır. Bu, .listen() çağrısını değişken sayıda argüman ile yapamayacağınız anlamına gelir.

// v4
fastify.listen(8000)

Şöyle olacak:

// v5
fastify.listen({ port: 8000 })

Bu, v4'te FSTDEP011 olarak zaten kullanım dışı bırakıldığından, yeni imzayı kullanmak için kodunuzu güncellemeyi çoktan yapmış olmalısınız.

Trailers'ın doğrudan döndürülmesi kaldırılmıştır

v4'te, bir handler'dan doğrudan trailers döndürebiliyordunuz. Bu, v5'te artık mümkün değildir.

// v4
fastify.get('/route', (req, reply) => {
reply.trailer('ETag', function (reply, payload) {
return 'custom-etag'
})
reply.send('')
});
// v5
fastify.get('/route', (req, reply) => {
reply.trailer('ETag', async function (reply, payload) {
return 'custom-etag'
})
reply.send('')
});

Bir geri çağırma da kullanılabilirdi. Bu, v4'te FSTDEP013 olarak zaten kullanım dışı bırakıldığı için, yeni imzayı kullanmak için kodunuzu güncellemeyi çoktan yapmış olmalısınız.

Rota tanımına daha kolay erişim

Rota tanımına erişimle ilgili tüm kullanım dışı özellikler kaldırılmış ve artık request.routeOptions üzerinden erişilmektedir.

KodAçıklamaNasıl ÇözülürTartışma
FSTDEP012Kullanım dışı bırakılmış request.context özelliğine erişmeye çalışıyorsunuz.request.routeOptions.config veya request.routeOptions.schema kullanın.#4216 #5084
FSTDEP015Kullanım dışı bırakılmış request.routeSchema özelliğine erişiyorsunuz.request.routeOptions.schema kullanın.#4470
FSTDEP016Kullanım dışı bırakılmış request.routeConfig özelliğine erişiyorsunuz.request.routeOptions.config kullanın.#4470
FSTDEP017Kullanım dışı bırakılmış request.routerPath özelliğine erişiyorsunuz.request.routeOptions.url kullanın.#4470
FSTDEP018Kullanım dışı bırakılmış request.routerMethod özelliğine erişiyorsunuz.request.routeOptions.method kullanın.#4470
FSTDEP019Kullanım dışı bırakılmış reply.context özelliğine erişiyorsunuz.reply.routeOptions.config veya reply.routeOptions.schema kullanın.#5032 #5084

Daha fazla bilgi için #5616 bakabilirsiniz.

reply.redirect() yeni bir imzaya sahiptir

reply.redirect() yönteminin yeni bir imzası vardır: reply.redirect(url: string, code?: number).

// v4
reply.redirect(301, '/new-route')

Bunu şu şekilde değiştirin:

// v5
reply.redirect('/new-route', 301)

Bu, v4'te FSTDEP021 olarak zaten kullanım dışı bırakıldığından, yeni imzayı kullanmak için kodunuzu güncellemeyi çoktan yapmış olmalısınız.

reply.sent özelliğini değiştirmek artık yasak

v4'te, reply.sent özelliğini değiştirerek yanıtın gönderilmesini engelleyebiliyordunuz. Bu, v5'te artık mümkün değildir, bunun yerine reply.hijack() kullanmalısınız.

// v4
fastify.get('/route', (req, reply) => {
reply.sent = true;
reply.raw.end('hello');
});

Bunu şu şekilde değiştirin:

// v5
fastify.get('/route', (req, reply) => {
reply.hijack();
reply.raw.end('hello');
});

Bu zaten v4'te FSTDEP010 olarak kullanım dışı bırakılmıştı, bu nedenle yeni imzayı kullanmak için kodunuzu güncellemeyi çoktan yapmış olmalısınız.

Rota sürümleme imza değişiklikleri için kısıtlamalar

Rota sürümleme kısıtlamaları için imzayı değiştirdik. version ve versioning seçenekleri kaldırılmıştır ve bunun yerine constraints seçeneğini kullanmalısınız.

KodAçıklamaNasıl ÇözülürTartışma
FSTDEP008Rota {version: "..."} seçeneği ile rota kısıtlamaları kullanıyorsunuz.{constraints: {version: "..."}} seçeneğini kullanın.#2682
FSTDEP009Sunucu {versioning: "..."} seçeneği via özel rota sürümleme stratejisi kullanıyorsunuz.{constraints: {version: "..."}} seçeneğini kullanın.#2682

HEAD rotalarının GET'ten önce kaydedilmesi gerekmektedir exposeHeadRoutes: true durumunda

exposeHeadRoutes: true olduğunda, özel HEAD rota için daha katı bir gereksinimimiz vardır.

Eğer özel bir HEAD rotası sağlıyorsanız, exposeHeadRoutes'i açıkça false yapmalısınız.

// v4
fastify.get('/route', {

}, (req, reply) => {
reply.send({ hello: 'world' });
});

fastify.head('/route', (req, reply) => {
// ...
});
// v5
fastify.get('/route', {
exposeHeadRoutes: false
}, (req, reply) => {
reply.send({ hello: 'world' });
});

fastify.head('/route', (req, reply) => {
// ...
});

veya HEAD rotasını GET'ten önce yerleştirin.

// v5
fastify.head('/route', (req, reply) => {
// ...
});

fastify.get('/route', {

}, (req, reply) => {
reply.send({ hello: 'world' });
});

Bu, #2700 içinde değiştirildi ve eski davranış v4'te FSTDEP007 olarak kullanım dışı bırakıldı.

request.connection kaldırıldı

request.connection özelliği v5'te kaldırılmıştır. Bunun yerine request.socket kullanmalısınız.

// v4
fastify.get('/route', (req, reply) => {
console.log(req.connection.remoteAddress);
return { hello: 'world' };
});
// v5
fastify.get('/route', (req, reply) => {
console.log(req.socket.remoteAddress);
return { hello: 'world' };
});

Bu, zaten v4'te FSTDEP05 olarak kullanım dışı bırakıldığı için, yeni imzayı kullanmak için kodunuzu güncellemeyi çoktan yapmış olmalısınız.

reply.getResponseTime() kaldırıldı, bunun yerine reply.elapsedTime kullanın

reply.getResponseTime() yöntemi v5'te kaldırılmıştır. Bunun yerine reply.elapsedTime kullanmalısınız.

// v4
fastify.get('/route', (req, reply) => {
console.log(reply.getResponseTime());
return { hello: 'world' };
});
// v5
fastify.get('/route', (req, reply) => {
console.log(reply.elapsedTime);
return { hello: 'world' };
});

Bu, v4'te FSTDEP20 olarak kullanım dışı bırakıldığından, yeni imzayı kullanmak için kodunuzu güncellemeyi çoktan yapmış olmalısınız.

fastify.hasRoute() artık find-my-way davranışını eşleştiriyor

fastify.hasRoute() yöntemi artık find-my-way davranışını eşleştiriyor ve rota tanımının tanımlandığı gibi geçilmesini gerektiriyor.

// v4
fastify.get('/example/:file(^\\d+).png', function (request, reply) { })

console.log(fastify.hasRoute({
method: 'GET',
url: '/example/12345.png'
})); // true
// v5

fastify.get('/example/:file(^\\d+).png', function (request, reply) { })

console.log(fastify.hasRoute({
method: 'GET',
url: '/example/:file(^\\d+).png'
})); // true

Bazı standart dışı HTTP yöntemlerinin kaldırılması

Fastify'dan aşağıdaki HTTP yöntemleri kaldırılmıştır:

  • PROPFIND
  • PROPPATCH
  • MKCOL
  • COPY
  • MOVE
  • LOCK
  • UNLOCK
  • TRACE
  • SEARCH

Artık bunları addHttpMethod yöntemi aracılığıyla geri eklemek mümkündür.

const fastify = Fastify()

// varsayılanların üzerine yeni bir http yöntemi ekleyin:
fastify.addHttpMethod('REBIND')

// bir gövde kabul eden yeni bir HTTP yöntemi ekleyin:
fastify.addHttpMethod('REBIND', { hasBody: true })

// HTTP yöntemleri listesini okumak:
fastify.supportedMethods // bir dizi döndürür

Daha fazla bilgi için #5567 bakabilirsiniz.

Dekoratörlerde referans türlerine destek kaldırıldı

Request/Reply'i referans türü (Array, Object) ile süslemek artık yasaktır; çünkü bu referans tüm istekler arasında paylaşılmaktadır.

// v4
fastify.decorateRequest('myObject', { hello: 'world' });
// v5
fastify.decorateRequest('myObject');
fastify.addHook('onRequest', async (req, reply) => {
req.myObject = { hello: 'world' };
});

ya da bir fonksiyon haline getirin

// v5
fastify.decorateRequest('myObject', () => { hello: 'world' });

ya da bir getter olarak

// v5
fastify.decorateRequest('myObject', {
getter () {
return { hello: 'world' }
}
});

Daha fazla bilgi için #5462 bakabilirsiniz.

Boş gövde ile Content-Type: application/json başlığı olan DELETE'e destek kaldırıldı

v4'te Fastify, Content-Type: application/json başlığı olan ve boş gövde ile DELETE isteklerine izin veriyordu. Bu artık v5'te izin verilmemektedir.

Daha fazla bilgi için #5419 bakabilirsiniz.

Eklentiler artık geri çağrı/promise API'sini karıştıramaz

v4'te, eklentiler geri çağrı ve promise API'sini karıştırabilir, bu da beklenmedik davranışlara yol açabilirdi. Bu artık v5'te izin verilmemektedir.

// v4
fastify.register(async function (instance, opts, done) {
done();
});
// v5
fastify.register(async function (instance, opts) {
return;
});

veya

// v5
fastify.register(function (instance, opts, done) {
done();
});

getDefaultRoute ve setDefaultRoute yöntemleri kaldırıldı

getDefaultRoute ve setDefaultRoute yöntemleri v5'te kaldırılmıştır.

Daha fazla bilgi için #4485 ve #4480 bakabilirsiniz. Bu, zaten v4'te FSTDEP014 olarak kullanım dışı bırakıldığı için, kodunuzu güncellemek için çoktan yapmak zorundasınız.

Yeni Özellikler

Diagnostic Channel desteği

Fastify v5 artık Diagnostics Channel API'sini yerel olarak desteklemekte ve bir isteğin yaşam döngüsünü izlemek için bir yol sunmaktadır.

'use strict'

const diagnostics = require('node:diagnostics_channel')
const sget = require('simple-get').concat
const Fastify = require('fastify')

diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
console.log(msg.route.url) // '/:id'
console.log(msg.route.method) // 'GET'
})

diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
// msg, 'tracing:fastify.request.handler:start' kanalından yayımlananla aynıdır
console.log(msg)
})

diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
// hata durumunda
})

const fastify = Fastify()
fastify.route({
method: 'GET',
url: '/:id',
handler: function (req, reply) {
return { hello: 'world' }
}
})

fastify.listen({ port: 0 }, function () {
sget({
method: 'GET',
url: fastify.listeningOrigin + '/7'
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.same(JSON.parse(body), { hello: 'world' })
})
})

Daha fazla detay için belgelere ve #5252 bakabilirsiniz.