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

[docs] Add documentation for SSR event handling #1390

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
15 changes: 15 additions & 0 deletions packages/lit-dev-content/site/docs/v3/data/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,21 @@ and the ContextConsumer controller:
);
```

### SSR
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this section needs to focus a bit more on the information of "I am googling around and I just want to get this thing done where can I copy paste a solution" and then follow up with the explanation. So like questions a user might have:

  • Does Context work in SSR?
  • If so how do I do it?
  • I am running into X error when I try to use Context in SSR, how do I fix it?
  • Why is this the solution? (probably lower priority question they have)

So maybe rephrasing a bit backwards might help e.g.

// answer the questions
Lit SSR provides basic support for global and component-scoped context. Context in SSR requires that globalThis.litSsrCallConnectedCallback = true to be enabled. (insert link to docs on that)

// give a copy-pastable example

// server.ts
globalThis.litSsrCallConnectedCallback = true; // or however / wherever you're supposed to set this
...

// client.ts
import {isServer} from 'lit';
import {ContextProvider} from '@lit/context';
const globalRoot = isServer ? globalThis.litServerRoot : document.body;
new ContextProvider(globalRoot, {...});

// then include wonky explanation why
As DOM nodes like document.body are not typically available in the server environment, Lit SSR will provide globalThis.litServerRoot for event-emitting purposes. Additionally, Lit Context provides setup in the native web component connectedCallback lifecycle callback, so globalThis.litSsrCallConnectedCallback needs to be set to true to enable Lit SSR to include that callback in the server lifecycle.

To use Lit Context in a component, you can do the following:

// copy-pastable example

// I actually don't know, please provide

// wonky explanation why the code above is like that


Basic support for server side rendering can be enabled by assigning
`globalThis.litSsrCallConnectedCallback = true`. This will configure `@lit-labs/ssr` to call
`connectedCallback()` and `ReactiveController.hostConnected()`, which allows `@lit/context`
to register the necessary event handlers for SSR.

As an alternative to `document.documentElement` or `document.body` (which are expected to be undefined
in the server environment) for global event listeners (e.g. for `@lit/context ContextProvider`), you can
use the global variable `globalThis.litServerRoot` which is (only) available during SSR.

```ts
new ContextProvider(isServer ? globalThis.litServerRoot : document.body, {...});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the overloaded constructor signature for ContextProvider is

  constructor(host: HostElement, options: Options<T>);
  /** @deprecated Use new ContextProvider(host, options) */
  constructor(host: HostElement, context: T, initialValue?: ContextType<T>);
  constructor(
    host: HostElement,
    contextOrOptions: T | Options<T>,
    initialValue?: ContextType<T>
  ) { /*...* }

ContextRoot does not have any constructor params.

Do you mean something like this?

  const root = new ContextRoot();
  if (!isServer) {
    root.attach(document.body);
  } else {
    root.attach(globalThis.litServerRoot);
  }

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I am referring to the use case of registering a ContextProvider globally. (See https://www.npmjs.com/package/@lit/context and search for document.body)
ContextRoot should not be necessary in an SSR environment, as classes are loaded in order (from my understanding).

But thank you for pointing out, that my example is incomplete and easily misunderstood. I will extend it. 😄 👍

```

## Example Use Cases

### Current user, locale, etc.
Expand Down
4 changes: 2 additions & 2 deletions packages/lit-dev-content/site/docs/v3/ssr/authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Whether a method is called on the server is subject to change while Lit SSR is p
| Method | Called on server | Notes |
|-|-|-|
| `constructor()` | Yes ⚠️ | |
| `connectedCallback()` | No | |
| `connectedCallback()` | No | Can be enabled with `globalThis.litSsrCallConnectedCallback = true` |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please give an example of this in this document?

| `disconnectedCallback()` | No | |
| `attributeChangedCallback()` | No | |
| `adoptedCallback()` | No | |
Expand All @@ -119,7 +119,7 @@ Whether a method is called on the server is subject to change while Lit SSR is p
| Method | Called on server | Notes |
|-|-|-|
| `constructor()` | Yes ⚠️ | |
| `hostConnected()` | No | |
| `hostConnected()` | No | Can be enabled with `globalThis.litSsrCallConnectedCallback = true` |
| `hostDisconnected()` | No | |
| `hostUpdate()` | No | |
| `hostUpdated()` | No | |
Expand Down
5 changes: 3 additions & 2 deletions packages/lit-dev-content/site/docs/v3/ssr/dom-emulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ When running in Node, Lit automatically imports and uses a set of DOM shims, and
<!-- TODO(augustinekim) Consider replacing emojis below with icons https://github.com/lit/lit.dev/pull/880#discussion_r944821511 -->
| Property | Notes |
|-|-|
| `Element` | ⚠️ Partial <table><tbody><tr><td>`attributes`</td><td>✅</td><tr><td>`shadowRoot`</td><td>⚠️ Returns `{host: this}` if `attachShadow()` was called with `{mode: 'open'}`</td><tr><td>`setAttribute()`</td><td>✅</td><tr><td>`removeAttribute()`</td><td>✅</td><tr><td>`hasAttribute()`</td><td>✅</td><tr><td>`attachShadow()`</td><td>⚠️ Returns `{host: this}`</td><tr><td>`getAttribute()`</td><td>✅</td></tr></tbody></table> |
| `HTMLElement` | ⚠️ Empty class |
| `EventTarget` | ⚠️ Partial <table><tbody><tr><td>`addEventListener()`</td><td>✅</td><tr><td>`removeEventListener()`</td><td>✅</td><tr><td>`dispatchEvent()`</td><td>✅</td></tr></tbody></table> |
| `Element` | Inherits `EventTarget`<br> ⚠️ Partial <table><tbody><tr><td>`attributes`</td><td>✅</td><tr><td>`shadowRoot`</td><td>⚠️ Returns `{host: this}` if `attachShadow()` was called with `{mode: 'open'}`</td><tr><td>`setAttribute()`</td><td>✅</td><tr><td>`removeAttribute()`</td><td>✅</td><tr><td>`hasAttribute()`</td><td>✅</td><tr><td>`attachShadow()`</td><td>⚠️ Returns `{host: this}`</td><tr><td>`getAttribute()`</td><td>✅</td></tr></tbody></table> |
| `HTMLElement` | Inherits `Element`<br> ⚠️ Empty class |
| `CustomElementRegistry` | <table><tbody><tr><td>`define()`</td><td>✅</td></tr><tr><td>`get()`</td><td>✅</td></tr></tbody></table> |
| `customElements` | Instance of `CustomElementRegistry` |