メインコンテンツへスキップ
バージョン: 最新版 (v5.0.x)

V5移行ガイド

このガイドは、Fastify v4からv5への移行を支援することを目的としています。

v5に移行する前に、v4からのすべての非推奨警告を修正していることを確認してください。すべてのv4の非推奨機能は削除されており、アップグレード後は機能しなくなります。

長期サポートサイクル

Fastify v5はNode.js v20以降のみサポートします。古いバージョンのNode.jsを使用している場合は、Fastify v5を使用するには新しいバージョンにアップグレードする必要があります。

Fastify v4は2025年6月30日までサポートされます。アップグレードできない場合は、HeroDevsから製品寿命終了後のサポートプランを購入することを検討してください。

Node.js v20の理由

Fastify v5は、`node:test`の優れたサポートなど、v18と比較して大きな違いがあるため、Node.js v20以降のみサポートします。これにより、より優れた開発者エクスペリエンスを提供し、メンテナンスを合理化できます。

Node.js v18は2025年4月30日に長期サポートを終了するため、いずれにしてもv20へのアップグレードを計画する必要があります。

破壊的変更

完全なJSONスキーマは、`querystring`、`params`、`body`、およびレスポンススキーマで必須になりました

v5以降、Fastifyは`querystring`、`params`、`body`スキーマに完全なJSONスキーマを要求します。`jsonShortHand`オプションも削除されたことに注意してください。

デフォルトのJSONスキーマバリデーターを使用する場合は、`type`プロパティを含む`querystring`、`params`、`body`、`response`スキーマに完全なJSONスキーマを提供する必要があります。

// 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 });
});

詳細については、#5586を参照してください。

Zodなどの異なる形式を使用するためにJSONスキーマバリデーターをオーバーライドすることは依然として可能です。この変更は、それを簡素化します。

この変更は、@fastify/swaggerなどの他のツールとの統合に役立ちます。

新しいロガーコンストラクターシグネチャ

Fastify v4では、`logger`オプションにpinoロガーを構築するためのオプションと、カスタムロガーインスタンスを受け入れていました。これは大きな混乱の原因となっていました。

その結果、v5では`logger`オプションはカスタムロガーを受け入れなくなりました。カスタムロガーを使用するには、代わりに`loggerInstance`オプションを使用してください。

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

`useSemicolonDelimiter`はデフォルトでfalse

v5以降、Fastifyインスタンスは、v4で行っていたように、クエリ文字列でのセミコロン区切り記号の使用をデフォルトでサポートしなくなりました。これは、標準外の動作であり、RFC 3986に準拠していないためです。

それでもセミコロンを区切り記号として使用したい場合は、サーバー設定で`useSemicolonDelimiter: true`を設定できます。

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

パラメーターオブジェクトにはプロトタイプがなくなりました

v4では、`parameters`オブジェクトにプロトタイプがありました。v5では、これはもう当てはまりません。つまり、`toString`や`hasOwnProperty`など、`Object`から継承されたプロパティを`parameters`オブジェクトでアクセスできなくなりました。

// 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 };
});

これにより、プロトタイプ汚染攻撃に対する防御を強化することで、アプリケーションのセキュリティが向上します。

タイププロバイダーは、バリデーターとシリアライザーのスキーマを区別するようになりました

v4では、タイププロバイダーは検証とシリアライゼーションの両方に同じ型を持っていました。v5では、タイププロバイダーは`ValidatorSchema`と`SerializerSchema`という2つの別々の型に分割されています。

@fastify/type-provider-json-schema-to-ts@fastify/type-provider-typeboxはすでに更新されています。新しい型を取得するには、最新バージョンにアップグレードしてください。カスタムタイププロバイダーを使用している場合は、次のように変更する必要があります。

--- 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()メソッドの変更

.listen()メソッドの可変長引数シグネチャは削除されました。つまり、可変数の引数で`.listen()`を呼び出すことができなくなりました。

// v4
fastify.listen(8000)

こうなります

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

これはv4で`FSTDEP011`として既に非推奨になっていたので、新しいシグネチャを使用するようにコードを既に更新しているはずです。

トレーラーの直接返却が削除されました

v4では、ハンドラーからトレーラーを直接返すことができました。v5では、これはできなくなりました。

// 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('')
});

コールバックを使用することもできました。これはv4で`FSTDEP013`として既に非推奨になっていたので、新しいシグネチャを使用するようにコードを既に更新しているはずです。

ルート定義へのアクセスが簡素化されました

ルート定義へのアクセスに関するすべての非推奨プロパティが削除され、現在は`request.routeOptions`からアクセスされます。

コード説明解決方法議論
FSTDEP012非推奨の`request.context`プロパティにアクセスしようとしています。`request.routeOptions.config`または`request.routeOptions.schema`を使用してください。#4216 #5084
FSTDEP015非推奨の`request.routeSchema`プロパティにアクセスしています。`request.routeOptions.schema`を使用してください。#4470
FSTDEP016非推奨の`request.routeConfig`プロパティにアクセスしています。`request.routeOptions.config`を使用してください。#4470
FSTDEP017非推奨の`request.routerPath`プロパティにアクセスしています。`request.routeOptions.url`を使用してください。#4470
FSTDEP018非推奨の`request.routerMethod`プロパティにアクセスしています。`request.routeOptions.method`を使用してください。#4470
FSTDEP019非推奨の`reply.context`プロパティにアクセスしています。`reply.routeOptions.config`または`reply.routeOptions.schema`を使用してください。#5032 #5084

