Skip to content

Commit

Permalink
Expose the ssr manifest (#6435)
Browse files Browse the repository at this point in the history
* Expose the ssr manifest

* Add changeset

* Add types for virtual mod
  • Loading branch information
matthewp authored Mar 7, 2023
1 parent 2751584 commit a206106
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/heavy-kids-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': minor
---

Expose the manifest to plugins via the astro:ssr-manifest virtual module
4 changes: 4 additions & 0 deletions packages/astro/client-base.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ declare module '*.mdx' {
export default load;
}

declare module 'astro:ssr-manifest' {
export const manifest: import('./dist/@types/astro').SSRManifest;
}

// Everything below are Vite's types (apart from image types, which are in `client.d.ts`)

// CSS modules
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/build/plugins/plugin-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ export function vitePluginSSR(internals: BuildInternals, adapter: AstroAdapter):
return `import * as adapter from '${adapter.serverEntrypoint}';
import * as _main from '${pagesVirtualModuleId}';
import { deserializeManifest as _deserializeManifest } from 'astro/app';
import { _privateSetManifestDontUseThis } from 'astro:ssr-manifest';
const _manifest = Object.assign(_deserializeManifest('${manifestReplace}'), {
pageMap: _main.pageMap,
renderers: _main.renderers
});
_privateSetManifestDontUseThis(_manifest);
const _args = ${adapter.args ? JSON.stringify(adapter.args) : 'undefined'};
export * from '${pagesVirtualModuleId}';
${
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import markdownVitePlugin from '../vite-plugin-markdown/index.js';
import astroScannerPlugin from '../vite-plugin-scanner/index.js';
import astroScriptsPlugin from '../vite-plugin-scripts/index.js';
import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js';
import { vitePluginSSRManifest } from '../vite-plugin-ssr-manifest/index.js';

interface CreateViteOptions {
settings: AstroSettings;
Expand Down Expand Up @@ -116,6 +117,7 @@ export async function createVite(
astroContentVirtualModPlugin({ settings }),
astroContentImportPlugin({ fs, settings }),
astroContentAssetPropagationPlugin({ mode }),
vitePluginSSRManifest(),
settings.config.experimental.assets ? [astroAssetsPlugin({ settings, logging, mode })] : [],
],
publicDir: fileURLToPath(settings.config.publicDir),
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/vite-plugin-astro-server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export default function createVitePluginAstroServer({
handle: baseMiddleware(settings, logging),
});
}
viteServer.middlewares.use(async (req, res) => {
// Note that this function has a name so other middleware can find it.
viteServer.middlewares.use(async function astroDevHandler(req, res) {
if (req.url === undefined || !req.method) {
res.writeHead(500, 'Incomplete request');
res.end();
Expand Down
26 changes: 26 additions & 0 deletions packages/astro/src/vite-plugin-ssr-manifest/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

import type { Plugin as VitePlugin } from 'vite';

const manifestVirtualModuleId = 'astro:ssr-manifest';
const resolvedManifestVirtualModuleId = '\0' + manifestVirtualModuleId;

export function vitePluginSSRManifest(): VitePlugin {
return {
name: '@astrojs/vite-plugin-astro-ssr-manifest',
enforce: 'post',
resolveId(id, parent) {
if(id === manifestVirtualModuleId) {
return resolvedManifestVirtualModuleId;
}
},
load(id) {
if (id === resolvedManifestVirtualModuleId) {
return `export let manifest = {};
export function _privateSetManifestDontUseThis(ssrManifest) {
manifest = ssrManifest;
}`;
}
return void 0;
},
};
}
8 changes: 8 additions & 0 deletions packages/astro/test/fixtures/ssr-manifest/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@test/ssr-manifest",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*"
}
}
17 changes: 17 additions & 0 deletions packages/astro/test/fixtures/ssr-manifest/src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
import { manifest } from 'astro:ssr-manifest';
---
<html>
<head>
<title>Testing</title>
<style>
body {
background: green;
}
</style>
</head>
<body>
<h1>Testing</h1>
<div id="assets" set:html={JSON.stringify([...manifest.assets])}></div>
</body>
</html>
30 changes: 30 additions & 0 deletions packages/astro/test/ssr-manifest.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

import { expect } from 'chai';
import { loadFixture } from './test-utils.js';
import testAdapter from './test-adapter.js';
import * as cheerio from 'cheerio';

describe('astro:ssr-manifest', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;

before(async () => {
fixture = await loadFixture({
root: './fixtures/ssr-manifest/',
output: 'server',
adapter: testAdapter(),
});
await fixture.build();
});

it('works', async () => {
const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/');
const response = await app.render(request);
const html = await response.text();

const $ = cheerio.load(html);
expect($('#assets').text()).to.equal('["/_astro/index.1bad7273.css"]');

});
});
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a206106

Please sign in to comment.