Skip to content

Commit

Permalink
Merge pull request #24 from patricknelson/issue-23-example-docs
Browse files Browse the repository at this point in the history
Fix for #23: Better documentation explaining how to get started
  • Loading branch information
patricknelson authored Nov 21, 2023
2 parents 4ba67d6 + 3b8f29a commit 7023232
Show file tree
Hide file tree
Showing 44 changed files with 1,114 additions and 41 deletions.
120 changes: 85 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,64 +9,115 @@ DOM _or_ shadow DOM. Automatically forwards all slots and attributes to your Sve

**Demo:** https://svelte-retag.vercel.app/

## Core features
## Core Features

* 🌟 **Light DOM:** Allows you to render your Svelte components as custom elements in the light DOM as usual.
* 🎰 **Slots:** Supports default and named slots in the _light DOM_ (supports nesting).
* 🎰 **Slots & Nesting:** Supports default and named slots in the _light DOM_ (with nesting).
* 🧭 **Context:** Use `setContext()` and `getContext()` and just compose your components as custom elements as you
normally would ([see live tab demo](https://svelte-retag.vercel.app/)). Supports nesting.
***Vite HMR:** Unlike Svelte, these custom elements are also compatible with Vite's HMR. It avoids the
infamous `Failed to execute 'define' on 'CustomElementRegistry'` errors.
* 🏃‍♂️ **IIFE/UMD:** Supports building to `iife` and `umd` for eager rendering to the light DOM, as soon as the
parser encounters the custom element. Reduces CLS (Cumulative Layout Shift), making it interactive more quickly
_without_ waiting for `defer`'d scripts (such as modules).
***Composability:** `svelte-retag` gives you the flexility to use your component as you normally would within Svelte
_and_ as a custom element outside of Svelte (supporting both `<ExampleComponent />` and `<example-component>`).
_without_ waiting for `defer`'d scripts (such as modules).
***Composability:** `svelte-retag` gives you the flexibility to use your component as you normally would within
Svelte _and_ as a custom element outside of Svelte (supporting both `<ExampleComponent />` and `<example-component>`).
For details on how to use with PHP, Python, Ruby, etc., see [Backend Integration](#backend-integration) below.
* 💼 **Portability:** Enables the freedom to utilize your Svelte components anywhere custom elements are supported,
regardless of the stack (great for upgrading legacy applications).

## Why?

Svelte already allows you to compile your components to custom elements. However, it has a couple of flaws:

* All of your nested components have to be implemented as custom elements, since the render flag applies to everything.
* You have to use shadow DOM (Svelte 3, or Svelte 4 if you still want to use slots).
* You have to deal with lots of bugs.
* You loose many features Svelte has for inter-component communication.
* Svelte 3: You have to use shadow DOM (no light DOM compatibility at all)
* Svelte 4: You cannot use slots in the light DOM (https://github.com/sveltejs/svelte/issues/8963), which means no nesting
* No context support (https://github.com/sveltejs/svelte/issues/8987)
* Vite HMR doesn't work with custom elements (see comments of https://github.com/sveltejs/svelte/issues/8681)

## How do I use it?

### Installation
### Installation & Quick Start

```bash
npm install svelte-retag
```

### Demo code
If you're **starting from scratch**, create a new [Vite](https://vitejs.dev/) project like so:

1. `npm create vite@latest` and select `Svelte` as your framework and `JavaScript` as your variant (or `TypeScript` if
you prefer). Don't select `SvelteKit` if you're already running another backend (e.g. PHP or Python, [see below](#backend-integration)).
2. `cd` into your new project
3. Run `npm install svelte-retag`
4. Run `npm run dev` to start the Vite development server and open http://localhost:5173/ in your browser
5. Create your Svelte components and define your custom elements (web components) using `svelteRetag()` in `src/main.js` as described below, e.g.

```javascript
import svelteRetag from 'svelte-retag';
import HelloWorld from './HelloWorld.svelte';

svelteRetag({
component: HelloWorld,
tagname: 'hello-world',
});
```
6. In `index.html`, remove `<div id="app"></div>` and instead add your custom elements to your `index.html` (e.g.
`<hello-world greetperson="👩‍🚀"></hello-world>`).

**Note:** No modifications are required to your `vite.config.js` or `svelte.config.js` files. Keep in mind that the
`customElement` compiler option _does not_ need to be enabled since we are replacing that functionality entirely
with `svelte-retag`.

### <a id="backend-integration" />Backend Integration

If you're running a non-JavaScript backend such as PHP, Python, Ruby, etc. and would still like to use Vite (but cannot
rely solely on Vite for local development), see [Vite's Backend Integration documentation](https://vitejs.dev/guide/backend-integration.html).
This will guide you on how to run both your specific backend _and_ Vite's development server simultaneously.
#### Svelte vs. SvelteKit
Note that if you already have an existing backend, it is recommended that you just install `svelte` and not
`@sveltejs/kit` since the extra metaframework features of SvelteKit (such as routing) may not be necessary. SvelteKit is
now installed by default in the official documentation, so the extra complexity may be confusing when you are already
running a backend and just using `svelte-retag` to add web components into an existing site.
### Demo Code
Add the following to your main entrypoint. If you are using Vite, this would likely be `src/main.js`.
```javascript
import svelteRetag from 'svelte-retag';
import HelloWorld from 'hello-world.svelte';
import HelloWorld from './HelloWorld.svelte';
svelteRetag({
component: HelloWorld,
tagname: 'hello-world',
// Optional:
attributes: ['greetperson'],
shadow: false,
attributes: ['greetperson'], // Changes to these attributes will be reactively forwarded to your component
shadow: false, // Use the light DOM
href: '/your/stylesheet.css', // Only necessary if shadow is true
// Experimental:
hydratable: false,
});
```
And in the `HelloWorld.svelte` Svelte component:
```svelte
<script>
export let greetPerson = 'World';
</script>
<h1>Hello {greetPerson}!</h1>
```
Now anywhere you use the `<hello-world>` tag, you'll get a Svelte component. Note that you must set your tag
name
to [anything containing a dash](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements).

To align with future versions of Svelte, attributes are automatically converted to lowercase (following
To align with Svelte 4, **attributes** are automatically converted to lowercase (following
the [Lit-style naming convention](https://lit.dev/docs/components/properties/#observed-attributes)). So, `greetPerson`
on your component would be automatically made available as `greetperson` on your custom element.

Expand All @@ -76,34 +127,33 @@ on your component would be automatically made available as `greetperson` on your

### Options

| Option | Default | Description |
|------------|:------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| component | _(required)_ | The constructor for your Svelte component (from `import`) |
| tagname | _(required)_ | The custom element tag name to use ([must contain a dash](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements)) |
| attributes | `[]` | array - List of attributes to reactively forward to your component (does not reflect changes inside the component). <br> **Important:** Attributes must be the lowercase version of your Svelte component props ([similar to Lit](https://lit.dev/docs/components/properties/#observed-attributes)). |
| shadow | `false` | boolean - Should this component use shadow DOM.<br/> **Note:** Only basic support for shadow DOM is currently provided. See https://github.com/patricknelson/svelte-retag/issues/6. |
| href | `''` | link to your stylesheet - Allows you to ensure your styles are included in the shadow DOM (thus only required when `shadow` is set to `true`). |
| hydratable | `false` | If enabled, allows for SSR/SSG of custom elements managed by `svelte-retag` by including extra markup so that they can be initialized (or "hydrated") client-side from pre-rendered HTML. Enable this during SSR/SSG to allow for proper initialization. See [hydration demo here](https://svelte-retag.vercel.app/hydratable.html). <br><br>Note: Experimental. Compatible with light DOM rendering only. |
| Option | Default | Description |
|--------------|:------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `component` | _(required)_ | The constructor for your Svelte component (from `import`) |
| `tagname` | _(required)_ | The custom element tag name to use ([must contain a dash](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements)) |
| `attributes` | `[]` | Optional. List of attributes to reactively forward to your component (does not reflect changes inside the component). <br> **Important:** Attributes must be the lowercase version of your Svelte component props ([similar to Lit](https://lit.dev/docs/components/properties/#observed-attributes)). |
| `shadow` | `false` | Optional. Indicates if this component should use shadow DOM.<br/> **Note:** Only basic support for shadow DOM is currently provided. See https://github.com/patricknelson/svelte-retag/issues/6. |
| `href` | `''` | Optional. URL to your stylesheet. Allows you to ensure your styles are included in the shadow DOM. This option is only useful when `shadow` is set to `true`. |
| `hydratable` | `false` | Optional. If enabled, allows for SSR/SSG of custom elements managed by `svelte-retag` by including extra markup so that they can be initialized (or "hydrated") client-side from pre-rendered HTML. Enable this during SSR/SSG to allow for proper initialization. See [hydration demo here](https://svelte-retag.vercel.app/hydratable.html). <br><br>Note: Experimental. Compatible with light DOM rendering only. |

**Note:** For portability, `svelte-retag`'s API is fully backward compatible
with [`svelte-tag@^1.0.0`](https://github.com/crisward/svelte-tag).

## To Do

On the immediate horizon:
## Change Log

- [x] Migrate to Vitest for unit testing (see https://github.com/crisward/svelte-tag/pull/14)
- [x] Update logo
- [x] Fix nested slot support (https://github.com/patricknelson/svelte-retag/pull/5)
- [x] Better support for slots during early execution of IIFE compiled packages, i.e. use `MutationObserver` to watch
- Migrate to Vitest for unit testing (see https://github.com/crisward/svelte-tag/pull/14)
- Update logo
- Fix nested slot support (https://github.com/patricknelson/svelte-retag/pull/5)
- Better support for slots during early execution of IIFE compiled packages, i.e. use `MutationObserver` to watch
for light DOM slots during initial parsing (see https://github.com/patricknelson/svelte-retag/issues/7)
- [x] Support Lit-style lowercase props (see https://github.com/patricknelson/svelte-retag/pull/9)
- [x] Svelte 4 support (tested)
- [x] Support context (see https://github.com/patricknelson/svelte-retag/issues/10, PR
- Support Lit-style lowercase props (see https://github.com/patricknelson/svelte-retag/pull/9)
- Svelte 4 support (tested)
- Support context (see https://github.com/patricknelson/svelte-retag/issues/10, PR
at https://github.com/patricknelson/svelte-retag/pull/18)
- [x] Add demos (see https://github.com/patricknelson/svelte-retag/issues/11)
- Add demos to vercel site (see https://github.com/patricknelson/svelte-retag/issues/11)
- Add step-by-step instructions and provided a simple MVP example (https://github.com/patricknelson/svelte-retag/pull/24)

Milestones:
### Milestones:

- **v1:** ✅
- **v2:** Utilize Svelte 4's `customElement` syntax, i.e.
Expand Down
File renamed without changes.
File renamed without changes.
15 changes: 15 additions & 0 deletions demo/hello-world/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# svelte-retag: Hello World

This is an **MVP** demo that shows `svelte-retag` in action in its simplest form in local development with a
`HelloWorld.svelte` component implemented as a `<hello-world>` custom element.

To try it out yourself, make sure you have [Git](https://git-scm.com/downloads) and [Node](https://nodejs.org/) installed and then run:

```bash
git clone https://github.com/patricknelson/svelte-retag.git
cd svelte-retag/demo/hello-world
npm install
npm run dev
```

Then open your browser to [http://localhost:5173/](http://localhost:5173/) to view the demo.
13 changes: 13 additions & 0 deletions demo/hello-world/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/svelte-retag-favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>svelte-retag: Hello World</title>
</head>
<body>
<hello-world greetperson="👩‍🚀"></hello-world>
<script type="module" src="/src/main.js"></script>
</body>
</html>
File renamed without changes.
Loading

0 comments on commit 7023232

Please sign in to comment.