Exploring How lit-html Works: render Function
Tags: javascript, typescript, webcomponents, devjournal
Published: 2020-01-09 09:37:47

In this series, How lit-html works, I will explore (not explain) internal implementation of [lit-html](https://lit-html.polymer-project.org/).

In the last 4 posts, we saw what `TemplateResult` and `SVGTemplateResult` looks like.

From now on, I will explore the `render` function.

# `render` function

`render` function is defined beside a variable whose name is `parts`.

```typescript
export const parts = new WeakMap<Node, NodePart>();

export const render =
    (result: unknown,
     container: Element|DocumentFragment,
     options?: Partial<RenderOptions>) => {
      let part = parts.get(container);
      if (part === undefined) {
        removeNodes(container, container.firstChild);
        parts.set(
            container,
            part = new NodePart(
                {
                  templateFactory,
                  ...options,
                },
                undefined));
        part.appendInto(container);
      }
      part.setValue(result);
      part.commit();
    };
```

This function receives two arguments. First one is an instance of `TemplateResult` or `SVGTemplateResult`. Second is the `container`, which is a DOM parent inside which the content is rendered.

## Searching Cache

Firstly, `render` function checks if an instance of `NodePart` class is stored in `parts` with the `container` as a key.

##  Create a New `NodePart`

If a cached NodePart instance is not found, then all the direct children of the container are removed by `removeNodes` function.

```typescript
export const removeNodes =
    (container: Node, start: Node|null, end: Node|null = null): void => {
      while (start !== end) {
        const n = start!.nextSibling;
        container.removeChild(start!);
        start = n;
      }
    };
```

The algorithm is quite similar to `reparentNodes` function that I saw in [the last post](https://dev.to/nozomuikuta/draft-exploring-how-lit-html-works-templateresult-and-svgtemplateresult-constructors-4-3p1i). Only difference is how the functions manipulate DOM tree.

After cleaning up the `container`, a new NodePart instance is registered into the `parts` and is associated with with the `container`.

## Rendering

Finally, `render` function lets the NodePart instance call three methods of it, but I will explore this part in later posts. Instead, I will recap what WeakMap is, because it's worth using in other development as well.

# WeakMap

[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) says  that the WeakMap object is a collection of key/value pairs and the keys must be objects.

The word "weak" here means that the reference from weak map to the key object doesn't prevent the object from being garbage collected.

Thus, it is really convenient to store data in a WeakMap as a cache. We don't have to check, every time we do something or periodically the data of the object, whether the data is no longer used.

Just for information, there are also [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set), [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet), each of which has suitable situation.

# Summary

So far, I learned the following points:

- `render` function caches NodePart.
- `render` function creates a new NodePart if no corresponding cache is found.
- `render` function delegates actual rendering process to the NodePart instance.

From the next post, I will dive into the NodePart class.