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

Feature/issue 855 prerender default to false optional puppeteer #860

Closed
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
1 change: 1 addition & 0 deletions greenwood.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const FAVICON_HREF = '/assets/favicon.ico';
export default {
workspace: fileURLToPath(new URL('./www', import.meta.url)),
mode: 'mpa',
prerender: true,
optimization: 'inline',
title: 'Greenwood',
meta: [
Expand Down
5 changes: 4 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"puppeteer": "^10.2.0"
},
"dependencies": {
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-replace": "^2.3.4",
Expand All @@ -40,7 +43,6 @@
"node-html-parser": "^1.2.21",
"postcss": "^8.3.11",
"postcss-import": "^13.0.0",
"puppeteer": "^10.2.0",
"rehype-raw": "^5.0.0",
"rehype-stringify": "^8.0.0",
"remark-frontmatter": "^2.0.0",
Expand All @@ -61,6 +63,7 @@
"lit-redux-router": "~0.20.0",
"lodash-es": "^4.17.20",
"postcss-nested": "^4.1.2",
"puppeteer": "^10.2.0",
"pwa-helpers": "^0.9.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import { bundleCompilation } from '../lifecycles/bundle.js';
import { copyAssets } from '../lifecycles/copy.js';
import { devServer } from '../lifecycles/serve.js';
import fs from 'fs';
import { generateCompilation } from '../lifecycles/compile.js';
import { preRenderCompilation, staticRenderCompilation } from '../lifecycles/prerender.js';
import { ServerInterface } from '../lib/server-interface.js';

const runProductionBuild = async () => {
const runProductionBuild = async (compilation) => {

return new Promise(async (resolve, reject) => {

try {
const compilation = await generateCompilation();
const { prerender } = compilation.config;
const port = compilation.config.devServer.port;
const outputDir = compilation.context.outputDir;
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/develop.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { generateCompilation } from '../lifecycles/compile.js';
import { ServerInterface } from '../lib/server-interface.js';
import { devServer } from '../lifecycles/serve.js';

const runDevServer = async () => {
const runDevServer = async (compilation) => {

return new Promise(async (resolve, reject) => {

try {
const compilation = await generateCompilation();
const { port } = compilation.config.devServer;

(await devServer(compilation)).listen(port, () => {
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/eject.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import fs from 'fs';
import { generateCompilation } from '../lifecycles/compile.js';
import path from 'path';
import { fileURLToPath, URL } from 'url';

const ejectConfiguration = async () => {
const ejectConfiguration = async (compilation) => {
return new Promise(async (resolve, reject) => {
try {
const compilation = await generateCompilation();
const configFilePath = fileURLToPath(new URL('../config', import.meta.url));
const configFiles = fs.readdirSync(configFilePath);

Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/serve.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { generateCompilation } from '../lifecycles/compile.js';
import { prodServer } from '../lifecycles/serve.js';

const runProdServer = async () => {
const runProdServer = async (compilation) => {

return new Promise(async (resolve, reject) => {

try {
const compilation = await generateCompilation();
const port = 8080;

(await prodServer(compilation)).listen(port, () => {
Expand Down
62 changes: 48 additions & 14 deletions packages/cli/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
// https://github.com/ProjectEvergreen/greenwood/issues/141
process.setMaxListeners(0);

import { generateCompilation } from './lifecycles/compile.js';
import program from 'commander';
import fs from 'fs/promises';
import { URL } from 'url';

import { runDevServer } from './commands/develop.js';
import { runProductionBuild } from './commands/build.js';
import { runProdServer } from './commands/serve.js';
import { ejectConfiguration } from './commands/eject.js';

const greenwoodPackageJson = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url), 'utf-8'));
let cmdOption = {};
let command = '';
Expand Down Expand Up @@ -63,30 +59,68 @@ if (program.parse.length === 0) {
program.help();
}

const run = async() => {
const run = async() => {
const compilation = await generateCompilation();

try {
console.info(`Running Greenwood with the ${command} command.`);
process.env.__GWD_COMMAND__ = command;


// auto install puppeteer if user has enabled prerendering
if (compilation.config.prerender) {
try {
await import('puppeteer');
} catch (e) {
console.debug('puppeteer not detected', e);
console.debug('auto intalling puppeteer...');
const os = await import('os');
const spawn = (await import('child_process')).spawn;
const pkgMng = 'yarn'; // program.yarn ? 'yarn' : 'npm'; // default to npm
const command = pkgMng === 'yarn' ? 'add' : 'install';
const pkgCommand = os.platform() === 'win32' ? `${pkgMng}.cmd` : pkgMng;
const args = [command, 'puppeteer@^10.2.0'];

try {
await new Promise((resolve, reject) => {

const process = spawn(pkgCommand, args, { stdio: 'ignore' });

process.on('close', code => {
if (code !== 0) {
reject({
command: `${pkgCommand} ${args.join(' ')}`
});
return;
}
console.debug('auto installation successful!');
resolve();
});
});
} catch (err) {
console.error('not able to handle installing puppeteer', err);
}
}
}

switch (command) {

case 'build':
await runProductionBuild();
case 'build':
await (await import('./commands/build.js')).runProductionBuild(compilation);

break;
case 'develop':
await runDevServer();
await (await import('./commands/develop.js')).runDevServer(compilation);

break;
case 'serve':
process.env.__GWD_COMMAND__ = 'build';
await runProductionBuild();
await runProdServer();

await (await import('./commands/build.js')).runProductionBuild(compilation);
await (await import('./commands/serve.js')).runProdServer(compilation);

break;
case 'eject':
await ejectConfiguration();
await (await import('./commands/eject.js')).ejectConfiguration(compilation);

break;
default:
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/lifecycles/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const defaultConfig = {
meta: [],
plugins: greenwoodPlugins,
markdown: { plugins: [], settings: {} },
prerender: true,
prerender: false,
pagesDirectory: 'pages',
templatesDirectory: 'templates'
};
Expand Down Expand Up @@ -176,7 +176,7 @@ const readAndMergeConfig = async() => {
}
}

// SPA should _not_ prerender if user has specified prerender should be true
// SPA mode should _not_ prerender unless user has chosen to set it to true
if (prerender === undefined && mode === 'spa') {
customConfig.prerender = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ describe('Build Greenwood With: ', function() {
expect(preloadScriptTags.length).to.be.equal(1);
expect(preloadScriptTags[0].href).to.match(/header.*.js/);
});

it('should contain the expected content from <app-header> in the <body>', function() {
const header = dom.window.document.querySelectorAll('body header');

expect(header.length).to.be.equal(1);
expect(header[0].textContent).to.be.equal('This is the header component.');
});
});

describe('<link> tag and preloading', function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,6 @@ describe('Build Greenwood With: ', function() {
// eslint-disable-next-line max-len
expect(scriptTag.textContent).to.be.contain('class e extends HTMLElement{constructor(){super(),this.root=this.attachShadow({mode:"open"}),this.root.innerHTML="\\n <header>This is the header component.</header>\\n "}}customElements.define("app-header",e);');
});

it('should contain the expected content from <app-header> in the <body>', function() {
const header = dom.window.document.querySelectorAll('body header');

expect(header.length).to.be.equal(1);
expect(header[0].textContent).to.be.equal('This is the header component.');
});
});

// assume the second tag is for FooBar
Expand Down Expand Up @@ -139,22 +132,19 @@ describe('Build Greenwood With: ', function() {
it('should contain two <style> tags with the expected CSS content inlined for theme.css and pages.css', function() {
const styleTags = dom.window.document.querySelectorAll('head style');

// one for puppeteer
expect(styleTags.length).to.be.equal(3);
expect(styleTags.length).to.be.equal(2);
});

it('should contain the expected CSS content inlined for theme.css', function() {
const styleTags = dom.window.document.querySelectorAll('head style');

// one for puppeteer
expect(styleTags[1].textContent).to.be.contain('*{font-family:Comic Sans,sans-serif;margin:0;padding:0}');
expect(styleTags[0].textContent).to.be.contain('*{font-family:Comic Sans,sans-serif;margin:0;padding:0}');
});

it('should contain the expected CSS content inlined for page.css', function() {
const styleTags = dom.window.document.querySelectorAll('head style');

// one for puppeteer
expect(styleTags[2].textContent).to.be.contain('body{color:red}');
expect(styleTags[1].textContent).to.be.contain('body{color:red}');
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,10 @@ describe('Build Greenwood With: ', function() {
expect(scriptTags.length).to.be.equal(1);
});

it('should contain the expected content from <app-header> in the <body>', function() {
const header = dom.window.document.querySelectorAll('body header');
it('should contain the expected <app-header> in the <body>', function() {
const header = dom.window.document.querySelectorAll('body app-header');

expect(header.length).to.be.equal(1);
expect(header[0].textContent).to.be.equal('This is the header component.');
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,10 @@ describe('Build Greenwood With: ', function() {
expect(scriptTags.length).to.be.equal(1);
});

// one of these tags comes from puppeteer
it('should have two <style> tags in the <head>', function() {
const styleTags = dom.window.document.querySelectorAll('head style');

expect(styleTags.length).to.be.equal(2);
expect(styleTags.length).to.be.equal(1);
});

it('should have no <link> tags in the <head>', function() {
Expand Down Expand Up @@ -110,13 +109,6 @@ describe('Build Greenwood With: ', function() {

expect(headerScriptTags.length).to.be.equal(0);
});

it('should contain the expected content from <app-header> in the <body>', function() {
const headerScriptTags = dom.window.document.querySelectorAll('body header');

expect(headerScriptTags.length).to.be.equal(1);
expect(headerScriptTags[0].textContent).to.be.equal('This is the header component.');
});
});

describe('JavaScript <script> tag and inline optimization override for <app-footer>', function() {
Expand All @@ -143,13 +135,6 @@ describe('Build Greenwood With: ', function() {

expect(footerScriptTags.length).to.be.equal(1);
});

it('should contain the expected content from <app-footer> in the <body>', function() {
const footer = dom.window.document.querySelectorAll('body footer');

expect(footer.length).to.be.equal(1);
expect(footer[0].textContent).to.be.equal('This is the footer component.');
});
});

describe('CSS <link> tag and inline optimization override for theme.css', function() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Use Case
* Run Greenwood build command with static setting for optimization.
* Run Greenwood build command with static setting for optimization and adds prerender to true to validate with puppeteer.
*
* User Result
* Should generate a Greenwood build that strips all <script> tags and files from the final HTML and output.
Expand All @@ -10,7 +10,8 @@
*
* User Config
* {
* optimization: 'static'
* optimization: 'static',
* prerender: true
* }
*
* Custom Workspace
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export default {
optimization: 'static'
optimization: 'static',
prerender: true
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
* Use Case
* Run Greenwood build command with prerender config set to false.
* Run Greenwood build command with prerender config set to true.
*
* User Result
* Should generate a Greenwood build with no puppeteer generated output.
* Should generate a Greenwood build with puppeteer generated output for Web Components.
*
* User Command
* greenwood build
*
* User Config
* {
* prerender: false
* prerender: true
* }
*
* User Workspace
Expand All @@ -31,7 +31,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;

describe('Build Greenwood With: ', function() {
const LABEL = 'Prerender Configuration turned off';
const LABEL = 'Prerender Configuration turned on';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
let runner;
Expand Down Expand Up @@ -104,12 +104,13 @@ describe('Build Greenwood With: ', function() {
expect(heading).to.equal('Welcome to Greenwood!');
});

it('should not have any prerendered content from <app-header> component', function() {
it('should have prerendered content from <app-header> component', function() {
const appHeader = dom.window.document.querySelectorAll('body app-header');
const header = dom.window.document.querySelectorAll('body header');

expect(appHeader.length).to.equal(1);
expect(header.length).to.equal(0);
expect(header.length).to.equal(1);
expect(header[0].textContent).to.equal('This is the header component.');
});
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export default {
prerender: false
prerender: true
};
Loading