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

code displays in browser after lit-html is loaded twice #1066

Closed
DanielKehoe opened this issue Aug 20, 2020 · 2 comments
Closed

code displays in browser after lit-html is loaded twice #1066

DanielKehoe opened this issue Aug 20, 2020 · 2 comments

Comments

@DanielKehoe
Copy link

All my LitElement-based custom elements failed overnight with no changes on my part. There were new releases of lit-element (version 2.4.0) and lit-html (version 1.3.0) published 12 hours ago.

I’ve built my custom elements using ES6 imports for lit-element and lit-html delivered from the JSPM CDN, for use directly in the browser without Node or build tooling. My ultimate use case is to provide tutorials and examples of web components that don’t require JavaScript build tooling or frameworks.

In my import statements, I’ve specified lit-element version 2.3.1 and lit-html version 1.2.1. I’ve checked what’s delivered from the JSPM CDN and for https://jspm.dev/lit-element@2.3.1 I get:

import "/npm:lit-html@1/lib/shady-render.js";
import "/npm:lit-element@2.3.1/lib/updating-element.js";
import "/npm:lit-element@2.3.1/lib/decorators";
import "/npm:lit-html@1/lit-html.js";
import "/npm:lit-element@2.3.1/lib/css-tag";
export * from "/npm:lit-element@2.3.1";

For https://jspm.dev/lit-html@1.2.1 I get:

import "/npm:lit-html@1.2.1/lib/directive.js";
import "/npm:lit-html@1.2.1/lib/dom.js";
import "/npm:lit-html@1.2.1/lib/part.js";
import "/npm:lit-html@1.2.1/lib/template.js";
import "/npm:lit-html@1.2.1/_/2c730f20.js";
import "/npm:lit-html@1.2.1/lib/template-factory.js";
import "/npm:lit-html@1.2.1/lib/render.js";
export * from "/npm:lit-html@1.2.1";

I’m surprised that my LitElement-based custom elements fail after a new version release when I’ve specified previous working versions.

The custom elements are all used on the page at https://assets.yax.com/. I’ve fixed the problem by updating the import statements to specify lit-element version 2.4.0 and lit-html version 1.3.0.

Here’s a partial screenshot of the page before the fix:

fails-after-new-release

In the <yax-navbar> and <yax-footer> elements, I’m importing

import { LitElement } from 'https://jspm.dev/lit-element@2.3.1';
import { html } from 'https://jspm.dev/lit-html@1.2.1';

The <yax-navbar> and <yax-footer> elements display [object Object]

In the <yax-markdown> tag I’m importing

import prismjs from 'https://jspm.dev/prismjs';
import commonmark from 'https://jspm.dev/commonmark';
import { LitElement, html } from 'https://jspm.dev/lit-element@2.3.1';
import { unsafeHTML } from 'https://jspm.dev/lit-html@1.2.1/directives/unsafe-html.js';

The <yax-markdown> tag displays

(part) => { if (!(part instanceof NodePart)) { throw new Error('unsafeHTML can only be used in text bindings'); } const previousValue = previousValues.get(part); if (previousValue !== undefined && isPrimitive(value) && value === previousValue.value && part.value === previousValue.fragment) { return; } const template = document.createElement('template'); template.innerHTML = value; // innerHTML casts to string internally const fragment = document.importNode(template.content, true); part.setValue(fragment); previousValues.set(part, { value, fragment }); } (part) => { if (!(part instanceof NodePart)) { throw new Error('unsafeHTML can only be used in text bindings'); } const previousValue = previousValues.get(part); if (previousValue !== undefined && isPrimitive(value) && value === previousValue.value && part.value === previousValue.fragment) { return; } const template = document.createElement('template'); template.innerHTML = value; // innerHTML casts to string internally const fragment = document.importNode(template.content, true); part.setValue(fragment); previousValues.set(part, { value, fragment }); }

In another five tags I’m importing

import { LitElement, html } from 'https://jspm.dev/lit-element@2.3.1';
import { until } from 'https://jspm.dev/lit-html@1.2.1/directives/until.js';
import { unsafeHTML } from 'https://jspm.dev/lit-html@1.2.1/directives/unsafe-html.js';

These five tags display

(part) => { let state = _state.get(part); if (state === undefined) { state = { lastRenderedIndex: _infinity, values: [], }; _state.set(part, state); } const previousValues = state.values; let previousLength = previousValues.length; state.values = args; for (let i = 0; i < args.length; i++) { // If we've rendered a higher-priority value already, stop. if (i > state.lastRenderedIndex) { break; } const value = args[i]; // Render non-Promise values immediately if (isPrimitive(value) || typeof value.then !== 'function') { part.setValue(value); state.lastRenderedIndex = i; // Since a lower-priority value will never overwrite a higher-priority // synchronous value, we can stop processing now. break; } // If this is a Promise we've already handled, skip it. if (i < previousLength && value === previousValues[i]) { continue; } // We have a Promise that we haven't seen before, so priorities may have // changed. Forget what we rendered before. state.lastRenderedIndex = _infinity; previousLength = 0; Promise.resolve(value).then((resolvedValue) => { const index = state.values.indexOf(value); // If state.values doesn't contain the value, we've re-rendered without // the value, so don't render it. Then, only render if the value is // higher-priority than what's already been rendered. if (index > -1 && index < state.lastRenderedIndex) { state.lastRenderedIndex = index; part.setValue(resolvedValue); part.commit(); } }); } }

The code is publicly available in the repo at https://github.com/yaxdotcom/assets-yax-com. For example, the simple <yax-footer> tag is here: https://github.com/yaxdotcom/assets-yax-com/blob/master/scripts/custom-tags/yax-footer.js.

Is there something I’m doing wrong in my use of import statements for lit-element and lit-html? Or perhaps the problem is in my use of the JSPM CDN? I'd like to improve my code and make sure new releases don't break these custom elements.

@DanielKehoe
Copy link
Author

DanielKehoe commented Aug 20, 2020

Thanks to https://github.com/daKmoR on the Polymer Slack channel, I was able to improve the imports to avoid importing lit-html twice.

import { LitElement, html } from 'https://jspm.dev/lit-element@2.3.1';
import { until } from 'https://jspm.dev/lit-html@1/directives/until.js';
import { unsafeHTML } from 'https://jspm.dev/lit-html@1/directives/unsafe-html.js';

But I still have a question:

  • Why did I have a failure despite pinning the versions in the imports?

@DanielKehoe
Copy link
Author

Guy Bedford of JSPM says, “The pin applies only to the top-level import, not to sub-dependencies. The way to pin dependencies is to generate an import map for the application. This is what is coming out in the next release of jspm soon.” So that explains why I had a failure.

I'm delighted to get great support from devs on the Polymer Slack channel as well as the JSPM Discord forum. Thanks!

I'm closing this issue as I've identified the failure was caused by my poor implementation of imports (I loaded lit-html twice) combined with some ignorance about how pinning versions works with JSPM.

@DanielKehoe DanielKehoe changed the title lit-element and lit-html fail after new release with import from JSPM CDN code displays in browser after lit-html is loaded twice Aug 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant