Skip to content

Commit

Permalink
Bug/issue 1072 serve command not serving prerendered ssr content (#1073)
Browse files Browse the repository at this point in the history
* fix serving of prerendered SSR pages for serve command

* improve detection of hybrid router for serve command and add static export SSR serve command specs

* nest spec setup inside describe block
  • Loading branch information
thescientist13 authored Feb 24, 2023
1 parent 59b4e3b commit 15dac4d
Show file tree
Hide file tree
Showing 25 changed files with 631 additions and 18 deletions.
4 changes: 2 additions & 2 deletions packages/cli/src/commands/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const runProdServer = async (compilation) => {
try {
const port = compilation.config.port;
const hasApisDir = await checkResourceExists(compilation.context.apisDir);
const hasDynamicRoutes = compilation.graph.filter(page => page.isSSR && ((page.data.hasOwnProperty('static') && !page.data.static) || !compilation.config.prerender));
const server = hasDynamicRoutes.length > 0 || hasApisDir ? getHybridServer : getStaticServer;
const hasDynamicRoutes = compilation.graph.find(page => page.isSSR && !page.data.static);
const server = (hasDynamicRoutes && !compilation.config.prerender) || hasApisDir ? getHybridServer : getStaticServer;

(await server(compilation)).listen(port, () => {
console.info(`Started server at localhost:${port}`);
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/lifecycles/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,13 @@ async function getStaticServer(compilation, composable) {
const url = new URL(`http://localhost:8080${ctx.url}`);
const matchingRoute = compilation.graph.find(page => page.route === url.pathname);
const isSPA = compilation.graph.find(page => page.isSPA);
const { isSSR } = matchingRoute || {};
const isStatic = matchingRoute && !isSSR || isSSR && compilation.config.prerender || isSSR && matchingRoute.data.static;

if (isSPA || (matchingRoute && !matchingRoute.isSSR) || url.pathname.split('.').pop() === 'html') {
if (isSPA || (matchingRoute && isStatic) || url.pathname.split('.').pop() === 'html') {
const pathname = isSPA
? 'index.html'
: matchingRoute
: isStatic
? matchingRoute.outputPath
: url.pathname;
const body = await fs.readFile(new URL(`./${pathname}`, outputDir), 'utf-8');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
* greenwood build
*
* User Config
* None
* {
* prerender: true
* }
*
* User Workspace
* src/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,17 @@ describe('Build Greenwood With: ', function() {

runSmokeTest(['public', 'index'], LABEL);

let dom;
let artistsPageGraphData;

before(async function() {
const graph = JSON.parse(await fs.promises.readFile(path.join(outputPath, 'public/graph.json'), 'utf-8'));
const artistsHtml = await fs.promises.readFile(path.join(outputPath, 'public/artists/index.html'), 'utf-8');

artistsPageGraphData = graph.filter(page => page.route === '/artists/')[0];
dom = new JSDOM(artistsHtml);
});

describe('Build command that tests for static HTML export from SSR route', function() {
let dom;
let artistsPageGraphData;

before(async function() {
const graph = JSON.parse(await fs.promises.readFile(path.join(outputPath, 'public/graph.json'), 'utf-8'));
const artistsHtml = await fs.promises.readFile(path.join(outputPath, 'public/artists/index.html'), 'utf-8');

artistsPageGraphData = graph.filter(page => page.route === '/artists/')[0];
dom = new JSDOM(artistsHtml);
});

it('should have one style tags', function() {
const styles = dom.window.document.querySelectorAll('head > style');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
prerender: true
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Use Case
* Run Greenwood with an SSR route that is prerender using configuration.
*
* User Result
* Should generate a bare bones Greenwood build for hosting a prerender SSR application.
*
* User Command
* greenwood build
*
* User Config
* {
* prerender: true
* }
*
* User Workspace
* src/
* components/
* footer.js
* pages/
* index.js
* templates/
* app.html
*/
import chai from 'chai';
import { JSDOM } from 'jsdom';
import path from 'path';
import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js';
import request from 'request';
import { runSmokeTest } from '../../../../../test/smoke-test.js';
import { Runner } from 'gallinago';
import { fileURLToPath, URL } from 'url';

const expect = chai.expect;

describe('Serve Greenwood With: ', function() {
const LABEL = 'A Server Rendered Application (SSR) with prerender configuration';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const hostname = 'http://127.0.0.1:8080';
const outputPath = fileURLToPath(new URL('.', import.meta.url));
let runner;

before(async function() {
this.context = {
publicDir: path.join(outputPath, 'public'),
hostname
};
runner = new Runner();
});

describe(LABEL, function() {

before(async function() {
await runner.setup(outputPath, getSetupFiles(outputPath));

return new Promise(async (resolve) => {
setTimeout(() => {
resolve();
}, 10000);

await runner.runCommand(cliPath, 'serve');
});
});

runSmokeTest(['public', 'index', 'serve'], LABEL);

describe('Serve command that prerenders SSR pages', function() {
let dom;
let response;

before(async function() {
return new Promise((resolve, reject) => {
request.get(`${hostname}/`, (err, res, body) => {
if (err) {
reject();
}

response = res;
response.body = body;
dom = new JSDOM(body);

resolve();
});
});
});

describe('Serve command with HTML response for the home page', function() {
it('should return a 200 status', function(done) {
expect(response.statusCode).to.equal(200);
done();
});

it('should return the correct content type', function(done) {
expect(response.headers['content-type']).to.contain('text/html');
done();
});

it('should return a response body', function(done) {
expect(response.body).to.not.be.undefined;
done();
});

it('should have the expected output for the page', function() {
const headings = dom.window.document.querySelectorAll('body > h1');

expect(headings.length).to.equal(1);
expect(headings[0].textContent).to.equal('This is the home page.');
});
});
});
});

after(function() {
runner.teardown(getOutputTeardownFiles(outputPath));
runner.stopCommand();
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const template = document.createElement('template');

template.innerHTML = '<footer>This is the footer component.</footer>';

export default class FooterComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}

connectedCallback() {
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
}

customElements.define('app-footer', FooterComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default class HomePage extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<h1>This is the home page.</h1>
`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">
<head>
<title>Default Title</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script type="module" src="/components/footer.js"></script>
</head>
<body>
<app-footer></app-footer>
<page-outlet></page-outlet>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "module",
"dependencies": {
"lit": "^2.0.0"
}
}
Loading

0 comments on commit 15dac4d

Please sign in to comment.