-
-
Notifications
You must be signed in to change notification settings - Fork 520
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Add 'No-Build Workflows' doc, focusing on importmaps (for now) (#…
- Loading branch information
1 parent
551d77b
commit d87bef4
Showing
3 changed files
with
137 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,7 +63,7 @@ Writing raw `h` or `createElement` calls can be tedious. JSX has the advantage o | |
> | ||
> `import { html, render } from 'https://esm.sh/htm/preact/standalone'` | ||
For a more full example, see [Using Preact with HTM and ImportMaps](#using-preact-with-htm-and-importmaps), and for more information on HTM, check out its [documentation][htm]. | ||
For a more scalable solution, see [Import Maps -- Basic Usage](/guide/v10/no-build-workflows#basic-usage), and for more information on HTM, check out its [documentation][htm]. | ||
|
||
[htm]: https://github.com/developit/htm | ||
|
||
|
@@ -252,61 +252,20 @@ our best to fix these), and as such, these libraries could be the source of Type | |
errors. By setting `skipLibCheck`, you can tell TS that it doesn't need to do a full check of all | ||
`.d.ts` files (usually these are limited to your libraries in `node_modules`) which will fix these errors. | ||
|
||
### Using Preact with HTM and ImportMaps | ||
|
||
An [Import Map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) is a newer feature | ||
that allows you to control how browsers resolve module specifiers, usually to convert bare specifiers such as `preact` | ||
to a CDN URL like `https://esm.sh/preact`. While many do prefer the aesthetics import maps can provide, there are also | ||
real advantages to using them, such as more control over module resolution (read on to see how to alias) and solving | ||
the burden (as well as possible bugs) that comes with copying CDN URLs from file to file. | ||
|
||
Here's an example of a import map in use: | ||
#### Aliasing with Import Maps | ||
|
||
```html | ||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"preact": "https://esm.sh/[email protected]", | ||
"preact/": "https://esm.sh/[email protected]/", | ||
"htm/preact": "https://esm.sh/[email protected]/preact?external=preact" | ||
"preact": "https://esm.sh/[email protected]", | ||
"preact/": "https://esm.sh/[email protected]/", | ||
"react": "https://esm.sh/[email protected]/compat", | ||
"react/": "https://esm.sh/[email protected]/compat/", | ||
"react-dom": "https://esm.sh/[email protected]/compat", | ||
} | ||
} | ||
</script> | ||
|
||
<script type="module"> | ||
import { render } from 'preact'; | ||
import { useReducer } from 'preact/hooks'; | ||
import { html } from 'htm/preact'; | ||
export function App() { | ||
const [count, add] = useReducer((a, b) => a + b, 0); | ||
return html` | ||
<button onClick=${() => add(-1)}>Decrement</button> | ||
<input readonly size="4" value=${count} /> | ||
<button onClick=${() => add(1)}>Increment</button> | ||
`; | ||
} | ||
render(html`<${App} />`, document.body); | ||
</script> | ||
``` | ||
|
||
> **Note:** We use `?external=preact` in the example above as many CDNs will helpfully provide the | ||
> module you're asking for as well as its dependencies. However, this can trip up Preact as it (and | ||
> React too) expect to be loaded as singletons (only 1 instance active at a time). Using `?external` | ||
> tells `esm.sh` that it doesn't need to provide a copy of `preact`, we can handle that ourselves with | ||
> our import map | ||
You can even use import maps to support aliasing: | ||
|
||
```html | ||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"react": "https://esm.sh/[email protected]/compat", | ||
"react-dom": "https://esm.sh/[email protected]/compat" | ||
} | ||
} | ||
</script> | ||
``` | ||
See also [Import Maps -- Recipes and Common Patterns](/guide/v10/no-build-workflows#recipes-and-common-patterns) for more examples. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
--- | ||
name: No-Build Workflows | ||
description: 'Whilst build tools like Webpack, Rollup, and Vite are incredibly powerful and useful, Preact fully supports building applications without them.' | ||
--- | ||
|
||
# No-Build Workflows | ||
|
||
Whilst build tools like Webpack, Rollup, and Vite are incredibly powerful and useful, Preact fully supports building | ||
applications without them. | ||
|
||
No-build workflows are a way to develop web applications while forgoing build tooling, instead relying on the browser | ||
to facilitate module loading and execution. This is a great way to get started wtih Preact and can continue to work | ||
very well at all scales, but isn't entirely without difficulties. | ||
|
||
--- | ||
|
||
<div><toc></toc></div> | ||
|
||
--- | ||
|
||
## Import Maps | ||
|
||
An [Import Map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) is a newer feature | ||
that allows you to control how browsers resolve module specifiers, often to convert bare specifiers such as `preact` | ||
to a CDN URL like `https://esm.sh/preact`. While many do prefer the aesthetics import maps can provide, there are also | ||
objective advantages to the centralization of dependencies, such as easier versioning, reduced/removed duplication, and | ||
better access to more powerful CDN features. | ||
|
||
This isn't to say you need import maps, but for those choosing to forgo build tooling, they are a great option to at least | ||
be aware of. | ||
|
||
### Basic Usage | ||
|
||
[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) has a great deal of information on how to | ||
utilize import maps, but a basic example looks like the following: | ||
|
||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"preact": "https://esm.sh/[email protected]", | ||
"htm/preact": "https://esm.sh/[email protected]/preact?external=preact" | ||
} | ||
} | ||
</script> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
|
||
<script type="module"> | ||
import { render } from 'preact'; | ||
import { html } from 'htm/preact'; | ||
export function App() { | ||
return html` | ||
<h1>Hello, World!</h1> | ||
`; | ||
} | ||
render(html`<${App} />`, document.getElementById('app')); | ||
</script> | ||
</body> | ||
</html> | ||
``` | ||
|
||
We create a `<script>` tag with a `type="importmap"` attribute, and then define the modules we'd like to use | ||
inside of it as JSON. Later, in a `<script type="module">` tag, we can import these modules using bare specifiers, | ||
similiar to what you'd see in Node. | ||
|
||
> **Note:** We use `?external=preact` in the example above as https://esm.sh will helpfully provide the | ||
> module you're asking for as well as its dependencies -- for `htm/preact`, this means also providing a | ||
> copy of `preact`. However, Preact and many other libraries need to be used as singletons (only a single | ||
> active instance at a time) which creates a problem. | ||
> | ||
> By using `?external=preact`, we tell `esm.sh` that it shouldn't provide a copy of `preact`, we can handle | ||
> that ourselves. Therefore, the browser will use our importmap to resolve `preact`, using the same Preact | ||
> instance as the rest of our code. | ||
### Recipes and Common Patterns | ||
|
||
While not an exhaustive list, here are some common patterns and recipes you may find useful when working with | ||
import maps. If you have a pattern you'd like to see, [let us know](https://github.com/preactjs/preact-www/issues/new)! | ||
|
||
For these examples we'll be using https://esm.sh as our CDN -- it's a brilliant, ESM-focused CDN that's a bit | ||
more flexible and powerful than some others, but by no means are you limited to it. However you choose to serve | ||
your modules, make sure you're familiar with the policy regarding dependencies: duplication of `preact` and some | ||
other libraries will cause (often subtle and unexpected) issues. For `esm.sh`, we address this with the `?external` | ||
query parameter, but other CDNs may work differently. | ||
|
||
#### Preact with Hooks, Signals, and HTM | ||
|
||
```html | ||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"preact": "https://esm.sh/[email protected]", | ||
"preact/": "https://esm.sh/[email protected]/", | ||
"@preact/signals": "https://esm.sh/@preact/[email protected]?external=preact", | ||
"htm/preact": "https://esm.sh/[email protected]/preact?external=preact" | ||
} | ||
} | ||
</script> | ||
``` | ||
|
||
#### Aliasing React to Preact | ||
|
||
```html | ||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"preact": "https://esm.sh/[email protected]", | ||
"preact/": "https://esm.sh/[email protected]/", | ||
"react": "https://esm.sh/[email protected]/compat", | ||
"react/": "https://esm.sh/[email protected]/compat/", | ||
"react-dom": "https://esm.sh/[email protected]/compat", | ||
"@mui/material": "https://esm.sh/@mui/[email protected]?external=react,react-dom" | ||
} | ||
} | ||
</script> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters