-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Description
Preliminary Checks
- This issue is not a duplicate. Before opening a new issue, please search existing issues: https://github.com/gatsbyjs/gatsby/issues
- This issue is not a question, feature request, RFC, or anything other than a bug report directly related to Gatsby. Please post those things in GitHub Discussions: https://github.com/gatsbyjs/gatsby/discussions
Description
The forced usage of Gatsby Adapters has caused several regressions and issues related to headers & redirects for builds running on NETLIFY. As of v5.12.0, Gatsby will detect that the build is running on NETLIFY and add the gatsby-adapter-netlify adapter to the build and remove the gatsby-plugin-netlify plugin without any stock way to "opt-out" of the behavior.
Unfortunately, the gatsby-adapter-netlify does not have feature parity with gatsby-plugin-netlify and also contains a few bugs. The combination of these two things results in build output being different for anyone building on NETLIFY.
A couple of references to bugs/issues already filed:
gatsby-adapter-netlifynot respecting"force"option passed tocreateRedirect#38541gatsby-adapter-netlifynot generating headers for redirects #38538
After digging through the output and code some more, I believe this is a much broader set of issues than those two issues alone so creating this issue as an umbrella. If the preference is to have a single issue for each individual item identified, please just let me know.
The issues discovered are:
- Headers on redirects are not emitted
forceis not honored (needs to include!)- external redirects have a forced
/added to the beginning of them (Netlify supports domain redirects - example: domain alias to redirect to primary site). Conditionson redirects are not honored- The following features of
gatsby-plugin-netlifyare not available and therefore have no effect:- allPageHeaders
- transformHeaders
- mergeSecurityHeaders
- mergeCachingHeaders
- generateMatchPathRewrites
Linkpaths are not converted to their corresponding hash- Client-only routes have incorrect header
pathPrefix&assetPrefix- Not honored in headers (note that
gatsby-plugin-netlifyhad some issues in this area as well). - Should
assetroutes even be passed through to the adapter in RoutesManifest when assetPrefix is an absolute URL?
- Not honored in headers (note that
_headersfile size could become significantly large, especially on larger sites -gatsby-adapter-netlifyemits explicit headers for each route path as opposed to passing wildcards, etc. through to the adapter. This comes with three potential downsides:- Does not give the adapter, which understands its own platform best, a way to optimize headers. While each platform will likely be able to process explicit path's, there may be optimizations that the platform can take with wildcards, supporting regex's, etc. that would better serve its implementation.
- Could lead to performance degradation depending on the way the platform evaluates path matching on headers at runtime. For example, if the platform looks through every "header" key for a match of a page path to determine all the header matches before setting the headers on the response, a large file would slow down page requests. This would take full evaluation of the platform to determine true impact (if any) but, as the first item mentions, the platform adapter should know best how to optimize the headers for itself.
- Could result in failed builds because of the file size. For example, Netlify specifically states that if the combined size of
_redirects&netlify.tomlis too large, it could fail the deploy. While it doesn't mention this for_headers, the same is likely true (would require validation). In the repro, the file size of_headersusinggatsby-plugin-netlifyis 2,408 bytes while the file size usinggatsby-adapter-netlifyis 59,515 bytes (using theextrapagesbuild which has ~105 pages), nearly a 25x increase.
All of the above (and possibly some more I missed), will impact customers relying on any of these as soon as they build on Netlify with a version >= 5.12.0.
As mentioned here as it relates to builds breaking, 5.12.0 likely should have been a major version update as all of these are breaking changes and since most likely have a semver of ^5.x.x, customers relying on any of these features/functionality will be impacted if building on NETLIFY.
Most of the above issues are problems/missing functionality in the core Gatsby Adapter logic, not in the gatsby-adapter-netlify adapter itself. For example, when IRedirectRoute is created, force is not passed through so the adapter doesn't receive the value even though there is code in the adapter to process it - same holds true for the conditions property. Additionally, createRedirect allows for any set of [key: string]: unknown which aren't passed through (they wouldn't be used in this case but they should be passed through since createRedirect API and IRedirectRoute support it).
I had created feature requests for the ability to disable adapters and add allPageHeaders & transformHeaders, however the more that I've run up against, after thinking it through, I believe these aren't features but regression defects given Adapters was a minor release version and not a major. At the very least, adding a way to disable adapters as soon as possible is likely warranted.
Workarounds
In the meantime, for those that come across this, there are a few options to avoid the above issues:
- Stay on a version of Gatsby < 5.12.0 - This is the simplest and recommended approach if any of the above would effect your site
- Implement the noop Adapter solution that I describe in the discussion
- Define your own redirects & headers via (_redirects/_headers) instead of relying on Gatsby adapter to generate. You can place these files in
staticdirectory and they will get copied over topublicduring the build. Gatsby adapter will merge in any changes it makes to these files for a combined output so you could define everything you need or just the redirects/rules that Gatsby adapter doesn't support properly.
Note
For any anyone (especially Gatsby cloud customers moving over) moving to Netlify and planning on using transformHeaders in gatsby-plugin-netlify (same existed in gatsby-plugin-gatsby-cloud), note that there is a bug where the path parameter is not passed as expected. Assuming the PR I submitted gets merged, then workaround 1 or 2 will achieve the equivalent output as something like gatsby-plugin-gatsby-cloud would have.
I have created a full-set of repros that demonstrate three scenarios related to the output of headers & redirects - again, this only impacts builds on NETLIFY:
- No Adapter - What the headers & redirects are when no adapter is used and
gatsby-plugin-netlifyis configured
- With Adapter - What the exact same site & config from
No Adapterwould generate for headers & redirects
- WIth Adapter & Gatsby Headers Config - As much as possible, use the
headersconfig to replicate some of the functionality that is lost with Adapters compared togatsby-plugin-netlify
Each branch has the following files in root directory:
npm run build- Standard site- sanitized_headers - The output of _headers after each build
- sanitized_redirects - The output of _redirects after each build
npm run build:pathprefix- Includes a path prefix- sanitized_headers_pathprefix - The output of _headers after each build
- sanitized_redirects_pathprefix - The output of _redirects after each build
npm run build:assetprefix- Includes a path & asset prefix- sanitized_headers_assetprefix - The output of _headers after each build
- sanitized_redirects_assetprefix - The output of _redirects after each build
npm run build:extrapages- Standard site with 100 extra pages- sanitized_headers_extrapages - The output of _headers after each build
- sanitized_redirects_extrapages - The output of _redirects after each build
I have manually adjusted these files from their original to align sort order some. The output between using an adapter & gatsby-plugin-netlify is quite different (e.g., plugin uses /*, adapter emits same headers for each path when /* is used) but hoping this makes it a little more readable. You can review the PRs to see the differences between building with just gatsby-plugin-netlify
Reproduction Link
https://github.com/techfg/gatsby-adapter-issues
Steps to Reproduce
Run one of the four builds in all three branches and compare the output of public/_headers and public/_redirects.
Expected Result
The headers & redirects in a build that uses gatsby-adapter-netlify should be same as build using gatsby-plugin-netlify (or better in some cases like security improvements & issues with prefix paths).
Actual Result
The headers & redirects are not identical resulting in different build output without any changes to code/config of the site due to Adapters not being an "opt-in" feature.
Environment
System:
OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa)
CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900HK
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v18.17.1/bin/yarn
npm: 9.8.1 - ~/.nvm/versions/node/v18.17.1/bin/npm
Browsers:
Chrome: 116.0.5845.179
npmPackages:
gatsby: ^5.11.0 => 5.12.4
gatsby-adapter-netlify: ^1.0.0 => 1.0.0
gatsby-plugin-netlify: ^5.1.0 => 5.1.0
npmGlobalPackages:
gatsby-cli: 5.12.1Config Flags
N/A