-
-
Notifications
You must be signed in to change notification settings - Fork 520
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
docs: Add 'No-Build Workflows' doc, focusing on importmaps (for now) #1175
Changes from all commits
a950fc1
8e51ed8
1961ad5
d06f30f
fd380c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
--- | ||
name: No-Build Workflows | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switched this over to 'No-Build Workflows' instead, as an importmap-specific page felt unnecessary. Granted, this might be a bit confusing for Deno users, but I felt that the ability to more info here in the future for buildless workflows is of more benefit. Will think on it, anyhow. Opinions certainly welcome (as always). |
||
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> | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to refer to import maps as more scalable? Obviously HTTP imports have "issues", but I'm not sure of the language here.