Ausnahme gefangen: SSL certificate problem: certificate is not yet valid 📌 Converting Lit Components to Enhance

🏠 Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeiträge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden Überblick über die wichtigsten Aspekte der IT-Sicherheit in einer sich ständig verändernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch übersetzen, erst Englisch auswählen dann wieder Deutsch!

Google Android Playstore Download Button für Team IT Security



📚 Converting Lit Components to Enhance


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

Last month we talked about using a Lit Component in an Enhance app. In this post, we’ll show you how to convert a Lit component into an Enhance component.

Why convert from Lit to Enhance?

Lit is a fine framework for building web components, but there are a few reasons you may want to convert a Lit component into an Enhance component.

  1. Flash of unregistered custom element (FOUCE). Since we have to wait until the custom element is registered you may see a brief flash of unstyled HTML as you page loads.
  2. Since web components are written in JavaScript, it’s very difficult to do progressive enhancement.
  3. Reduce client-side dependencies
  4. Remove TypeScript build step.

Our Lit Component

We’ll re-use the Lit component from the last post. Here’s the source as a reminder.

// public/my-element.js
import {LitElement, html, css} from 'lit';
export class MyElement extends LitElement {
 static properties = {
   greeting: {},
   planet: {},
 };
 static styles = css`
  :host {
    display: inline-block;
    padding: 10px;
    background: lightgray;
  }
  .planet {
    color: var(--planet-color, blue);
  }
`;

 constructor() {
   super();
   this.greeting = 'Hello';
   this.planet = 'World';
 }

 render() {
   return html`
    <span @click=${this.togglePlanet}
      >${this.greeting}
      <span class="planet">${this.planet}</span>
    </span>
  `;
 }

 togglePlanet() {
   this.planet = this.planet === 'World' ? 'Mars' : 'World';
 }
}
customElements.define('my-element', MyElement);

Now, we can use Lit components just like our Enhance components. For example, let’s create a new page app/pages/lit.html and populate it with the following lines:

<script type="module" src="/_public/my-element.js"></script>
<style>
 .mars {
   --planet-color: red;
 }
</style>
<my-element></my-element>
<hr />
<my-element class="mars" planet="Mars"></my-element>

The above HTML produces a page that looks like this:

Lit Demo

Solving the FOUCE problem

To make sure we don’t run into the FOUCE issue we’ll server-side render our component. This way, as soon as the page is rendered, our web component will be rendered with default content. Our Enhance version of the Lit component will look like this:

// app/elements/my-element.mjs
export default function Element ({ html, state }) {
 const { attrs } = state
 const { greeting = "Hello", planet = 'World'} = attrs
 return html`
<style>
:host {
 display: inline-block;
 background: lightgray;
}
.planet {
 color: var(--planet-color, blue);
}
</style>
<span>
 ${greeting}
 <span class="planet">${planet}</span>
</span>`
}

Then we can remove the script tag that points to our Lit version of the component.

<style>
 .mars {
   --planet-color: red;
 }
</style>
<my-element></my-element>
<hr />
<my-element class="mars" planet="Mars"></my-element>

Now when the page is loaded their is no FOUCE as our component styles have been hoisted to the head and we’ve sent our default content down the wire for the browser to render.

lit demo non-interactive

The only problem is we have no interactivity. When you click on either of the messages, the togglePlanet method is not fired as it doesn’t currently exist. However, we can fix this in the next step as Enhance excels at progressive enhancement.

Progressive Enhancement

Now that we have a server-side rendered version of our component that solves FOUCE and is displayed with or without JavaScript let’s get started adding interactivity to this component via progressive enhancement.

We’ll add a script tag to our single file component, which will load if and when JavaScript is available, adding interactivity to our component.

