-
Notifications
You must be signed in to change notification settings - Fork 880
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Move ssr vm-modules demo into its own dir * Fix some typos in ssr demo * Add global ssr demo
- Loading branch information
Showing
9 changed files
with
226 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
/** | ||
* This is a server-only module that renders the HTML file shell. | ||
*/ | ||
|
||
import {render} from '../../lib/render-with-global-dom-shim.js'; | ||
import {template, initialData} from './module.js'; | ||
|
||
export function renderAppWithInitialData() { | ||
return renderApp(initialData); | ||
} | ||
|
||
// This module runs in the app context with the client-side code, but is a | ||
// server-only module. It doesn't use lit-html so that it can render the HTML | ||
// shell in unbalanced fragments. By yielding the HTML preamable immediately | ||
// with no lit-html template preparation or rendering needed, we minimize TTFB, | ||
// And can get the browser to start prefetch as soon as possible. | ||
export function* renderApp(data: typeof initialData) { | ||
yield ` | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<!-- This little script loads the client script on a button click. This | ||
lets us see that only the HTML loads for first render --> | ||
<script type="module"> | ||
const button = document.querySelector('button'); | ||
button.addEventListener('click', () => { | ||
import('/demo/global/app-client.js'); | ||
}); | ||
</script> | ||
<script src="./node_modules/@webcomponents/template-shadowroot/template-shadowroot.min.js"></script> | ||
`; | ||
yield ` | ||
</head> | ||
<body> | ||
<button>Hydrate</button> | ||
<div>`; | ||
|
||
// Call the SSR render() function to render a client/server shared template. | ||
yield* render(template(data)); | ||
|
||
yield ` | ||
</div> | ||
<script>TemplateShadowRoot.hydrateShadowRoots(document.body);</script> | ||
</body> | ||
</html>`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import Koa from 'koa'; | ||
import staticFiles from 'koa-static'; | ||
import koaNodeResolve from 'koa-node-resolve'; | ||
import {URL} from 'url'; | ||
import * as path from 'path'; | ||
import {Readable} from 'stream'; | ||
import {renderAppWithInitialData} from './app-server.js'; | ||
|
||
const {nodeResolve} = koaNodeResolve; | ||
|
||
const moduleUrl = new URL(import.meta.url); | ||
const packageRoot = path.resolve(moduleUrl.pathname, '../../..'); | ||
|
||
const port = 8080; | ||
|
||
// This is a fairly standard Koa server that represents how the SSR API might | ||
// be used. | ||
const app = new Koa(); | ||
app.use(async (ctx: Koa.Context, next: Function) => { | ||
// Pass through anything not the root path to static file serving | ||
if (ctx.URL.pathname !== '/') { | ||
await next(); | ||
return; | ||
} | ||
|
||
const ssrResult = renderAppWithInitialData(); | ||
ctx.type = 'text/html'; | ||
ctx.body = Readable.from(ssrResult); | ||
}); | ||
app.use(nodeResolve({})); | ||
app.use(staticFiles(packageRoot)); | ||
app.listen(port, () => { | ||
console.log(`Server listening on port ${port}`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
/** | ||
* This is a client-only file used to boot the page. | ||
*/ | ||
|
||
import 'lit/experimental-hydrate-support.js'; | ||
import {render} from 'lit'; | ||
import {hydrate} from 'lit/experimental-hydrate.js'; | ||
import {template, initialData} from './module.js'; | ||
|
||
console.log('Page hydrating with same data as rendered with SSR.'); | ||
// The hydrate() function is run with the same data as used in the server | ||
// render. It doesn't update the DOM, and just updates the lit-html part values | ||
// so that future renders() will do the minimal DOM updates. | ||
hydrate(template(initialData), window.document.body); | ||
|
||
window.setTimeout(() => { | ||
console.log('Page updating with new data...'); | ||
// The first call to render() can use new data, and will only update the DOM | ||
// where this data differs from that passed to hydrate(). | ||
render( | ||
template({ | ||
name: 'Hydration', | ||
message: 'We have now been hydrated and updated with new data.', | ||
items: ['hy', 'dra', 'ted'], | ||
prop: 'prop-updated', | ||
attr: 'attr-updated', | ||
wasUpdated: true, | ||
}), | ||
window.document.body | ||
); | ||
}, 0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
/** | ||
* This is a shared client/server module. | ||
*/ | ||
|
||
import {html} from 'lit'; | ||
import {LitElement, css} from 'lit'; | ||
import {property} from 'lit/decorators/property.js'; | ||
|
||
export const initialData = { | ||
name: 'SSR', | ||
message: 'This is a test.', | ||
items: ['foo', 'bar', 'qux'], | ||
prop: 'prop-value', | ||
attr: 'attr-value', | ||
wasUpdated: false, | ||
}; | ||
|
||
export class MyElement extends LitElement { | ||
static styles = css` | ||
:host { | ||
display: inline-block; | ||
border: 1px dashed gray; | ||
margin: 4px; | ||
padding: 4px; | ||
} | ||
:host > * { | ||
padding: 4px; | ||
} | ||
header { | ||
font-weight: bold; | ||
} | ||
:host([wasUpdated]) { | ||
background: lightgreen; | ||
} | ||
`; | ||
|
||
@property({type: String}) | ||
prop = 'initial-prop'; | ||
@property({type: String}) | ||
attr = 'initial-attr'; | ||
@property({type: Boolean, reflect: true}) | ||
wasUpdated = false; | ||
|
||
render() { | ||
return html` | ||
<header>I'm a my-element!</header> | ||
<div><i>this.prop</i>: ${this.prop}</div> | ||
<div><i>this.attr</i>: ${this.attr}</div> | ||
`; | ||
} | ||
} | ||
customElements.define('my-element', MyElement); | ||
|
||
export const header = (name: string) => html` <h1>Hello ${name}!</h1> `; | ||
|
||
export const template = (data: { | ||
name: string; | ||
message: string; | ||
items: Array<string>; | ||
prop: string; | ||
attr: string; | ||
wasUpdated: boolean; | ||
}) => | ||
html` | ||
${header(data.name)} | ||
<p>${data.message}</p> | ||
<h4>repeating:</h4> | ||
<div>${data.items.map((item, i) => html` <p>${i}) ${item}</p> `)}</div> | ||
${Array(3) | ||
.fill(1) | ||
.map( | ||
(_item, i) => html` | ||
<my-element | ||
?wasUpdated=${data.wasUpdated} | ||
.prop=${`${data.prop}: ${i}`} | ||
attr=${`${data.attr}: ${i}`} | ||
></my-element> | ||
` | ||
)} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters