diff options
Diffstat (limited to 'packages/integrations/node')
-rw-r--r-- | packages/integrations/node/CHANGELOG.md | 12 | ||||
-rw-r--r-- | packages/integrations/node/README.md | 10 | ||||
-rw-r--r-- | packages/integrations/node/src/http-server.ts | 16 | ||||
-rw-r--r-- | packages/integrations/node/src/index.ts | 3 | ||||
-rw-r--r-- | packages/integrations/node/src/preview.ts | 3 | ||||
-rw-r--r-- | packages/integrations/node/src/server.ts | 1 | ||||
-rw-r--r-- | packages/integrations/node/src/standalone.ts | 1 | ||||
-rw-r--r-- | packages/integrations/node/src/types.ts | 1 | ||||
-rw-r--r-- | packages/integrations/node/test/assets.test.js | 43 | ||||
-rw-r--r-- | packages/integrations/node/test/fixtures/image/src/assets/file.txt | 1 | ||||
-rw-r--r-- | packages/integrations/node/test/fixtures/image/src/pages/text-file.astro | 14 |
11 files changed, 103 insertions, 2 deletions
diff --git a/packages/integrations/node/CHANGELOG.md b/packages/integrations/node/CHANGELOG.md index 732122ecf..e4cf76b85 100644 --- a/packages/integrations/node/CHANGELOG.md +++ b/packages/integrations/node/CHANGELOG.md @@ -13,6 +13,18 @@ - Updated dependencies [[`abf601233`](https://github.com/withastro/astro/commit/abf601233f8188d118a8cb063c777478d8d9f1a3), [`6201bbe96`](https://github.com/withastro/astro/commit/6201bbe96c2a083fb201e4a43a9bd88499821a3e), [`cdabf6ef0`](https://github.com/withastro/astro/commit/cdabf6ef02be7220fd2b6bdcef924ceca089381e), [`1c48ed286`](https://github.com/withastro/astro/commit/1c48ed286538ab9e354eca4e4dcd7c6385c96721), [`37697a2c5`](https://github.com/withastro/astro/commit/37697a2c5511572dc29c0a4ea46f90c2f62be8e6), [`bd0c2e9ae`](https://github.com/withastro/astro/commit/bd0c2e9ae3389a9d3085050c1e8134ae98dff299), [`0fe3a7ed5`](https://github.com/withastro/astro/commit/0fe3a7ed5d7bb1a9fce1623e84ba14104b51223c), [`710be505c`](https://github.com/withastro/astro/commit/710be505c9ddf416e77a75343d8cae9c497d72c6), [`153a5abb9`](https://github.com/withastro/astro/commit/153a5abb905042ac68b712514dc9ec387d3e6b17)]: - astro@4.0.0-beta.0 +## 6.1.0 + +### Minor Changes + +- [#9125](https://github.com/withastro/astro/pull/9125) [`8f1d50957`](https://github.com/withastro/astro/commit/8f1d509574f5ee5d77816a13d89ce452dce403ff) Thanks [@matthewp](https://github.com/matthewp)! - Automatically sets immutable cache headers for assets served from the `/_astro` directory. + +## 6.1.0 + +### Minor Changes + +- [#9125](https://github.com/withastro/astro/pull/9125) [`8f1d50957`](https://github.com/withastro/astro/commit/8f1d509574f5ee5d77816a13d89ce452dce403ff) Thanks [@matthewp](https://github.com/matthewp)! - Automatically sets immutable cache headers for assets served from the `/_astro` directory. + ## 6.0.4 ### Patch Changes diff --git a/packages/integrations/node/README.md b/packages/integrations/node/README.md index 5753a59bc..af11405c0 100644 --- a/packages/integrations/node/README.md +++ b/packages/integrations/node/README.md @@ -190,6 +190,16 @@ In the case of multiple run-time variables, store them in a seperate file (e.g. export $(cat .env.runtime) && astro build ``` +#### Assets + +In standalone mode, assets in your `dist/client/` folder are served via the standalone server. You might be deploying these assets to a CDN, in which case the server will never actually be serving them. But in some cases, such as intranet sites, it's fine to serve static assets directly from the application server. + +Assets in the `dist/client/_astro/` folder are the ones that Astro has built. These assets are all named with a hash and therefore can be given long cache headers. Internally the adapter adds this header for these assets: + +``` +Cache-Control: public, max-age=31536000, immutable +``` + ## Troubleshooting ### SyntaxError: Named export 'compile' not found diff --git a/packages/integrations/node/src/http-server.ts b/packages/integrations/node/src/http-server.ts index 2f2339cdf..904937601 100644 --- a/packages/integrations/node/src/http-server.ts +++ b/packages/integrations/node/src/http-server.ts @@ -10,6 +10,7 @@ interface CreateServerOptions { port: number; host: string | undefined; removeBase: (pathname: string) => string; + assets: string; } function parsePathname(pathname: string, host: string | undefined, port: number) { @@ -22,9 +23,16 @@ function parsePathname(pathname: string, host: string | undefined, port: number) } export function createServer( - { client, port, host, removeBase }: CreateServerOptions, + { client, port, host, removeBase, assets }: CreateServerOptions, handler: http.RequestListener ) { + // The `base` is removed before passed to this function, so we don't + // need to check for it here. + const assetsPrefix = `/${assets}/`; + function isImmutableAsset(pathname: string) { + return pathname.startsWith(assetsPrefix); + } + const listener: http.RequestListener = (req, res) => { if (req.url) { let pathname: string | undefined = removeBase(req.url); @@ -54,6 +62,12 @@ export function createServer( // File not found, forward to the SSR handler handler(req, res); }); + stream.on('headers', (_res: http.ServerResponse<http.IncomingMessage>) => { + if (isImmutableAsset(encodedURI)) { + // Taken from https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#immutable + _res.setHeader('Cache-Control', 'public, max-age=31536000, immutable'); + } + }); stream.on('directory', () => { // On directory find, redirect to the trailing slash let location: string; diff --git a/packages/integrations/node/src/index.ts b/packages/integrations/node/src/index.ts index 1f3707949..bac5c25ef 100644 --- a/packages/integrations/node/src/index.ts +++ b/packages/integrations/node/src/index.ts @@ -6,7 +6,7 @@ export function getAdapter(options: Options): AstroAdapter { name: '@astrojs/node', serverEntrypoint: '@astrojs/node/server.js', previewEntrypoint: '@astrojs/node/preview.js', - exports: ['handler', 'startServer'], + exports: ['handler', 'startServer', 'options'], args: options, supportedAstroFeatures: { hybridOutput: 'stable', @@ -49,6 +49,7 @@ export default function createIntegration(userOptions: UserOptions): AstroIntegr server: config.build.server?.toString(), host: config.server.host, port: config.server.port, + assets: config.build.assets, }; setAdapter(getAdapter(_options)); diff --git a/packages/integrations/node/src/preview.ts b/packages/integrations/node/src/preview.ts index 70ed54698..89baa1897 100644 --- a/packages/integrations/node/src/preview.ts +++ b/packages/integrations/node/src/preview.ts @@ -17,11 +17,13 @@ const preview: CreatePreviewServer = async function ({ type ServerModule = ReturnType<typeof createExports>; type MaybeServerModule = Partial<ServerModule>; let ssrHandler: ServerModule['handler']; + let options: ServerModule['options']; try { process.env.ASTRO_NODE_AUTOSTART = 'disabled'; const ssrModule: MaybeServerModule = await import(serverEntrypoint.toString()); if (typeof ssrModule.handler === 'function') { ssrHandler = ssrModule.handler; + options = ssrModule.options!; } else { throw new AstroError( `The server entrypoint doesn't have a handler. Are you sure this is the right file?` @@ -59,6 +61,7 @@ const preview: CreatePreviewServer = async function ({ port, host, removeBase, + assets: options.assets, }, handler ); diff --git a/packages/integrations/node/src/server.ts b/packages/integrations/node/src/server.ts index 90bf8c44c..88bcd7d62 100644 --- a/packages/integrations/node/src/server.ts +++ b/packages/integrations/node/src/server.ts @@ -8,6 +8,7 @@ applyPolyfills(); export function createExports(manifest: SSRManifest, options: Options) { const app = new NodeApp(manifest); return { + options: options, handler: middleware(app, options.mode), startServer: () => startServer(app, options), }; diff --git a/packages/integrations/node/src/standalone.ts b/packages/integrations/node/src/standalone.ts index abe40ff5c..e167e8ab6 100644 --- a/packages/integrations/node/src/standalone.ts +++ b/packages/integrations/node/src/standalone.ts @@ -52,6 +52,7 @@ export default function startServer(app: NodeApp, options: Options) { port, host, removeBase: app.removeBase.bind(app), + assets: options.assets, }, handler ); diff --git a/packages/integrations/node/src/types.ts b/packages/integrations/node/src/types.ts index 85f4f4fbc..1917d8cf3 100644 --- a/packages/integrations/node/src/types.ts +++ b/packages/integrations/node/src/types.ts @@ -15,6 +15,7 @@ export interface Options extends UserOptions { port: number; server: string; client: string; + assets: string; } export type RequestHandlerParams = [ diff --git a/packages/integrations/node/test/assets.test.js b/packages/integrations/node/test/assets.test.js new file mode 100644 index 000000000..9e44ab31d --- /dev/null +++ b/packages/integrations/node/test/assets.test.js @@ -0,0 +1,43 @@ +import { expect } from 'chai'; +import nodejs from '../dist/index.js'; +import { loadFixture } from './test-utils.js'; +import * as cheerio from 'cheerio'; + +describe('Assets', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + let devPreview; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/image/', + output: 'server', + adapter: nodejs({ mode: 'standalone' }), + vite: { + build: { + assetsInlineLimit: 0, + }, + }, + }); + await fixture.build(); + devPreview = await fixture.preview(); + }); + + after(async () => { + await devPreview.stop(); + }); + + it('Assets within the _astro folder should be given immutable headers', async () => { + let response = await fixture.fetch('/text-file'); + let cacheControl = response.headers.get('cache-control'); + expect(cacheControl).to.equal(null); + const html = await response.text(); + const $ = cheerio.load(html); + + // Fetch the asset + const fileURL = $('a').attr('href'); + response = await fixture.fetch(fileURL); + cacheControl = response.headers.get('cache-control'); + expect(cacheControl).to.equal('public, max-age=31536000, immutable'); + }); +}); diff --git a/packages/integrations/node/test/fixtures/image/src/assets/file.txt b/packages/integrations/node/test/fixtures/image/src/assets/file.txt new file mode 100644 index 000000000..e9ea42a12 --- /dev/null +++ b/packages/integrations/node/test/fixtures/image/src/assets/file.txt @@ -0,0 +1 @@ +this is a text file diff --git a/packages/integrations/node/test/fixtures/image/src/pages/text-file.astro b/packages/integrations/node/test/fixtures/image/src/pages/text-file.astro new file mode 100644 index 000000000..893250360 --- /dev/null +++ b/packages/integrations/node/test/fixtures/image/src/pages/text-file.astro @@ -0,0 +1,14 @@ +--- +import txt from '../assets/file.txt?url'; +--- +<html> + <head> + <title>Testing</title> + </head> + <body> + <h1>Testing</h1> + <main> + <a href={txt} download>Download text file</a> + </main> + </body> +</html> |