Spaces:
Runtime error
Runtime error
| # V3 Migration Guide | |
| This guide is intended to help with migration from Fastify v2 to v3. | |
| Before beginning please ensure that any deprecation warnings from v2 are fixed. | |
| All v2 deprecations have been removed and they will no longer work after | |
| upgrading. ([#1750](https://github.com/fastify/fastify/pull/1750)) | |
| ## Breaking changes | |
| ### Changed middleware support ([#2014](https://github.com/fastify/fastify/pull/2014)) | |
| From Fastify v3, middleware support does not come out-of-the-box with the | |
| framework itself. | |
| If you use Express middleware in your application, please install and register | |
| the [`@fastify/express`](https://github.com/fastify/fastify-express) or | |
| [`@fastify/middie`](https://github.com/fastify/middie) plugin before doing so. | |
| **v2:** | |
| ```js | |
| // Using the Express `cors` middleware in Fastify v2. | |
| fastify.use(require('cors')()); | |
| ``` | |
| **v3:** | |
| ```js | |
| // Using the Express `cors` middleware in Fastify v3. | |
| await fastify.register(require('@fastify/express')); | |
| fastify.use(require('cors')()); | |
| ``` | |
| ### Changed logging serialization ([#2017](https://github.com/fastify/fastify/pull/2017)) | |
| The logging [Serializers](../Reference/Logging.md) have been updated to now | |
| Fastify [`Request`](../Reference/Request.md) and | |
| [`Reply`](../Reference/Reply.md) objects instead of native ones. | |
| Any custom serializers must be updated if they rely upon `request` or `reply` | |
| properties that are present on the native objects but not the Fastify objects. | |
| **v2:** | |
| ```js | |
| const fastify = require('fastify')({ | |
| logger: { | |
| serializers: { | |
| res(res) { | |
| return { | |
| statusCode: res.statusCode, | |
| customProp: res.customProp | |
| }; | |
| } | |
| } | |
| } | |
| }); | |
| ``` | |
| **v3:** | |
| ```js | |
| const fastify = require('fastify')({ | |
| logger: { | |
| serializers: { | |
| res(reply) { | |
| return { | |
| statusCode: reply.statusCode, // No change required | |
| customProp: reply.raw.customProp // Log custom property from res object | |
| }; | |
| } | |
| } | |
| } | |
| }); | |
| ``` | |
| ### Changed schema substitution ([#2023](https://github.com/fastify/fastify/pull/2023)) | |
| The non-standard `replace-way` shared schema support has been removed. This | |
| feature has been replaced with JSON Schema specification compliant `$ref` based | |
| substitution. To help understand this change read [Validation and Serialization | |
| in Fastify | |
| v3](https://dev.to/eomm/validation-and-serialization-in-fastify-v3-2e8l). | |
| **v2:** | |
| ```js | |
| const schema = { | |
| body: 'schemaId#' | |
| }; | |
| fastify.route({ method, url, schema, handler }); | |
| ``` | |
| **v3:** | |
| ```js | |
| const schema = { | |
| body: { | |
| $ref: 'schemaId#' | |
| } | |
| }; | |
| fastify.route({ method, url, schema, handler }); | |
| ``` | |
| ### Changed schema validation options ([#2023](https://github.com/fastify/fastify/pull/2023)) | |
| The `setSchemaCompiler` and `setSchemaResolver` options have been replaced with | |
| the `setValidatorCompiler` to enable future tooling improvements. To help | |
| understand this change read [Validation and Serialization in Fastify | |
| v3](https://dev.to/eomm/validation-and-serialization-in-fastify-v3-2e8l). | |
| **v2:** | |
| ```js | |
| const fastify = Fastify(); | |
| const ajv = new AJV(); | |
| ajv.addSchema(schemaA); | |
| ajv.addSchema(schemaB); | |
| fastify.setSchemaCompiler(schema => ajv.compile(schema)); | |
| fastify.setSchemaResolver(ref => ajv.getSchema(ref).schema); | |
| ``` | |
| **v3:** | |
| ```js | |
| const fastify = Fastify(); | |
| const ajv = new AJV(); | |
| ajv.addSchema(schemaA); | |
| ajv.addSchema(schemaB); | |
| fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => | |
| ajv.compile(schema) | |
| ); | |
| ``` | |
| ### Changed preParsing hook behavior ([#2286](https://github.com/fastify/fastify/pull/2286)) | |
| From Fastify v3, the behavior of the `preParsing` hook will change slightly | |
| to support request payload manipulation. | |
| The hook now takes an additional argument, `payload`, and therefore the new hook | |
| signature is `fn(request, reply, payload, done)` or `async fn(request, reply, | |
| payload)`. | |
| The hook can optionally return a new stream via `done(null, stream)` or | |
| returning the stream in case of async functions. | |
| If the hook returns a new stream, it will be used instead of the original one in | |
| subsequent hooks. A sample use case for this is handling compressed requests. | |
| The new stream should add the `receivedEncodedLength` property to the stream | |
| that should reflect the actual data size received from the client. For instance, | |
| in a compressed request it should be the size of the compressed payload. This | |
| property can (and should) be dynamically updated during `data` events. | |
| The old syntax of Fastify v2 without payload is supported but it is deprecated. | |
| ### Changed hooks behavior ([#2004](https://github.com/fastify/fastify/pull/2004)) | |
| From Fastify v3, the behavior of `onRoute` and `onRegister` hooks will change | |
| slightly to support hook encapsulation. | |
| - `onRoute` - The hook will be called asynchronously. The hook is now inherited | |
| when registering a new plugin within the same encapsulation scope. Thus, this | |
| hook should be registered _before_ registering any plugins. | |
| - `onRegister` - Same as the onRoute hook. The only difference is that now the | |
| very first call will no longer be the framework itself, but the first | |
| registered plugin. | |
| ### Changed Content Type Parser syntax ([#2286](https://github.com/fastify/fastify/pull/2286)) | |
| In Fastify v3 the content type parsers now have a single signature for parsers. | |
| The new signatures are `fn(request, payload, done)` or `async fn(request, | |
| payload)`. Note that `request` is now a Fastify request, not an | |
| `IncomingMessage`. The payload is, by default, a stream. If the `parseAs` option | |
| is used in `addContentTypeParser`, then `payload` reflects the option value | |
| (string or buffer). | |
| The old signatures `fn(req, [done])` or `fn(req, payload, [done])` (where `req` | |
| is `IncomingMessage`) are still supported but are deprecated. | |
| ### Changed TypeScript support | |
| The type system was changed in Fastify version 3. The new type system introduces | |
| generic constraining and defaulting, plus a new way to define schema types such | |
| as a request body, querystring, and more! | |
| **v2:** | |
| ```ts | |
| interface PingQuerystring { | |
| foo?: number; | |
| } | |
| interface PingParams { | |
| bar?: string; | |
| } | |
| interface PingHeaders { | |
| a?: string; | |
| } | |
| interface PingBody { | |
| baz?: string; | |
| } | |
| server.get<PingQuerystring, PingParams, PingHeaders, PingBody>( | |
| '/ping/:bar', | |
| opts, | |
| (request, reply) => { | |
| console.log(request.query); // This is of type `PingQuerystring` | |
| console.log(request.params); // This is of type `PingParams` | |
| console.log(request.headers); // This is of type `PingHeaders` | |
| console.log(request.body); // This is of type `PingBody` | |
| } | |
| ); | |
| ``` | |
| **v3:** | |
| ```ts | |
| server.get<{ | |
| Querystring: PingQuerystring; | |
| Params: PingParams; | |
| Headers: PingHeaders; | |
| Body: PingBody; | |
| }>('/ping/:bar', opts, async (request, reply) => { | |
| console.log(request.query); // This is of type `PingQuerystring` | |
| console.log(request.params); // This is of type `PingParams` | |
| console.log(request.headers); // This is of type `PingHeaders` | |
| console.log(request.body); // This is of type `PingBody` | |
| }); | |
| ``` | |
| ### Manage uncaught exception ([#2073](https://github.com/fastify/fastify/pull/2073)) | |
| In sync route handlers, if an error was thrown the server crashed by design | |
| without calling the configured `.setErrorHandler()`. This has changed and now | |
| all unexpected errors in sync and async routes are managed. | |
| **v2:** | |
| ```js | |
| fastify.setErrorHandler((error, request, reply) => { | |
| // this is NOT called | |
| reply.send(error) | |
| }) | |
| fastify.get('/', (request, reply) => { | |
| const maybeAnArray = request.body.something ? [] : 'I am a string' | |
| maybeAnArray.substr() // Thrown: [].substr is not a function and crash the server | |
| }) | |
| ``` | |
| **v3:** | |
| ```js | |
| fastify.setErrorHandler((error, request, reply) => { | |
| // this IS called | |
| reply.send(error) | |
| }) | |
| fastify.get('/', (request, reply) => { | |
| const maybeAnArray = request.body.something ? [] : 'I am a string' | |
| maybeAnArray.substr() // Thrown: [].substr is not a function, but it is handled | |
| }) | |
| ``` | |
| ## Further additions and improvements | |
| - Hooks now have consistent context regardless of how they are registered | |
| ([#2005](https://github.com/fastify/fastify/pull/2005)) | |
| - Deprecated `request.req` and `reply.res` for | |
| [`request.raw`](../Reference/Request.md) and | |
| [`reply.raw`](../Reference/Reply.md) | |
| ([#2008](https://github.com/fastify/fastify/pull/2008)) | |
| - Removed `modifyCoreObjects` option | |
| ([#2015](https://github.com/fastify/fastify/pull/2015)) | |
| - Added [`connectionTimeout`](../Reference/Server.md#factory-connection-timeout) | |
| option ([#2086](https://github.com/fastify/fastify/pull/2086)) | |
| - Added [`keepAliveTimeout`](../Reference/Server.md#factory-keep-alive-timeout) | |
| option ([#2086](https://github.com/fastify/fastify/pull/2086)) | |
| - Added async-await support for [plugins](../Reference/Plugins.md#async-await) | |
| ([#2093](https://github.com/fastify/fastify/pull/2093)) | |
| - Added the feature to throw object as error | |
| ([#2134](https://github.com/fastify/fastify/pull/2134)) | |