From 0e879524f461d5abccac3060ed198deb02ab9478 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 1 Dec 2018 10:27:58 -0500 Subject: [PATCH] basic plumbing for SSR --- register.js | 2 +- src/cli/compile.ts | 3 +-- src/compile/Component.ts | 10 +++++----- src/compile/index.ts | 11 +++++++---- src/compile/render-dom/index.ts | 8 +------- src/compile/render-ssr/index.ts | 10 ++++++---- src/compile/wrapModule.ts | 3 ++- src/interfaces.ts | 2 +- test/css/index.js | 2 +- test/server-side-rendering/index.js | 12 ++++++------ 10 files changed, 31 insertions(+), 32 deletions(-) diff --git a/register.js b/register.js index 0bd0650112..4d971867b8 100644 --- a/register.js +++ b/register.js @@ -33,7 +33,7 @@ function registerExtension(extension) { const options = Object.assign({}, compileOptions, { filename, name: capitalise(name), - generate: 'ssr' + format: 'cjs' }); const { js } = compile(fs.readFileSync(filename, 'utf-8'), options); diff --git a/src/cli/compile.ts b/src/cli/compile.ts index 47141f2346..474a31e326 100644 --- a/src/cli/compile.ts +++ b/src/cli/compile.ts @@ -54,8 +54,7 @@ export function compile(input, opts) { immutable: opts.immutable, generate: opts.generate || 'dom', customElement: opts.customElement, - store: opts.store, - shared: opts.shared + sveltePath: opts.sveltePath }; if (isDir) { diff --git a/src/compile/Component.ts b/src/compile/Component.ts index 2e5590c054..d0b7f35ebe 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -219,17 +219,13 @@ export default class Component { return { name, alias }; }); - const sharedPath = typeof options.shared === 'string' - ? options.shared - : 'svelte/internal.js'; - const module = wrapModule( result, format, name, options, banner, - sharedPath, + options.sveltePath ? `${options.sveltePath}/internal.js` : `svelte/internal.js`, importedHelpers, this.imports, this.module_exports, @@ -485,6 +481,10 @@ export default class Component { this.userVars.add(specifier.local.name); this.declarations.push(specifier.local.name); // TODO we don't really want this, but it's convenient for now }); + + if (this.options.sveltePath && node.source.value === 'svelte') { + code.overwrite(node.source.start, node.source.end, this.options.sveltePath); + } } }); } diff --git a/src/compile/index.ts b/src/compile/index.ts index a0456b02f2..a35fa8193d 100644 --- a/src/compile/index.ts +++ b/src/compile/index.ts @@ -73,9 +73,12 @@ export default function compile(source: string, options: CompileOptions = {}) { return { ast, stats: stats.render(null), js: null, css: null }; } - if (options.generate === 'ssr') { - return renderSSR(component, options); - } + const dom = renderDOM(component, options); + const ssr = renderSSR(component, options); - return renderDOM(component, options); + return component.generate(`${dom}\n\n${ssr}`, options, { + banner: `/* ${component.file ? `${component.file} ` : ``}generated by Svelte v${"__VERSION__"} */`, + name: component.name, + format: options.format || 'esm' + }); } \ No newline at end of file diff --git a/src/compile/render-dom/index.ts b/src/compile/render-dom/index.ts index 09da6e9b41..a64541fcdb 100644 --- a/src/compile/render-dom/index.ts +++ b/src/compile/render-dom/index.ts @@ -222,11 +222,5 @@ export default function dom( `); } - let result = builder.toString(); - - return component.generate(result, options, { - banner: `/* ${component.file ? `${component.file} ` : ``}generated by Svelte v${"__VERSION__"} */`, - name, - format, - }); + return builder.toString(); } diff --git a/src/compile/render-ssr/index.ts b/src/compile/render-ssr/index.ts index bf6ed3b9ba..7aacddbc1d 100644 --- a/src/compile/render-ssr/index.ts +++ b/src/compile/render-ssr/index.ts @@ -12,7 +12,11 @@ export default function ssr( ) { const renderer = new Renderer(); - const format = options.format || 'cjs'; + return deindent` + function $render($$props) { + throw new Error('TODO'); + } + `; const { computations, name, templateProperties } = component; @@ -56,7 +60,7 @@ export default function ssr( const debugName = `<${component.customElement ? component.tag : name}>`; // TODO concatenate CSS maps - const result = (deindent` + return (deindent` ${js} var ${name} = {}; @@ -129,8 +133,6 @@ export default function ssr( ${templateProperties.preload && `${name}.preload = %preload;`} `).trim(); - - return component.generate(result, options, { name, format }); } function trim(nodes) { diff --git a/src/compile/wrapModule.ts b/src/compile/wrapModule.ts index dfbd262030..8063fc193e 100644 --- a/src/compile/wrapModule.ts +++ b/src/compile/wrapModule.ts @@ -65,6 +65,7 @@ function esm( ${code} export default ${name}; + export { $render }; ${module_exports.length > 0 && `export { ${module_exports.map(e => e.name === e.as ? e.name : `${e.name} as ${e.as}`).join(', ')} };`}`; } @@ -105,7 +106,7 @@ function cjs( return `const ${lhs} = require("${node.source.value}");` }); - const exports = [`exports.default = ${name};`].concat( + const exports = [`exports.default = ${name};`, `exports.$render = $render;`].concat( module_exports.map(x => `exports.${x.as} = ${x.name};`) ); diff --git a/src/interfaces.ts b/src/interfaces.ts index ee709e0888..c358ca20ed 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -49,10 +49,10 @@ export interface CompileOptions { outputFilename?: string; cssOutputFilename?: string; + sveltePath?: string; dev?: boolean; immutable?: boolean; - shared?: boolean | string; hydratable?: boolean; legacy?: boolean; customElement?: CustomElementOptions | true; diff --git a/test/css/index.js b/test/css/index.js index 76412df29b..093c78bc3e 100644 --- a/test/css/index.js +++ b/test/css/index.js @@ -22,7 +22,7 @@ function normalizeWarning(warning) { return warning; } -describe.only('css', () => { +describe('css', () => { fs.readdirSync('test/css/samples').forEach(dir => { if (dir[0] === '.') return; diff --git a/test/server-side-rendering/index.js b/test/server-side-rendering/index.js index 8c1e67ff5b..d94f784139 100644 --- a/test/server-side-rendering/index.js +++ b/test/server-side-rendering/index.js @@ -19,11 +19,11 @@ function tryToReadFile(file) { } } -describe("ssr", () => { +describe.only("ssr", () => { before(() => { require("../../register")({ extensions: ['.svelte', '.html'], - store: true + sveltePath: process.cwd() }); return setupHtmlEqual(); @@ -44,14 +44,14 @@ describe("ssr", () => { (solo ? it.only : it)(dir, () => { dir = path.resolve("test/server-side-rendering/samples", dir); try { - let component; + let $render; const mainHtmlFile = `${dir}/main.html`; const mainSvelteFile = `${dir}/main.svelte`; if (fs.existsSync(mainHtmlFile)) { - component = require(mainHtmlFile); + $render = require(mainHtmlFile).$render; } else if (fs.existsSync(mainSvelteFile)) { - component = require(mainSvelteFile); + $render = require(mainSvelteFile).$render; } const expectedHtml = tryToReadFile(`${dir}/_expected.html`); @@ -59,7 +59,7 @@ describe("ssr", () => { const data = tryToLoadJson(`${dir}/data.json`); - const rendered = component.render(data); + const rendered = $render(data); const { html, css, head } = rendered; // rendered.toString() === rendered.html