詳細については、#5616を参照してください。

`reply.redirect()`の新しいシグネチャ

`reply.redirect()`メソッドの新しいシグネチャは次のとおりです。`reply.redirect(url: string, code?: number)`。

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

次のように変更してください。

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

これはv4で`FSTDEP021`として既に非推奨になっていたので、新しいシグネチャを使用するようにコードを既に更新しているはずです。

`reply.sent`の変更は禁止されました

v4では、`reply.sent`プロパティを変更してレスポンスの送信を防ぐことができました。v5では、これはできなくなりました。代わりに`reply.hijack()`を使用してください。

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

次のように変更してください。

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

これはv4で`FSTDEP010`として既に非推奨になっていたので、新しいシグネチャを使用するようにコードを既に更新しているはずです。

ルートバージョニングシグネチャ変更の制約

ルートバージョニングの制約のシグネチャを変更しました。`version`オプションと`versioning`オプションは削除され、代わりに`constraints`オプションを使用する必要があります。

コード説明解決方法議論
FSTDEP008ルートの`{version: "..."}`オプションを使用してルート制約を使用しています。`{constraints: {version: "..."}}`オプションを使用してください。#2682
FSTDEP009サーバーの{versioning: "..."}オプションを使用して、カスタムルートバージョン管理戦略を使用しています。`{constraints: {version: "..."}}`オプションを使用してください。#2682

exposeHeadRoutes: trueの場合、GETの前にHEADルートを登録する必要があります

exposeHeadRoutes: trueの場合、カスタムHEADルートにさらに厳格な要件があります。

カスタムHEADルートを提供する場合、exposeHeadRoutesを明示的にfalseに設定するか、

// 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) => {
// ...
});

HEADルートをGETの前に配置する必要があります。

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

fastify.get('/route', {

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

これは#2700で変更され、旧動作はv4でFSTDEP007として非推奨になりました。

request.connectionの削除

request.connectionプロパティはv5で削除されました。代わりにrequest.socketを使用してください。

// 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' };
});

これはv4でFSTDEP05として既に非推奨になっていたため、新しいシグネチャを使用するようにコードを既に更新しているはずです。

reply.getResponseTime()は削除されました。代わりにreply.elapsedTimeを使用してください

reply.getResponseTime()メソッドはv5で削除されました。代わりにreply.elapsedTimeを使用してください。

// 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' };
});

これはv4でFSTDEP20として既に非推奨になっていたため、新しいシグネチャを使用するようにコードを既に更新しているはずです。

fastify.hasRoute()find-my-wayの動作に一致するようになりました

fastify.hasRoute()メソッドは、find-my-wayの動作に一致するようになり、ルート定義をルートで定義されているとおりに渡す必要があります。

// 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

一部の非標準HTTPメソッドの削除

Fastifyから以下のHTTPメソッドを削除しました。

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

acceptHTTPMethodメソッドを使用して、これらを再び追加できるようになりました。

const fastify = Fastify()

// add a new http method on top of the default ones:
fastify.acceptHTTPMethod('REBIND')

// add a new HTTP method that accepts a body:
fastify.acceptHTTPMethod('REBIND', { hasBody: true })

// reads the HTTP methods list:
fastify.supportedMethods // returns a string array

詳細については、#5567を参照してください。

デコレータでの参照型のサポート削除

この参照はすべてのリクエスト間で共有されるため、参照型(ArrayObject)を使用してRequest/Replyをデコレートすることは禁止されています。

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

または、関数の形式にする

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

または、ゲッターとして

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

詳細については、#5462を参照してください。

Content-Type: application/jsonヘッダーと空のボディを持つDELETEのサポート削除

v4では、FastifyはContent-Type: application/jsonヘッダーと空のボディを持つDELETEリクエストを受け入れていました。v5では、これは許可されなくなりました。

詳細については、#5419を参照してください。

プラグインは、コールバック/Promise APIを混合できなくなりました

v4では、プラグインはコールバックとPromise APIを混合することができ、予期しない動作につながることがありました。v5では、これは許可されなくなりました。

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

または

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

getDefaultRouteメソッドとsetDefaultRouteメソッドの削除

getDefaultRouteメソッドとsetDefaultRouteメソッドはv5で削除されました。

詳細については、#4485#4480を参照してください。これはv4でFSTDEP014として既に非推奨になっていたため、コードを既に更新しているはずです。

新機能

診断チャネルのサポート

Fastify v5は、診断チャネルAPIをネイティブにサポートし、リクエストのライフサイクルを追跡する方法を提供します。

'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 is the same as the one emitted by the 'tracing:fastify.request.handler:start' channel
console.log(msg)
})

diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
// in case of error
})

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' })
})
})

ドキュメント#5252で詳細を確認してください。