diff options
author | 2023-06-05 09:03:20 -0400 | |
---|---|---|
committer | 2023-06-05 09:03:20 -0400 | |
commit | 57f8d14c027c30919363e12c664ccff4ed64d0fc (patch) | |
tree | 61817073af197b716af5f0d5b55a6bac34abecdc /packages/integrations/netlify/src | |
parent | dd1a6b6c941aeb7af934bd12db22412af262f5a1 (diff) | |
download | astro-57f8d14c027c30919363e12c664ccff4ed64d0fc.tar.gz astro-57f8d14c027c30919363e12c664ccff4ed64d0fc.tar.zst astro-57f8d14c027c30919363e12c664ccff4ed64d0fc.zip |
Redirects (#7067)
* Redirects spike
* Allow redirects in static mode
* Support in Netlify as well
* Adding a changeset
* Rename file
* Fix build problem
* Refactor to be more modular
* Fix location ref
* Late test should only run in SSR
* Support redirects in Netlify SSR configuration (#7167)
* Implement support for dynamic routes in redirects (#7173)
* Implement support for dynamic routes in redirects
* Remove the .only
* No need to special-case redirects in static build
* Implement support for redirects config in the Vercel adapter (#7182)
* Implement support for redirects config in the Vercel adapter
* Remove unused condition
* Move to a internal helper package
* Add support for the object notation in redirects
* Use status 308 for non-GET redirects (#7186)
* Implement redirects in Cloudflare (#7198)
* Implement redirects in Cloudflare
* Fix build
* Update tests b/c of new ordering
* Debug issue
* Use posix.join
* Update packages/underscore-redirects/package.json
Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
* Update based on review comments
* Update broken test
---------
Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
* Test that redirects can come from middleware (#7213)
* Test that redirects can come from middleware
* Allow non-promise returns for middleware
* Implement priority (#7210)
* Refactor
* Fix netlify test ordering
* Fix ordering again
* Redirects: Allow preventing the output of the static HTML file (#7245)
* Do a simple push for priority
* Adding changesets
* Put the implementation behind a flag.
* Self review
* Update .changeset/chatty-actors-stare.md
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
* Update docs on dynamic restrictions.
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
* Code review changes
* Document netlify static adapter
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
* Slight reword
* Update .changeset/twenty-suns-vanish.md
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
* Add a note about public/_redirects file
* Update packages/astro/src/@types/astro.ts
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
---------
Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
Diffstat (limited to 'packages/integrations/netlify/src')
-rw-r--r-- | packages/integrations/netlify/src/index.ts | 1 | ||||
-rw-r--r-- | packages/integrations/netlify/src/integration-static.ts | 26 | ||||
-rw-r--r-- | packages/integrations/netlify/src/shared.ts | 140 |
3 files changed, 37 insertions, 130 deletions
diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts index fd7fd5fed..510e560f1 100644 --- a/packages/integrations/netlify/src/index.ts +++ b/packages/integrations/netlify/src/index.ts @@ -1,2 +1,3 @@ export { netlifyEdgeFunctions } from './integration-edge-functions.js'; export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js'; +export { netlifyStatic } from './integration-static.js'; diff --git a/packages/integrations/netlify/src/integration-static.ts b/packages/integrations/netlify/src/integration-static.ts new file mode 100644 index 000000000..8814f9d2a --- /dev/null +++ b/packages/integrations/netlify/src/integration-static.ts @@ -0,0 +1,26 @@ +import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro'; +import type { Args } from './netlify-functions.js'; +import { createRedirects } from './shared.js'; + +export function netlifyStatic(): AstroIntegration { + let _config: any; + return { + name: '@astrojs/netlify', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + build: { + // Do not output HTML redirects because we are building a `_redirects` file. + redirects: false, + }, + }); + }, + 'astro:config:done': ({ config }) => { + _config = config; + }, + 'astro:build:done': async ({ dir, routes }) => { + await createRedirects(_config, routes, dir, '', 'static'); + } + } + }; +} diff --git a/packages/integrations/netlify/src/shared.ts b/packages/integrations/netlify/src/shared.ts index 78a61a800..d452ada10 100644 --- a/packages/integrations/netlify/src/shared.ts +++ b/packages/integrations/netlify/src/shared.ts @@ -1,145 +1,25 @@ import type { AstroConfig, RouteData } from 'astro'; -import fs from 'fs'; - -type RedirectDefinition = { - dynamic: boolean; - input: string; - target: string; - weight: 0 | 1; - status: 200 | 404; -}; +import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects'; +import fs from 'node:fs'; export async function createRedirects( config: AstroConfig, routes: RouteData[], dir: URL, entryFile: string, - type: 'functions' | 'edge-functions' | 'builders' + type: 'functions' | 'edge-functions' | 'builders' | 'static' ) { - const _redirectsURL = new URL('./_redirects', dir); const kind = type ?? 'functions'; + const dynamicTarget = `/.netlify/${kind}/${entryFile}`; + const _redirectsURL = new URL('./_redirects', dir); - const definitions: RedirectDefinition[] = []; - - for (const route of routes) { - if (route.pathname) { - if (route.distURL) { - definitions.push({ - dynamic: false, - input: route.pathname, - target: prependForwardSlash(route.distURL.toString().replace(dir.toString(), '')), - status: 200, - weight: 1, - }); - } else { - definitions.push({ - dynamic: false, - input: route.pathname, - target: `/.netlify/${kind}/${entryFile}`, - status: 200, - weight: 1, - }); - - if (route.route === '/404') { - definitions.push({ - dynamic: true, - input: '/*', - target: `/.netlify/${kind}/${entryFile}`, - status: 404, - weight: 0, - }); - } - } - } else { - const pattern = - '/' + - route.segments - .map(([part]) => { - //(part.dynamic ? '*' : part.content) - if (part.dynamic) { - if (part.spread) { - return '*'; - } else { - return ':' + part.content; - } - } else { - return part.content; - } - }) - .join('/'); - - if (route.distURL) { - const target = - `${pattern}` + (config.build.format === 'directory' ? '/index.html' : '.html'); - definitions.push({ - dynamic: true, - input: pattern, - target, - status: 200, - weight: 1, - }); - } else { - definitions.push({ - dynamic: true, - input: pattern, - target: `/.netlify/${kind}/${entryFile}`, - status: 200, - weight: 1, - }); - } - } - } - - let _redirects = prettify(definitions); + const _redirects = createRedirectsFromAstroRoutes({ + config, routes, dir, dynamicTarget + }); + const content = _redirects.print(); // Always use appendFile() because the redirects file could already exist, // e.g. due to a `/public/_redirects` file that got copied to the output dir. // If the file does not exist yet, appendFile() automatically creates it. - await fs.promises.appendFile(_redirectsURL, _redirects, 'utf-8'); -} - -function prettify(definitions: RedirectDefinition[]) { - let minInputLength = 0, - minTargetLength = 0; - definitions.sort((a, b) => { - // Find the longest input, so we can format things nicely - if (a.input.length > minInputLength) { - minInputLength = a.input.length; - } - if (b.input.length > minInputLength) { - minInputLength = b.input.length; - } - - // Same for the target - if (a.target.length > minTargetLength) { - minTargetLength = a.target.length; - } - if (b.target.length > minTargetLength) { - minTargetLength = b.target.length; - } - - // Sort dynamic routes on top - return b.weight - a.weight; - }); - - let _redirects = ''; - // Loop over the definitions - definitions.forEach((defn, i) => { - // Figure out the number of spaces to add. We want at least 4 spaces - // after the input. This ensure that all targets line up together. - let inputSpaces = minInputLength - defn.input.length + 4; - let targetSpaces = minTargetLength - defn.target.length + 4; - _redirects += - (i === 0 ? '' : '\n') + - defn.input + - ' '.repeat(inputSpaces) + - defn.target + - ' '.repeat(Math.abs(targetSpaces)) + - defn.status; - }); - return _redirects; -} - -function prependForwardSlash(str: string) { - return str[0] === '/' ? str : '/' + str; + await fs.promises.appendFile(_redirectsURL, content, 'utf-8'); } |