diff --git a/packages/cli/package.json b/packages/cli/package.json index acaafa2c4..216057b34 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -55,7 +55,8 @@ "remark-rehype": "^7.0.0", "rollup": "^2.58.0", "rollup-plugin-terser": "^7.0.0", - "unified": "^9.2.0" + "unified": "^9.2.0", + "wc-compiler": "~0.3.1" }, "devDependencies": { "@babel/runtime": "^7.10.4", diff --git a/packages/cli/src/lib/ssr-route-worker.js b/packages/cli/src/lib/ssr-route-worker.js index 9f859575b..3a30e0b8b 100644 --- a/packages/cli/src/lib/ssr-route-worker.js +++ b/packages/cli/src/lib/ssr-route-worker.js @@ -1,9 +1,12 @@ // https://github.com/nodejs/modules/issues/307#issuecomment-858729422 import { pathToFileURL } from 'url'; import { workerData, parentPort } from 'worker_threads'; +import { renderToString } from 'wc-compiler'; async function executeRouteModule({ modulePath, compilation, route, label, id }) { - const { getTemplate = null, getBody = null, getFrontmatter = null } = await import(pathToFileURL(modulePath)).then(module => module); + const moduleURL = pathToFileURL(modulePath); + const module = await import(moduleURL).then(module => module); + const { getFrontmatter = null, getBody = null, getTemplate = null } = module; const parsedCompilation = JSON.parse(compilation); const data = { template: null, @@ -11,16 +14,22 @@ async function executeRouteModule({ modulePath, compilation, route, label, id }) frontmatter: null }; + if (getFrontmatter) { + data.frontmatter = await getFrontmatter(parsedCompilation, route, label, id); + } + if (getTemplate) { data.template = await getTemplate(parsedCompilation, route); } - if (getBody) { - data.body = await getBody(parsedCompilation, route); - } + if (module.default) { + const { html } = await renderToString(moduleURL); - if (getFrontmatter) { - data.frontmatter = await getFrontmatter(parsedCompilation, route, label, id); + data.body = html; + } else { + if (getBody) { + data.body = await getBody(parsedCompilation, route); + } } parentPort.postMessage(data); diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js index 3326d9df2..4b4229b86 100644 --- a/packages/cli/src/lifecycles/bundle.js +++ b/packages/cli/src/lifecycles/bundle.js @@ -5,11 +5,12 @@ const bundleCompilation = async (compilation) => { return new Promise(async (resolve, reject) => { try { - compilation.graph = compilation.graph.filter(page => !page.isSSR); - // https://rollupjs.org/guide/en/#differences-to-the-javascript-api if (compilation.graph.length > 0) { - const rollupConfigs = await getRollupConfig(compilation); + const rollupConfigs = await getRollupConfig({ + ...compilation, + graph: compilation.graph.filter(page => !page.isSSR) + }); const bundle = await rollup(rollupConfigs[0]); await bundle.write(rollupConfigs[0].output); diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index bf3e42528..9964c0a39 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -314,9 +314,10 @@ async function getHybridServer(compilation) { await fs.promises.mkdir(path.join(compilation.context.scratchDir, url), { recursive: true }); await fs.promises.writeFile(path.join(compilation.context.scratchDir, url, 'index.html'), body); - compilation.graph = compilation.graph.filter(page => page.isSSR && page.route === url); - - const rollupConfigs = await getRollupConfig(compilation); + const rollupConfigs = await getRollupConfig({ + ...compilation, + graph: [matchingRoute] + }); const bundle = await rollup(rollupConfigs[0]); await bundle.write(rollupConfigs[0].output); diff --git a/packages/cli/src/plugins/renderer/plugin-renderer-string.js b/packages/cli/src/plugins/renderer/plugin-renderer-default.js similarity index 54% rename from packages/cli/src/plugins/renderer/plugin-renderer-string.js rename to packages/cli/src/plugins/renderer/plugin-renderer-default.js index df120d32a..16203beb9 100644 --- a/packages/cli/src/plugins/renderer/plugin-renderer-string.js +++ b/packages/cli/src/plugins/renderer/plugin-renderer-default.js @@ -1,6 +1,6 @@ -const greenwoodPluginRendererString = { +const greenwoodPluginRendererDefault = { type: 'renderer', - name: 'plugin-renderer-string', + name: 'plugin-renderer-default', provider: () => { return { workerUrl: new URL('../../lib/ssr-route-worker.js', import.meta.url) @@ -8,4 +8,4 @@ const greenwoodPluginRendererString = { } }; -export { greenwoodPluginRendererString }; \ No newline at end of file +export { greenwoodPluginRendererDefault }; \ No newline at end of file diff --git a/packages/cli/test/cases/build.default.ssr/build.default.ssr.spec.js b/packages/cli/test/cases/build.default.ssr/build.default.ssr.spec.js index c8adae81a..f1d9f769a 100644 --- a/packages/cli/test/cases/build.default.ssr/build.default.ssr.spec.js +++ b/packages/cli/test/cases/build.default.ssr/build.default.ssr.spec.js @@ -17,6 +17,8 @@ * footer.js * pages/ * artists.js + * index.md + * users.js * templates/ * app.html */ @@ -24,7 +26,7 @@ import chai from 'chai'; import fs from 'fs'; import { JSDOM } from 'jsdom'; import path from 'path'; -import { getSetupFiles, getDependencyFiles, getOutputTeardownFiles } from '../../../../../test/utils.js'; +import { getSetupFiles, getOutputTeardownFiles } from '../../../../../test/utils.js'; import request from 'request'; import { runSmokeTest } from '../../../../../test/smoke-test.js'; import { Runner } from 'gallinago'; @@ -49,82 +51,7 @@ describe('Build Greenwood With: ', function() { describe(LABEL, function() { before(async function() { - const lit = await getDependencyFiles( - `${process.cwd()}/node_modules/lit/*.js`, - `${outputPath}/node_modules/lit/` - ); - const litDecorators = await getDependencyFiles( - `${process.cwd()}/node_modules/lit/decorators/*.js`, - `${outputPath}/node_modules/lit/decorators/` - ); - const litDirectives = await getDependencyFiles( - `${process.cwd()}/node_modules/lit/directives/*.js`, - `${outputPath}/node_modules/lit/directives/` - ); - const litPackageJson = await getDependencyFiles( - `${process.cwd()}/node_modules/lit/package.json`, - `${outputPath}/node_modules/lit/` - ); - const litElement = await getDependencyFiles( - `${process.cwd()}/node_modules/lit-element/*.js`, - `${outputPath}/node_modules/lit-element/` - ); - const litElementPackageJson = await getDependencyFiles( - `${process.cwd()}/node_modules/lit-element/package.json`, - `${outputPath}/node_modules/lit-element/` - ); - const litElementDecorators = await getDependencyFiles( - `${process.cwd()}/node_modules/lit-element/decorators/*.js`, - `${outputPath}/node_modules/lit-element/decorators/` - ); - const litHtml = await getDependencyFiles( - `${process.cwd()}/node_modules/lit-html/*.js`, - `${outputPath}/node_modules/lit-html/` - ); - const litHtmlPackageJson = await getDependencyFiles( - `${process.cwd()}/node_modules/lit-html/package.json`, - `${outputPath}/node_modules/lit-html/` - ); - const litHtmlDirectives = await getDependencyFiles( - `${process.cwd()}/node_modules/lit-html/directives/*.js`, - `${outputPath}/node_modules/lit-html/directives/` - ); - // lit-html has a dependency on this - // https://github.com/lit/lit/blob/main/packages/lit-html/package.json#L82 - const trustedTypes = await getDependencyFiles( - `${process.cwd()}/node_modules/@types/trusted-types/package.json`, - `${outputPath}/node_modules/@types/trusted-types/` - ); - const litReactiveElement = await getDependencyFiles( - `${process.cwd()}/node_modules/@lit/reactive-element/*.js`, - `${outputPath}/node_modules/@lit/reactive-element/` - ); - const litReactiveElementDecorators = await getDependencyFiles( - `${process.cwd()}/node_modules/@lit/reactive-element/decorators/*.js`, - `${outputPath}/node_modules/@lit/reactive-element/decorators/` - ); - const litReactiveElementPackageJson = await getDependencyFiles( - `${process.cwd()}/node_modules/@lit/reactive-element/package.json`, - `${outputPath}/node_modules/@lit/reactive-element/` - ); - - await runner.setup(outputPath, [ - ...getSetupFiles(outputPath), - ...lit, - ...litPackageJson, - ...litDirectives, - ...litDecorators, - ...litElementPackageJson, - ...litElement, - ...litElementDecorators, - ...litHtmlPackageJson, - ...litHtml, - ...litHtmlDirectives, - ...trustedTypes, - ...litReactiveElement, - ...litReactiveElementDecorators, - ...litReactiveElementPackageJson - ]); + await runner.setup(outputPath, getSetupFiles(outputPath)); return new Promise(async (resolve) => { setTimeout(() => { @@ -138,12 +65,13 @@ describe('Build Greenwood With: ', function() { runSmokeTest(['public', 'index'], LABEL); let response = {}; - let dom; + let artistsPageDom; + let usersPageDom; let artistsPageGraphData; before(async function() { const graph = JSON.parse(await fs.promises.readFile(path.join(outputPath, 'public/graph.json'), 'utf-8')); - + artistsPageGraphData = graph.filter(page => page.route === '/artists/')[0]; return new Promise((resolve, reject) => { @@ -154,14 +82,28 @@ describe('Build Greenwood With: ', function() { response = res; response.body = body; - dom = new JSDOM(body); + + artistsPageDom = new JSDOM(body); resolve(); }); }); }); - describe('Serve command with HTML route response', function() { + before(async function() { + return new Promise((resolve, reject) => { + request.get(`${hostname}/users/`, (err, res, body) => { + if (err) { + reject(); + } + usersPageDom = new JSDOM(body); + + resolve(); + }); + }); + }); + + describe('Serve command with HTML route response for page using "get" functions', function() { it('should return a 200 status', function(done) { expect(response.statusCode).to.equal(200); @@ -179,53 +121,45 @@ describe('Build Greenwood With: ', function() { }); it('the response body should be valid HTML from JSDOM', function(done) { - expect(dom).to.not.be.undefined; + expect(artistsPageDom).to.not.be.undefined; done(); }); it('should have one style tags', function() { - const styles = dom.window.document.querySelectorAll('head > style'); + const styles = artistsPageDom.window.document.querySelectorAll('head > style'); expect(styles.length).to.equal(1); }); - it('should have three script tags', function() { - const scripts = dom.window.document.querySelectorAll('head > script'); + it('should have the expected number of