<script type="module">
 class MyElement extends HTMLElement {
   constructor() {
     super()
     this.planetSpan = this.querySelector('.planet')
     this.planetSpan.addEventListener('click', this.togglePlanet.bind(this))
   }

   static get observedAttributes() {
     return [ 'planet' ]
   }

   attributeChangedCallback(name, oldValue, newValue) {
     if (oldValue !== newValue) {
       if (name === 'planet') {
         this.planetSpan.textContent = newValue
       }
     }
   }

   togglePlanet() {
     let planet = this.getAttribute('planet') || 'World'
     this.planet = planet === 'World' ? 'Mars' : 'World';
   }

   set planet(value) {
     this.setAttribute('planet', value);
   }
 }

 customElements.define('my-element', MyElement)
</script>

Now, anytime you click on the component, the planet name will be toggled:

Lit Demo

Since we have implemented a plain vanilla web component, you can remove the Lit dependency. Lit has a relatively small bundle size, just 16.5 kb minified according to Bundlephobia, but every byte of JavaScript you remove from the client side helps with performance.

Also, you don’t need TypeScript, so you can remove that transpilation step in your build process to convert TypeScript into JavaScript.

Syntactical Sugar

But what if you really like the syntactical sugar that TypeScript or Lit Element give you? Well, you are in luck, as you can use the @enhance/element package to rid yourself of some boilerplate code.

The first step is to remove that script tag from your app/elements/my-element.mjs file so that it looks like this:

export default function Element ({ html, state }) {
 const { attrs } = state
 const { greeting = "Hello", planet = 'World'} = attrs
 return html`
<style>
:host {
 display: inline-block;
 background: lightgray;
}
.planet {
 color: var(--planet-color, blue);
}
</style>
<span>
 ${greeting}
 <span class="planet">${planet}</span>
</span>`
}

Effectively we are back to where we started when we first server-side rendered our component. The component in this state is not interactive.

We’ll need to add a new dependency to our project so run:

npm install @enhance/element

Now create a new file app/browser/my-element.mjs where we will contain our client-side code.

// app/browser/my-element.mjs
import enhance from '@enhance/element'

enhance('my-element, {
 attrs: [ 'planet' ],
 init(el) {
   this.planetSpan = el.querySelector('.planet')
   this.planetSpan.addEventListener('click', this.togglePlanet.bind(this))
 },
 render({ html, state }) {
   const { attrs={} } = state
   const { greeting='Hello', planet='World' } = attrs
   return html`
       <span>
         ${greeting}
         <span class="planet">${planet}</span>
       </span>
       `
 },
 togglePlanet() {
   let planet = this.getAttribute('planet') || 'World'
   this.setAttribute('planet', planet === 'World' ? 'Mars' : 'World')
 }
})

Finally, you’ll need to add a script tag to any HTML page you use my-element in.

<script type="module" src="/_public/pages/my-element.mjs"></script>

You’ll notice with this syntactical sugar version that we don’t need to add boilerplate code for observedAttributes, attributeChangedCallback and attribute setters as @enhance/element handles this for you.

However, you may have noticed that the render function in your client-side code mirror your server-side code. It seems wasteful for two reasons:

  1. You are re-rendering the entire element
  2. You are duplicating the render method in two spaces

Your first concern is invalid as Enhance Element does DOM diffing for you and only updates the parts of the DOM that have been changed, but how would you know that if I didn’t tell you?

The second point is more than valid so let’s remove that duplication.

Remove Duplication

We’ll update ourapp/browser/my-element.mjsfile with the following contents:

import enhance from '@enhance/element'
import Element from '../elements/my-element-sugar.mjs'

enhance('my-element, {
 attrs: [ 'planet' ],
 init(el) {
   this.planetSpan = el.querySelector('.planet')
   this.planetSpan.addEventListener('click', this.togglePlanet.bind(this))
 },
 render: Element,
 togglePlanet() {
   let planet = this.getAttribute('planet') || 'World'
   this.setAttribute('planet', planet === 'World' ? 'Mars' : 'World')
 }
})

