npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@11ty/is-land

v4.0.0

Published

A framework independent partial hydration islands architecture implementation.

Downloads

2,730

Readme

<is-land>

A new performance-focused way to add interactive client-side components to your web site.

Or, more technically: a framework independent partial hydration islands architecture implementation.

Features:

  • Easy to add to existing components
  • Zero dependencies
  • Not tightly coupled to a server framework or site generator tool.
  • Small footprint (5 kB minimized; 1.61 kB with Brotli compression)
  • Server-rendered (SSR) component examples available for SSR-friendly frameworks (Lit, Svelte, Vue, Preact are provided)

Examples for:

Integrations in the wild:

Installation

npm install @11ty/is-land

Add is-land.js to your primary bundle. It can be deferred and/or loaded asynchronously.

When using with web components it must be the first custom element defined (via customElements.define) on the page. Choose your style:

<script type="module" src="/is-land.js"></script>
<script type="module">
import "/is-land.js";
</script>

The framework autoinit examples shown below now require a separate is-land-autoinit.js file too.

Usage

<is-land>This is an island.</is-land>

Add any number of loading conditions to this tag to control how and when the island is initialized. You can mix and match:

  • on:visible
  • on:idle
  • on:interaction (defaults to touchstart,click)
    • Change events with on:interaction="mouseenter,focusin"
  • on:media
    • Viewport size: on:media="(min-width: 64em)"
    • Reduced motion:
      • Opt-in with on:media="(prefers-reduced-motion)"
      • Opt-out with on:media="(prefers-reduced-motion: no-preference)"
  • Save Data (read about Save Data on MDN)
    • Opt-in with on:save-data
    • Opt-out with on:save-data="false"
<is-land on:visible on:idle>
  <!-- your HTML here -->

  <is-land on:media="(min-width: 64em)">
    <!-- Islands can be nested -->
    <!-- Islands inherit all of their parents’ loading conditions -->
  </is-land>
</is-land>

Controlling Fallback Content

Pre-JS

<is-land on:visible on:idle>
  <vanilla-web-component>
    Put your pre-JS fallback content in your web component.
  </vanilla-web-component>
</is-land>

Post-JS with <template>

Place any post-JS content inside of one or more <template data-island> elements anywhere in the <is-land>. These will be swapped with their template content. You can nest an <is-land> in there if you want!

<is-land on:visible on:idle>
  <template data-island>
    <vanilla-web-component>
      This component is post-JS.
    </vanilla-web-component>
  </template>
</is-land>
  • Use data-island="replace" to replace the contents of the <is-land> with the template.
  • Use data-island="once" to run a template’s contents once per page (keyed from template contents). (New in v2.0.1)

Run your own custom JavaScript, load your own CSS

Embed a script inside the template to run custom JS when the island’s loading conditions have been satisfied!

<is-land on:visible>
  <template data-island>
    <!-- CSS -->
    <style>/* My custom CSS */</style>
    <link rel="stylesheet" href="my-css-file.css">

    <!-- JS -->
    <script type="module">console.log("Hydrating!");</script>
    <script type="module" src="my-js-file.js"></script>
  </template>
</is-land>

You can also use the ready attribute for styling, added to the <is-land> when the island has been hydrated.

<style>
is-land[ready] {
  background-color: lightgreen;
}
</style>

Framework Support

Demos and source in the HTML are available for each framework listed here. These examples require the is-land-autoinit.js JavaScript file (in addition to is-land.js).

autoinit

Use the autoinit and import attributes together to import a third party library (or component code). autoinit can be one of petite-vue, vue, preact, or svelte. It is recommended to use a self-hosted framework library (future Eleventy integrations will automate this for you).

<is-land on:visible autoinit="petite-vue" import="https://unpkg.com/[email protected]/dist/petite-vue.es.js" v-scope="{ name: 'post-JS' }">
  Hello from <span v-html="name">pre-JS</span>
</is-land>

<!-- when import maps support is better, this simplifies with an entry for petite-vue in your import map -->
<is-land on:visible import="petite-vue" v-scope="{ name: 'post-JS' }">
  Hello from <span v-html="name">pre-JS</span>
</is-land>

Petite Vue

  • Small library (8K)
  • Rendering modes: Client
  • Progressive-enhancement friendly (full control of fallback content)
  • Support for autoinit
<is-land on:visible autoinit="petite-vue" import="https://unpkg.com/[email protected]/dist/petite-vue.es.js" v-scope="{ name: 'post-JS' }">
  Hello from <span v-html="name">pre-JS</span>
</is-land>

Vue

  • Larger library (51 kB)
  • Rendering modes: Client-only, Server-only, Server + Client (Hydration)
  • Support for autoinit
<is-land on:visible>
  <div id="vue-app">
    Hello from <span v-html="name">pre-JS</span>
  </div>

  <template data-island>
    <script type="module">
    import { createApp } from "https://unpkg.com/[email protected]/dist/vue.esm-browser.prod.js";

    createApp({
      data: () => ({ name: "post-JS" })
    }).mount("#vue-app")
    </script>
  </template>
</is-land>

Svelte

  • Smaller library (12 kB)
  • Rendering modes: Client-only, Server-only, Server + Client (Hydration)
    • Requires a compiler for both client and server modes (tighter server coupling)
  • Support for autoinit

This example uses an Eleventy/Svelte integration to compile a Svelte component.

{% assign component = "./lib/svelte/my-component.svelte" | svelte %}
<is-land on:visible autoinit="svelte" import="{{ component.clientJsUrl }}"></is-land>
<script>
  // using export to allow overrides via props
  export let name = 'world';

  let count = 0;

  function handleClick() {
    count += 1;
  }
</script>

<style>
  h1 { color: red }
</style>

<h1>Hello {name}</h1>

<button on:click={handleClick}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

Preact

  • Very small library (~5 kB)
  • Rendering modes: Client-only, Server-only, Server + Client (Hydration)
  • Support for autoinit

This example uses htm instead of JSX.

<is-land on:visible autoinit="preact" import="/lib/preact/preact-component.js"></is-land>
import { html, render } from 'https://unpkg.com/htm/preact/index.mjs?module'

function App (props) {
  return html`<p><strong>Hello ${props.name}!</strong></p>`;
}

export default function(el) {
  render(html`<${App} name="from Preact" />`, el);
}

Lit

  • Small library (~7 kB)
  • Rendering modes: Client-only, Server + Client (Hydration)
    • Note: Server-only is not supported: it requires Declarative Shadow DOM support to work without JS.
  • No support for autoinit
<is-land on:visible import="./lib/lit/lit-component.js">
  <lit-component name="Post-JS">Pre-JS Content</lit-web-component>
</is-land>
import {html, css, LitElement} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";

customElements.define('lit-component', class extends LitElement {
  static properties = {
    name: {type: String},
  };

  render() {
    return html`<p>Hello, ${this.name || "Stranger"}!</p>`;
  }
});

Alpine.js

  • Smaller library (15 kB)
  • Rendering modes: Client-only
  • No autoinit but it is not needed (functionality included for-free by Alpine.js)
<is-land on:visible import="https://unpkg.com/alpinejs">
  <div x-data="{ count: 0 }">
    Hello from Alpine.js!

    <button @click="count++">⬆️</button> <button @click="count--">⬇️</button> <span x-text="count"></span>
  </div>
</is-land>