Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug/issue 1363 honor resource plugin optimization lifecycle for SSR pages bundling #1364

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions packages/cli/src/lifecycles/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,26 @@ async function interceptPage(url, request, plugins, body) {
return response;
}

function getPluginInstances(compilation) {
async function optimizePage(url, plugins, body) {
let response = new Response(body, {
headers: new Headers({ 'Content-Type': 'text/html' })
});

for (const plugin of plugins) {
if (plugin.shouldOptimize && await plugin.shouldOptimize(url, response.clone())) {
response = mergeResponse(response.clone(), await plugin.optimize(url, response.clone()));
}
}

return response;
}

function getPluginInstances(compilation, pluginFilters = []) {
return [...compilation.config.plugins]
.filter(plugin => plugin.type === 'resource' && plugin.name !== 'plugin-node-modules:resource')
.filter(plugin => plugin.type === 'resource'
&& plugin.name !== 'plugin-node-modules:resource'
&& pluginFilters.indexOf(plugin.name) < 0
)
.map((plugin) => {
return plugin.provider(compilation);
});
Expand Down Expand Up @@ -251,6 +268,9 @@ async function bundleSsrPages(compilation, optimizePlugins) {
const { executeModuleUrl } = config.plugins.find(plugin => plugin.type === 'renderer').provider();
const { executeRouteModule } = await import(executeModuleUrl);
const { pagesDir, scratchDir } = context;
// SSR pages do not support static routing (yet)
// https://github.com/ProjectEvergreen/greenwood/discussions/1033
const plugins = getPluginInstances(compilation, ['plugin-static-router']);

// one pass to generate initial static HTML and to track all combined static resources across layouts
// and before we optimize so that all bundled assets can tracked up front
Expand Down Expand Up @@ -284,12 +304,11 @@ async function bundleSsrPages(compilation, optimizePlugins) {
const entryFileUrl = new URL(pageHref);
const entryFileOutputUrl = new URL(`file://${entryFileUrl.pathname.replace(pagesDir.pathname, scratchDir.pathname)}`);
const outputPathRootUrl = new URL(`file://${path.dirname(entryFileOutputUrl.pathname)}/`);
const htmlOptimizer = config.plugins.find(plugin => plugin.name === 'plugin-standard-html').provider(compilation);
const pagesPathDiff = context.pagesDir.pathname.replace(context.projectDirectory.pathname, '');
const relativeDepth = '../'.repeat(pagePath.split('/').length - 1);

let staticHtml = ssrPrerenderPagesRouteMapper[route];
staticHtml = await (await htmlOptimizer.optimize(new URL(`http://localhost:8080${route}`), new Response(staticHtml))).text();
staticHtml = await (await optimizePage(new URL(`http://localhost:8080${route}`), plugins, staticHtml)).text();
staticHtml = staticHtml.replace(/[`\\$]/g, '\\$&'); // https://stackoverflow.com/a/75688937/417806

if (!await checkResourceExists(outputPathRootUrl)) {
Expand Down
33 changes: 32 additions & 1 deletion packages/cli/test/cases/serve.default.ssr/greenwood.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
import { ResourceInterface } from '@greenwood/cli/src/lib/resource-interface.js';

// here to test for https://github.com/ProjectEvergreen/greenwood/issues/1363
class BannerPluginResource extends ResourceInterface {
constructor(compilation, options = {}) {
super(compilation, options);

this.contentType = ['text/html'];
}

async shouldOptimize(url, response) {
return response.headers.get('Content-Type').indexOf(this.contentType[0]) >= 0;
}

async optimize(url, response) {
let body = await response.text();

body = body.replace('<head>', `
<head>
<!-- banner plugin was here -->
`);

return new Response(body);
}
}

export default {
port: 8181
port: 8181,
plugins: [{
type: 'resource',
name: 'plugin-banner-content',
provider: (compilation) => new BannerPluginResource(compilation)
}]
};
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ describe('Serve Greenwood With: ', function() {
describe('Serve command with HTML route response for the home page using "get" functions', function() {
let response;
let dom;
let body;

before(async function() {
response = await fetch(`${hostname}/`);
const body = await response.clone().text();
body = await response.clone().text();
dom = new JSDOM(body);
});

Expand All @@ -98,6 +99,10 @@ describe('Serve Greenwood With: ', function() {

expect(scriptFiles.length).to.equal(2);
});

it('should have the expected resource plugin optimization lifecycle content for SSR pages', async function() {
expect(body.indexOf('<!-- banner plugin was here -->') >= 0).to.equal(true);
});
});

// https://github.com/ProjectEvergreen/greenwood/issues/1351
Expand Down
Loading