The render function of our new file will be our previously created pure function for server-side rendering our web component. Enhance will make this file available under public/pages/my-element.mjs.

In conclusion

With a bit of extra work you can avoid common web component issues like FOUCE, while retaining interactivity. You can also reduce the complexity of your application by removing unnecessary builds steps.

...



📌 Converting Lit Components to Enhance


📈 66.47 Punkte

📌 Using Lit Components in an Enhance App


📈 47.73 Punkte

📌 JerryScript 1.0 lit/lit-char-helpers.c lit_read_code_unit_from_hex Pufferüberlauf


📈 46 Punkte

📌 Sharkoon RGB Lit 100 & Lit 200: Hinter Frontglas warten Leuchtmuster


📈 46 Punkte

📌 JerryScript 1.0 lit/lit-char-helpers.c lit_read_code_unit_from_hex memory corruption


📈 46 Punkte

📌 Converting React Class Components to Functional Components: A Checklist and Example


📈 41.99 Punkte

📌 Enhance Your React Apps with ShadCn Utilities and Components


📈 24.73 Punkte

📌 Medium CVE-2017-18604: Sitebuilder dynamic components project Sitebuilder dynamic components


📈 23.25 Punkte

📌 Typescript for React Components (or How To Write Components in React The Right Way)


📈 23.25 Punkte

📌 Understanding Function Components vs Class Components in 100 seconds.


📈 23.25 Punkte

📌 React Components 101: Building Reusable Components


📈 23.25 Punkte

📌 Function Components vs Class Components in React – With Examples


📈 23.25 Punkte

📌 Lightning Web Components: Custom Nested Components


📈 23.25 Punkte

📌 🔄 Class Components vs Functional Components: A Lifecycle Journey in React 🔄


📈 23.25 Punkte

📌 Embracing Modern React: Transitioning from Class Components to Functional Components


📈 23.25 Punkte

📌 Embracing Modern React: Transitioning from Class Components to Functional Components


📈 23.25 Punkte

📌 Implementing Higher Order Components (HOC) for Functional Components in ReactJS


📈 23.25 Punkte

📌 React Controlled Components V/S Uncontrolled Components


📈 23.25 Punkte

📌 Automotive: Apple soll an McLaren und Lit Motors interessiert sein


📈 23 Punkte

📌 Eerie Photos Take You Down China’s Neon-Lit Alleyways


📈 23 Punkte

📌 Automotive: Apple soll an McLaren und Lit Motors interessiert sein


📈 23 Punkte

📌 Stay lit with Tacklife's discounted Electric Arc Lighter for $8


📈 23 Punkte

📌 LIT Creations African CMS SQL injection


📈 23 Punkte

📌 SilentiumPC Astrum AT6V: Edge-Lit-Fenster und Punkte-Front fallen auf


📈 23 Punkte

📌 GE Employees Lit Up with Sensitive Doc Breach


📈 23 Punkte

📌 JerryScript 4e58ccf68070671e1fff5cd6673f0c1d5b80b166 lit-char-helpers.c lit_char_to_utf8_bytes memory corruption


📈 23 Punkte

📌 Eerie Photos Take You Down China’s Neon-Lit Alleyways


📈 23 Punkte

📌 Talos II Lit - a reduced cost version of our legenday Talos II mainboard with open firmware


📈 23 Punkte

📌 LIT Creations Sql Injection Vulnerability


📈 23 Punkte

📌 JerryScript 2.2.0 lit-strings.c lit_read_code_unit_from_utf8 heap-based overflow


📈 23 Punkte

📌 Samsung 65-inch QN90B QLED TV review: The best TV for brightly lit spaces


📈 23 Punkte

📌 Stay lit with Tacklife's discounted Electric Arc Lighter for $8


📈 23 Punkte

📌 Wofür steht Lit?


📈 23 Punkte

📌 Keep your desk lit and your phones charged with these lamps


📈 23 Punkte











matomo