Add snowpack as an example project. (#11)

* Initial tests set up

This adds tests using uvu (we can switch if people want) and restructures things a bit so that it's easier to test.

Like in snowpack you set up a little project. In our tests you can say:

```js
const result = await runtime.load('/blog/hello-world')
```

And analyze the result. I included a `test-helpers.js` which has a function that will turn HTML into a cheerio instance, for inspecting the result HTML.

* Bring snowpack example in

* Formatting
This commit is contained in:
Matthew Phillips 2021-03-19 17:17:38 -04:00 committed by GitHub
parent 17c3c98f07
commit 2082001ff8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
198 changed files with 25117 additions and 0 deletions

3
examples/snowpack/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.DS_Store
build
node_modules

View file

@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}

View file

@ -0,0 +1,15 @@
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-rational-order',
'stylelint-config-prettier',
],
rules: {
'at-rule-no-unknown': [
true,
{ ignoreAtRules: ['use', 'each', 'for', 'mixin', 'extend', 'include'] },
], // allow Sass syntax,
'no-descending-specificity': null,
},
syntax: 'scss',
};

21
examples/snowpack/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Fred K. Schott
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,37 @@
# Astro Demo
## Getting setup
1. Checkout Astro at: https://github.com/snowpackjs/astro
1. Install and build Astro:
```shell
npm install
npm run build
```
2. Link Astro:
```shell
npm link
```
2. In this project link Astro and install other deps:
```shell
npm link astro
npm install
```
3. Run the Astro dev environment.
```shell
npm run start
```
4. Build the website. (Not yet working.)
```shell
npm run build
```

View file

@ -0,0 +1,6 @@
export default {
projectRoot: '.',
hmxRoot: './astro',
dist: './_site'
}

View file

@ -0,0 +1,12 @@
<Component>
<section class="grid-banner">
<div class="notification">
<div class="container">
Snowpack 3.0 is out now!
<a href="/posts/2021-01-13-snowpack-3-0">
Read the announcement post →
</a>
</div>
</div>
</section>
</Component>

View file

@ -0,0 +1,29 @@
import {h} from 'preact';
import {format as formatDate, parseISO} from 'date-fns';
export default function Card({ item }) {
return (
<article class="card">
<a
href={item.url}
style="text-decoration: none; color: initial; flex-grow: 1;"
>
{item.img ? (
<img
class="card-image card-image-small"
src={item.img}
alt=""
style={{ background: item.imgBackground || undefined }}
/>
) : (
<div class="card-image card-image-small"></div>
)}
<div class="card-text">
<h3 class="card-title">{item.title}</h3>
{item.date && <time class="snow-toc-link">{ formatDate(parseISO(item.date), 'MMMM d, yyyy') }</time>}
{item.description && <p style="margin: 0.5rem 0 0.25rem;">{ item.description }</p>}
</div>
</a>
</article>
);
}

View file

@ -0,0 +1,13 @@
import {h} from 'preact';
export default function CompanyLogo({ user }) {
return (
<a href={user.url} target="_blank" rel="noopener noreferrer nofollow">
{user.img ? (
<img class="company-logo" src={user.img} alt={user.name} />
) : (
<span>{user.name}</span>
)}
</a>
);
}

View file

@ -0,0 +1,22 @@
import { BLOCKS, MARKS } from '@contentful/rich-text-types';
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';
const options = {
renderMark: {
[MARKS.BOLD]: (text) => `<custom-bold>${text}<custom-bold>`,
},
renderNode: {
[BLOCKS.PARAGRAPH]: (node, next) =>
`<custom-paragraph>${next(node.content)}</custom-paragraph>`,
},
};
export function RichTextDocument({ document }) {
return (
<div
dangerouslySetInnerHTML={{
html: documentToHtmlString(document, options),
}}
/>
);
}

View file

@ -0,0 +1,47 @@
<Component>
<div class="hero">
<div class="section">
<h1 class="header-snowpack">Snowpack</h1>
<p class="header-snowpack-subtitle">The faster frontend build tool.</p>
<div class="hero-cta">
<a href="/tutorials/quick-start" class="button button-primary">Get started</a>
<div style="margin: 0.5rem"></div>
<button id="copy-button" class="copy-button hidden-mobile" data-clipboard-text="npm install snowpack">
<span class="faded" style="margin-right: 0.75rem;">$</span>
<span id="copy-button-text">npm install snowpack</span>
<svg style="height: 22px;width: 22px;margin: -0.1rem -0.1rem 0 0.75rem;" aria-hidden="true" focusable="false" data-prefix="far" data-icon="clone" class="svg-inline--fa fa-clone fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 512 512">
<path fill="currentColor" d="M464 0H144c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h48c26.51 0 48-21.49 48-48V48c0-26.51-21.49-48-48-48zM362 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h42v224c0 26.51 21.49 48 48 48h224v42a6 6 0 0 1-6 6zm96-96H150a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v308a6 6 0 0 1-6 6z"></path>
</svg>
</button>
<script type="module">
import Clipboard from 'https://cdn.skypack.dev/pin/clipboard@v2.0.6-eJjsV6JYCJOnOsq3YfEc/min/clipboard.js';
const clippy = new Clipboard('.copy-button');
const copyText = document.getElementById('copy-button').innerHTML;
clippy.on('success', function (e) {
document.getElementById('copy-button').style.minWidth = document.getElementById('copy-button').offsetWidth;
console.info('Trigger:', e);
document.getElementById('copy-button').innerHTML = '<span>copied to clipboard!</span>';
document.getElementById('copy-button').addEventListener("mouseleave", function( event ) {
document.getElementById('copy-button').innerHTML = copyText;
}, false);
setTimeout(() => {
e
.trigger
.classList
.remove('active')
}, 1000);
e.clearSelection();
});
</script>
</div>
<div class="hero-cta">
<!-- Place this tag where you want the button to render. -->
<div class="hidden-mobile" style="text-align: center; height: 36px;">
<a class="github-button" href="https://github.com/snowpackjs/snowpack" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star snowpackjs/snowpack on GitHub">Star</a >
</div>
</div>
</div>
</div>
</Component>

View file

@ -0,0 +1,86 @@
<Component>
<nav class="snow-toc">
<ol class="snow-toc-contents">
<li class="snow-toc-section">
<span class="snow-toc-section-header">Concepts</span>
<ol class="snow-toc-section-items">
<li>
<a class="snow-toc-link" href="/concepts/how-snowpack-works">How Snowpack Works</a>
</li>
<li>
<a class="snow-toc-link" href="/concepts/dev-server">The Dev Server</a>
</li>
<li>
<a class="snow-toc-link" href="/concepts/build-pipeline">The Build Pipeline</a>
</li>
<li>
<a class="snow-toc-link" href="/concepts/hot-module-replacement">Fast Refresh & HMR</a>
</li>
</ol>
</li>
<li class="snow-toc-section">
<span class="snow-toc-section-header">Getting Started</span>
<ol class="snow-toc-section-items">
<li>
<a class="snow-toc-link" href="/tutorials/quick-start">Quick Start</a>
</li>
<li>
<a class="snow-toc-link" href="/tutorials/getting-started">Getting Started</a>
</li>
<li>
<a class="snow-toc-link" href="/tutorials/react">React</a>
</li>
<li>
<a class="snow-toc-link" href="/tutorials/svelte">Svelte</a>
</li>
</ol>
</li>
<li class="snow-toc-section">
<a class="snow-toc-link" href="/guides">
<span class="snow-toc-section-header">Guides</span></a>
</li>
<li class="snow-toc-section">
<span class="snow-toc-section-header">Reference</span>
<ol class="snow-toc-section-items">
<li>
<a class="snow-toc-link" href="/reference/configuration">snowpack.config.js</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/cli-command-line-interface">Command Line API</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/javascript-interface">JavaScript API</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/plugins">Plugin API</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/environment-variables">Environment Variables</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/hot-module-replacement">HMR API</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/supported-files">Supported Files</a>
</li>
<li>
<a class="snow-toc-link" href="/reference/common-error-details">Common Errors</a>
</li>
</ol>
</li>
<li class="snow-toc-section">
<a class="snow-toc-link" href="/plugins">
<span class="snow-toc-section-header">Plugin Catalog</span></a>
</li>
<li class="snow-toc-section">
<a class="snow-toc-link" href="/news">
<span class="snow-toc-section-header">Community & News</span></a>
</li>
</ol>
</nav>
</Component>

View file

@ -0,0 +1,92 @@
<Component>
<nav class="snow-nav">
<button id="toc-drawer-button" class="snow-nav-mobile-open" type="button" aria-expanded="false" aria-controls="nav-primary">
<svg focusable="false" class="snow-icon" role="img" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 448 512">
<title>Toggle mobile menu</title>
<path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"></path>
</svg>
</button>
<a class="snow-nav-logo snow-logo" href="/">
<svg class="snow-logo-icon" viewbox="0 0 640 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(-1.000000, 0.000000)" fill-rule="nonzero">
<path d="M635.92,462.7 L347.92,14.7 C342.03,5.54 331.89,0 321,0 C310.11,0 299.97,5.54 294.08,14.7 L6.08,462.7 C-0.250773249,472.547007 -0.699487627,485.064987 4.91,495.34 C10.522069,505.612419 21.2945349,512 33,512 L609,512 C620.71,512 631.48,505.61 637.09,495.33 C642.699457,485.058495 642.250708,472.543372 635.92,462.7 Z M321,91.18 L406.39,224 L321,224 L257,288 L218.94,249.94 L321,91.18 Z" id="Shape"></path>
</g>
</svg>
<span class="snow-logo-type">Snowpack</span>
</a>
<div class="search-form">
<input type="text" name="search" placeholder="Search documentation..." class="search-form-input" id="search-form-input">
<span class="search-form-hint">
<span class="sr-only">Press </span>
<kbd class="font-sans"><abbr title="Command" style="text-decoration: none;">⌘</abbr></kbd>
<span class="sr-only"> and </span>
<kbd class="font-sans">K</kbd>
<span class="sr-only"> to search</span>
</span>
</div>
<div style="flex-grow: 1"></div>
<a href="https://github.com/snowpackjs/snowpack/releases" target="_blank" class="snow-nav-link snow-nav-version">
{`v${props.version}`}
</a>
<a href="https://github.com/snowpackjs/snowpack" target="_blank" class="snow-nav-link snow-nav-link__desktop">
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" class="snow-icon" role="img" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 496 512">
<path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path>
</svg>
</a>
<a href="https://twitter.com/snowpackjs" target="_blank" class="snow-nav-link snow-nav-link__desktop">
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="twitter" class="snow-icon" role="img" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 512 512">
<path fill="currentColor" d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path>
</svg>
</a>
<a href="https://discord.gg/snowpack" target="_blank" class="snow-nav-link snow-nav-link__desktop">
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="discord" class="snow-icon" role="img" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 210 240"><path d="M84.79 90.45c-6.45 0-11.55 5.66-11.55 12.57s5.21 12.57 11.55 12.57c6.45 0 11.55-5.66 11.55-12.57.11-6.91-5.09-12.57-11.55-12.57zm41.32 0c-6.45 0-11.55 5.66-11.55 12.57s5.21 12.57 11.55 12.57c6.45 0 11.55-5.66 11.55-12.57s-5.09-12.57-11.55-12.57z"/><path fill="currentColor" d="M185.4 0H24.6C11.04 0 0 11.04 0 24.72v162.24c0 13.68 11.04 24.72 24.6 24.72h136.08l-6.36-22.2 15.36 14.28 14.52 13.44L210 240V24.72C210 11.04 198.96 0 185.4 0zm-46.32 156.72s-4.32-5.16-7.92-9.72c15.72-4.44 21.72-14.28 21.72-14.28-4.92 3.24-9.6 5.52-13.8 7.08-6 2.52-11.76 4.2-17.4 5.16-11.52 2.16-22.08 1.56-31.08-.12-6.84-1.32-12.72-3.24-17.64-5.16-2.76-1.08-5.76-2.4-8.76-4.08-.36-.24-.72-.36-1.08-.6-.24-.12-.36-.24-.48-.36-2.16-1.2-3.36-2.04-3.36-2.04s5.76 9.6 21 14.16c-3.6 4.56-8.04 9.96-8.04 9.96-26.52-.84-36.6-18.24-36.6-18.24 0-38.64 17.28-69.96 17.28-69.96 17.28-12.96 33.72-12.6 33.72-12.6l1.2 1.44c-21.6 6.24-31.56 15.72-31.56 15.72s2.64-1.44 7.08-3.48c12.84-5.64 23.04-7.2 27.24-7.56.72-.12 1.32-.24 2.04-.24 7.32-.96 15.6-1.2 24.24-.24 11.4 1.32 23.64 4.68 36.12 11.52 0 0-9.48-9-29.88-15.24l1.68-1.92s16.44-.36 33.72 12.6c0 0 17.28 31.32 17.28 69.96 0 0-10.2 17.4-36.72 18.24z"/></svg>
</a>
</nav>
<script>
function handleMobileNav(evt) {
evt.preventDefault();
/*If hidden-mobile class is enabled that means we are on desktop do overflow normal but we
if we are at mobile fixed body position, so that its not scrollable(which currently causing bug) and navbar handling its
owns scroll. Case to consider there are chance use can open navbar using toggle button and user when click on any link
body postion should be unset
*/
document.body.classList.toggle('is-nav-open');
const isOpen = document.body.classList.contains('is-nav-open');
if (isOpen) {
evt.target.setAttribute('aria-expanded', 'true');
} else {
evt.target.setAttribute('aria-expanded', 'false');
}
}
const mobileNavBtn = document.getElementById('toc-drawer-button');
mobileNavBtn.addEventListener('click', handleMobileNav);
mobileNavBtn.addEventListener('touchend', handleMobileNav);
if (window.location.pathname.startsWith('/posts')) {
mobileNavBtn.style.display = 'none';
}
const searchFormInputEl = document.getElementById('search-form-input');
searchFormInputEl.addEventListener('keyup', () => {
const gridTocEl = document.querySelector('#nav-primary');
if (searchFormInputEl.value) {
gridTocEl.classList.add('is-mobile-hidden');
} else {
gridTocEl.classList.remove('is-mobile-hidden');
}
});
document.onkeydown = function (e) {
if ((e.ctrlKey || e.metaKey) && e.which == 75) {
e.preventDefault();
searchFormInputEl.focus();
}
};
</script>
<script type="module" defer>
import docsearch from 'docsearch.js/dist/cdn/docsearch.min.js';
docsearch({
apiKey: '562139304880b94536fc53f5d65c5c19', indexName: 'snowpack', inputSelector: '.search-form-input', debug: true // Set debug to true if you want to inspect the dropdown
});
</script>
</Component>

View file

@ -0,0 +1,14 @@
<script>
//let name = 'world';
// TODO make this dynamic?
</script>
<h3>Assets</h3>
<ul>
<li><a href="(img/snowpack-logo-white.png">Snowpack Logo (PNG, White)</a></li>
<li><a href="(img/snowpack-logo-dark.png">Snowpack Logo (PNG, Dark)</a></li>
<li><a href="(img/snowpack-logo-black.png">Snowpack Logo (PNG, Black)</a></li>
<li><a href="(img/snowpack-wordmark-white.png">Snowpack Wordmark (PNG, White)</a></li>
<li><a href="(img/snowpack-wordmark-black.png">Snowpack Wordmark (PNG, Black)</a></li>
</ul>

View file

@ -0,0 +1,15 @@
<template>
<h2 class="content-title">
{{ title }}
</h2>
</template>
<script>
export default {
props: {
title: {
type: String,
required: true
}
}
}
</script>

View file

@ -0,0 +1,66 @@
#loading-message {
margin: 1rem;
text-align: center;
}
.cards {
list-style: none;
max-width: 600px;
padding-left: 0;
}
.plugin-icon {
height: 52px;
width: 52px;
opacity: .5;
transform: rotate(45deg);
/* background: radial-gradient(to top,red,blue); */
position: absolute;
top: 13px;
left: -15px;
}
.card:nth-child(3n+2) .plugin-icon {
filter: hue-rotate(-60deg);
}
.card:nth-child(3n+3) .plugin-icon {
filter: hue-rotate(-120deg);
}
.card {
margin: 0.5rem 0.25em;
border-radius: 4px;
padding: 0.5rem 0.5rem 0.5rem 48px;
flex-direction: column;
position: relative;
}
.card-name {
font-weight: 500;
margin: 0;
}
.card-header {
font-size: 1.1447rem;
}
.card-descr {
line-height: 1.25;
margin-top: 0.25em;
margin-bottom: 0.25em;
max-width: 80ch;
}
.card-subtitle {
margin: 0;
color: #7986a5;
font-size: 0.8735804647362989em;
}
.sky-form {
display: flex;
padding: 0.5rem;
justify-content: center;
}
.sky-btn {
background: #2e5e82;
color: white;
border: none;
border-radius: 0 2px 2px 0;
font-weight: 500;
padding: 0.5rem;
font-size: 22px;
}

View file

@ -0,0 +1,111 @@
import {h, Fragment} from 'preact';
import {useEffect, useState} from 'preact/hooks';
import './PluginSearchPage.css';
async function searchPlugins(val) {
const params3 = new URLSearchParams([
['q', 'snowpack plugin ' + (val || '')],
['count', '100'],
]);
const res = await fetch(
`https://api.skypack.dev/v1/search?${params3.toString()}`,
);
const jsonres = await res.json();
return jsonres.results;
}
function Card({ result }) {
const updatedAtFormatted = Intl.DateTimeFormat('en', {
month: 'long',
day: 'numeric',
year: 'numeric',
}).format(Date.parse(result.updatedAt));
return (
<li class="card">
<img class="plugin-icon" src="/img/plug-light.svg" />
<header class="card-header">
<h3 class="card-name">
<a
href="https://www.npmjs.com/package/{result.name}"
target="_blank"
>
<span itemprop="name">{result.name}</span>
</a>
</h3>
</header>
<p class="card-descr" itemprop="description">
{result.description.split('. ')[0]}
</p>
<p class="card-subtitle">
Updated
<time class="" datetime={result.updatedAt}>
{updatedAtFormatted}
</time>
</p>
</li>
);
}
export default function PluginSearchPage() {
const searchParams = new URLSearchParams(window.location.search);
const [results, setResults] = useState(null);
const [searchQuery, setSearchQuery] = useState(searchParams.get('q'));
useEffect(() => {
(async () => {
setResults(await searchPlugins(searchParams.get('q')));
})();
}, []);
async function onFormSubmit(e) {
e.preventDefault();
const form = new FormData(e.target);
const formula = form.get('q');
// document.getElementById('loading-message').style.display = 'block';
const searchParams = new URLSearchParams(window.location.search);
searchParams.set('q', formula);
window.history.pushState(null, null, '?' + searchParams.toString());
setSearchQuery(formula);
setResults(await searchPlugins(formula));
return false;
}
// if (document.getElementById('loading-message')) {
// document.getElementById('loading-message').style.display = 'none';
// }
return (
<>
<form
name="myform"
id="myform"
class="pluginPage-search"
action="https://www.npmjs.com/search"
method="GET"
onSubmit={onFormSubmit}
>
<input
type="search"
name="q"
defaultValue={searchQuery}
placeholder="search Sass, sitemaps, image optimization..."
class="pluginPage-search-input"
/>
<button type="submit" class="pluginPage-search-submit">
Search
</button>
</form>
<div class="pluginPage-count" id="total-result-count">
{!searchQuery && results && results.length > 50 && `${results.length}+ plugins available!`}
</div>
<section id="search-results" style="max-width: 600px;">
{!results && <div id="loading-message">Loading...</div>}
{results && results.length === 0 && <ul class="cards">
<li style="margin: 1rem; text-align: center;">No results found.</li>
</ul>}
{results && results.length > 0 && <ul class="cards">
{results.map((r) => <Card result={r} />)}
</ul>}
</section>
</>
);
}

View file

@ -0,0 +1,19 @@
<Component>
<script type="module" defer src="/js/index.js"></script>
<aside class="snow-toc snow-toc__subnav snow-view-subnav">
<h2 class="content-title">
{props.title}
</h2>
<h4 class="snow-toc-section-header">On this page</h4>
<nav class="toc">
<ol>
{props.headings.map((heading) => {
return <li><a href={heading.url}>{heading.text}</a></li>
})}
</ol>
</nav>
<hr />
<h4 class="snow-toc-section-header">Suggest a change</h4>
<a href="https://github.com/snowpackjs/snowpack/blob/main/www/{props.inputPath}">Edit this page on GitHub</a>
</aside>
</Component>

View file

@ -0,0 +1,90 @@
[
{
"title": "Snowpack v2.0",
"description": "Build web applications with less tooling and faster iteration.",
"date": "2020-05-26T00:00:00.000Z",
"url": "https://www.snowpack.dev/posts/2020-05-26-snowpack-2-0-release",
"img": "https://www.snowpack.dev/img/social-2.jpg"
},
{
"title": "Svelte + Snowpack",
"date": "2020-06-27T00:00:00.000Z",
"url": "https://www.youtube.com/watch?v=BxDaIQ1LNvI",
"img": "https://i.ytimg.com/vi/BxDaIQ1LNvI/hqdefault.jpg"
},
{
"title": "The Web Platform Podcast - Pika and Snowpack",
"date": "2020-06-28T00:00:00.000Z",
"url": "https://thewebplatformpodcast.com/200-pika-and-snowpack",
"img": "https://thewebplatformpodcast.com/assets/img/social/social-twp-twitter-default.jpg"
},
{
"title": "Creating a TypeScript React application using Snowpack",
"date": "2020-07-01T00:00:00.000Z",
"url": "https://www.youtube.com/watch?v=gjFDiaR3P5w",
"img": "https://i.ytimg.com/vi/gjFDiaR3P5w/hqdefault.jpg"
},
{
"title": "Snowpack v2.7",
"description": "A new plugin API plus smaller, faster production builds.",
"date": "2020-07-30T00:00:00.000Z",
"url": "https://www.snowpack.dev/posts/2020-07-30-snowpack-2-7-release",
"img": "https://www.snowpack.dev/img/social-2.jpg"
},
{
"title": "Up and running with Snowpack and Svelte in seconds",
"date": "2020-08-20T00:00:00.000Z",
"url": "https://dev.to/dailydotdev/up-and-running-with-snowpack-and-svelte-in-seconds-15po",
"img": "https://res.cloudinary.com/practicaldev/image/fetch/s--IoChIDsm--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/lmzyc4tuan79b6i8tro5.png"
},
{
"title": "Using Azure Static Web Apps with Snowpack for TypeScript",
"date": "2020-09-01T00:00:00.000Z",
"url": "https://dev.to/david_whitney/using-azure-static-web-apps-with-snowpack-for-typescript-in-your-frontend-22cc",
"img": "https://res.cloudinary.com/practicaldev/image/fetch/s--rC8eB2Gx--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/gf3bfom00lsemcfevqdq.png"
},
{
"title": "Speakeasy JS Snowpack: Faster web tooling, powered by ESM (Fred K Schott)",
"date": "2020-10-09T00:00:00.000Z",
"url": "https://www.youtube.com/watch?v=PJcfKX_PKaM",
"img": "https://i.ytimg.com/vi/PJcfKX_PKaM/hqdefault.jpg"
},
{
"title": "Getting started with Snowpack, React & Tailwind CSS",
"date": "2020-11-11T00:00:00.000Z",
"url": "https://scribbble.io/subhero/getting-started-with-snowpack-react-and-tailwind/"
},
{
"title": "New Official Guide: React",
"date": "2020-12-01T00:00:00.000Z",
"url": "https://next.snowpack.dev/tutorials/react",
"img": "https://next.snowpack.dev/img/ReactGuide.jpg"
},
{
"title": "New Official Guide: Svelte",
"date": "2020-12-01T00:00:00.000Z",
"url": "https://next.snowpack.dev/tutorials/svelte",
"img": "https://next.snowpack.dev/img/SvelteGuide.jpg"
},
{
"title": "Snowpack v3.0",
"description": "Snowpack v3.0 is here!",
"date": "2021-01-13T00:00:00.000Z",
"url": "https://www.snowpack.dev/posts/2021-01-13-snowpack-3-0",
"img": "https://www.snowpack.dev/img/social-snowpackv3.jpg"
},
{
"title": "Learn Snowpack in 15 minutes",
"description": "A video tutorial on creating a React app with Snowpack",
"date": "2021-01-20T00:00:00.000Z",
"url": "https://www.youtube.com/watch?v=QAwW0E9BXKc",
"img": "/img/news/learn-snow-youtube.jpg"
},
{
"title": "Create a 3D product landing page",
"description": "Using ThreeJS + React + Snowpack ",
"date": "2021-01-20T00:00:00.000Z",
"url": "https://dev.to/takeshape/create-a-3d-product-landing-page-with-threejs-and-react-3coh",
"img": "/img/news/3d-product.jpeg"
}
]

View file

@ -0,0 +1,97 @@
[
{
"name": "The Internet Archive",
"img": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Internet_Archive_logo_and_wordmark.svg/1200px-Internet_Archive_logo_and_wordmark.svg.png",
"url": "https://github.com/internetarchive/dweb-archive"
},
{
"name": "Alibaba 1688",
"img": "https://s.cafebazaar.ir/1/icons/com.alibaba.intl.android.apps.poseidon_512x512.png",
"url": "https://www.1688.com"
},
{
"name": "Intel",
"img": "https://upload.wikimedia.org/wikipedia/commons/4/4e/Intel_logo_%282006%29.svg",
"url": "https://twitter.com/kennethrohde/status/1227273971831332865"
},
{
"name": "CircleHD",
"img": "https://www.circlehd.com/img/logo-sm.svg",
"url": "https://www.circlehd.com/"
},
{
"name": "Svelvet",
"img": "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/240/apple/237/spool-of-thread_1f9f5.png",
"url": "https://github.com/jakedeichert/svelvet"
},
{
"name": "Pika.dev",
"img": "https://www.pika.dev/static/img/logo5.svg",
"url": "https://www.pika.dev"
},
{
"name": "Toast",
"img": "https://www.toast.dev/toast-icon-300.png",
"url": "https://www.toast.dev"
},
{
"name": "Maskable.app",
"img": "https://maskable.app/favicon/favicon_196.png",
"url": "https://maskable.app/"
},
{
"name": "Web Skills",
"img": "https://andreasbm.github.io/web-skills/www/icon.svg",
"url": "https://andreasbm.github.io/web-skills"
},
{
"name": "SwissDev JavaScript Jobs",
"img": "https://static.swissdevjobs.ch/pictures/swissdev-javascript-jobs.svg",
"url": "https://swissdevjobs.ch/jobs/JavaScript/All"
},
{
"name": "Tradie Training",
"img": "https://tt.edu.au/images/logo.png",
"url": "https://tt.edu.au"
},
{
"name": "wemake.services",
"img": "https://avatars0.githubusercontent.com/u/19639014?s=200&v=4",
"url": "https://github.com/wemake-services"
},
{
"name": "airhacks.com",
"img": "https://airhacks.com/logo.svg",
"url": "https://airhacks.com"
},
{
"name": "tongdun",
"img": "https://www.tongdun.cn/static/favicon.ico",
"url": "https://www.tongdun.cn/"
},
{
"name": "Blessing Skin",
"img": "https://blessing.netlify.app/logo.png",
"url": "https://github.com/bs-community"
},
{
"name": "TRPG Engine",
"img": "https://trpgdoc.moonrailgun.com/img/trpg_logo.png",
"url": "https://trpgdoc.moonrailgun.com/"
},
{
"name": "SHEIN",
"img": "https://sheinsz.ltwebstatic.com/she_dist/images/touch-icon-ipad-144-47ceee2d97.png",
"url": "https://www.shein.com/"
},
{
"name": "SeekInnovation",
"img": "https://assets.website-files.com/5e2c3e23d2e067287ea582e4/5e6a5bca2d401204ada76b95_SeekInnovationLogoRound_Vector.svg",
"url": "https://seekinnovation.at"
},
{
"name": "Vipatra",
"img": "https://vigneshksaithal.github.io/img/vipatra-logo-with-text.png",
"url": "https://vipatra.in"
}
]

View file

@ -0,0 +1,2 @@
const snowpackManifest = JSON.parse(fs.readFileSync(path.join(__dirname, '../../snowpack/package.json'), 'utf8'));
export default snowpackManifest.version;

View file

@ -0,0 +1,68 @@
<script hmx="setup">
import Banner from '../components/Banner.hmx';
import Nav from '../components/Nav.hmx';
export function setup() {
return {
title: 'Snowpack',
description: 'Snowpack is a lightning-fast frontend build tool, designed for the modern web.',
props: {
version: '3.0.13',
}
};
}
</script>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"/>
<link rel="manifest" href="/favicon/site.webmanifest" />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content="{description}" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website"/>
<meta property="og:url" content="https://www.snowpack.dev{props.permalink}"/>
<meta property="og:title" content={title}/>
<meta property="og:description" content={description}/>
<meta property="og:image" content="https://www.snowpack.dev/img/social-2.jpg"/>
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image"/>
<meta property="twitter:url" content="https://www.snowpack.dev{props.permalink}"/>
<meta property="twitter:title" content={title}/>
<meta property="twitter:description" content={description}/>
<meta property="twitter:image" content="https://www.snowpack.dev/img/social-2.jpg"/>
<!-- Global Stylesheets -->
<link rel="stylesheet" href="/css/app.css" />
<link href="https://fonts.googleapis.com/css2?family=Overpass:wght@400;700;900&display=swap" rel="stylesheet"/>
<!-- Note: You can then add additional, custom things here as well. -->
<!-- if no slot given, assume add to bottom -->
<slot></slot>
</head>
<body class="base 2">
<Banner></Banner>
<Nav version={props.version} />
<!-- if no slot given, assume add to bottom -->
<slot></slot>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-130280175-9"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-130280175-9', { page_path: location.pathname === '/' ? (location.pathname + location.hash) : (location.pathname) });
</script>
</body>

View file

@ -0,0 +1,82 @@
<script hmx="setup">
import Menu from '../components/Menu.hmx';
import Subnav from '../components/Subnav.hmx';
export function setup() {
return {layout: 'layouts/base.hmx', props: {}};
}
</script>
<head>
<style>
.cover-wrapper {
width: 100%;
height: 44vh;
min-height: 20rem;
max-height: 30rem;
position: relative;
background: #2a85ca40;
overflow: hidden;
}
.cover,
.cover-blur {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 100%;
width: 100%;
}
.cover-blur {
object-fit: cover;
filter: blur(3px) brightness(1.5);
transform: scale(1.1);
}
.cover {
object-fit: contain;
filter: brightness(1.5);
}
@media (max-width: 1200px) {
.cover-blur {
object-fit: cover;
}
.cover {
object-fit: cover;
}
}
</style>
<slot></slot>
</head>
<body>
<div class="cover-wrapper">
<img class="cover-blur" src={props.cover} alt=""/>
<img class="cover" src={props.cover} alt=""/>
</div>
<div class="container">
<section class="snow-view__docs has-subnav">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{title}
</h2>
<div class="content-layout">
<div class="content-body">
<slot></slot>
</div>
</div>
</div>
</article>
<Subnav title={title} />
</section>
</div>
</body>

View file

@ -0,0 +1,55 @@
<script hmx="setup">
import Subnav from '../components/Subnav.hmx';
import Menu from '../components/Menu.hmx';
import markdownToAst from "mdast-util-from-markdown";
import markdownTableOfContents from "mdast-util-toc";
export function setup({content}) {
const mdAst = markdownToAst(content.source);
// This is super gross, and just me trying to get an existing table of contents generator to work
// we can either do this internally as helpful sugar, or build a simpler one as a plugin
const headingsAst = markdownTableOfContents(mdAst);
const headings = headingsAst.map ? headingsAst.map.children.map(ch => {
return {depth: 1, url: ch.children[0].children[0].url, text: ch.children[0].children[0].children[0].value};
}) : [];
return {
layout: 'layouts/base.hmx',
props: {
headings,
}
};
}
</script>
<head>
<slot></slot>
</head>
<body>
<div class="container">
<section class="snow-view__docs has-subnav">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<Subnav title={title} headings={props.headings} />
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{title}
</h2>
<div class="content-layout">
<div class="content-body">
<slot></slot>
</div>
</div>
</div>
</article>
</section>
</div>
</body>

View file

@ -0,0 +1,31 @@
<script hmx="setup">
import Menu from '../components/Menu.hmx';
export function setup() {
return {
layout: 'layouts/base.hmx',
props: {}
};
}
</script>
<head>
<!-- hi -->
<slot></slot>
</head>
<body class="base 2">
<div class="container">
<section class="snow-view__docs is-full">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<article class="snow-view-main">
<slot></slot>
</article>
</section>
</div>
</body>

View file

@ -0,0 +1,143 @@
<script hmx="setup">
import {format as formatDate, parseISO} from 'date-fns';
export function setup() {
return { layout: 'layouts/base.hmx', props: {} };
}
</script>
<head>
<link rel="stylesheet" href="/css/legacy-post.css" />
<style>
.markdown-body img,
.markdown-body video,
.markdown-body iframe {
box-shadow: 0px 5px 12px 0 #CCC;
border-radius: 3px;
min-width: 130%;
width: 130%;
margin-left: -15%;
margin-right: -15%;
margin-top: 4rem;
margin-bottom: -1rem;
}
@media (max-width: 860px) {
.markdown-body img,
.markdown-body video,
.markdown-body iframe {
min-width: 100%;
margin-left: 0;
margin-right: 0;
margin-bottom: -2rem;
}
}
.markdown-body table td:nth-child(1) {
white-space: nowrap;
}
.grid-body {
padding: 4rem 0;
}
.grid-body-header h1 {
margin-bottom: 1rem;
margin-top: 1rem;
}
.markdown-body,
.fbody-header {
max-width: 840px;
}
.markdown-body {
font-size: 18px;
margin-bottom: 20vh;
}
.markdown-body h2 {
font-size: 1.8em;
}
@media (max-width: 860px) {
.markdown-body,
.toc {
padding: 1em;
}
}
@media (max-width: 740px) {
.markdown-body img,
.markdown-body iframe {
max-width: 108%;
margin-left: -4%;
margin-right: -4%;
}
.grid-body {
padding: 20px 0 0 0;
}
.header-snowpack {
font-size: 3.5rem;
text-align: center;
}
.markdown-body h1 {
font-size: 3.5em;
}
.markdown-body h3 .header-link {
opacity: 1;
}
}
</style>
<slot></slot>
</head>
<body>
<div class="grid-extra-space">
<div class="grid-body-header">
<svg height="80px" style="padding-left: 8px;" viewBox="0 0 640 512" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd">
<g id="mountain-solid" transform="translate(-1.000000, 0.000000)" fill-rule="nonzero">
<path
d="M635.92,462.7 L347.92,14.7 C342.03,5.54 331.89,0 321,0 C310.11,0 299.97,5.54 294.08,14.7 L6.08,462.7 C-0.250773249,472.547007 -0.699487627,485.064987 4.91,495.34 C10.522069,505.612419 21.2945349,512 33,512 L609,512 C620.71,512 631.48,505.61 637.09,495.33 C642.699457,485.058495 642.250708,472.543372 635.92,462.7 Z M321,91.18 L406.39,224 L321,224 L257,288 L218.94,249.94 L321,91.18 Z"
id="Shape"></path>
</g>
</g>
</svg>
<h1 class="header-snowpack">{title}</h1>
<p>
{props.tagline && <div style="margin-bottom: 1rem;">{props.tagline}</div>}
<div>
Published <a href='#published-at'>{formatDate(parseISO(props.date), 'MMMM d, yyyy')}</a>
by <a href="https://twitter.com/FredKSchott">Fred K. Schott</a>
</div>
</p>
<!-- Place this tag where you want the button to render. -->
<div class="hidden-mobile" style="text-align: center; margin-top: 0.5rem; filter: scale(2);">
<a class="github-button" href="https://github.com/snowpackjs/snowpack" data-icon="octicon-star"
data-size="large" data-show-count="true" aria-label="Star snowpackjs/snowpack on GitHub">Star</a>
</div>
<!-- Place this tag in your head or just before your close body tag. -->
<script defer src="https://buttons.github.io/buttons.js"></script>
</div>
</div>
<div class="grid-body">
<article class="markdown-body">
<slot></slot>
</article>
</div>
</body>

View file

@ -0,0 +1,18 @@
<script hmx="setup">
export function setup() {
return {
title: '404 - Not Found',
layout: 'layouts/main.hmx',
props: {
}
};
}
</script>
<h2 class="content-title">
{title}
</h2>
<div class="content">
<a href="/">Go Home</a>
</div>

View file

@ -0,0 +1,40 @@
---
layout: layouts/content.hmx
title: The Build Pipeline
description: Snowpack Build creates a production-ready website with or without a bundler
---
![build output example](/img/snowpack-build-example.png)
`snowpack build` - When you're ready to deploy your application, run the build command to generate a static production build of your site. Building is tightly integrated with your dev setup so that you are guaranteed to get a near-exact copy of the same code that you saw during development.
### Bundle for Production
**You should be able to use a bundler because you want to, and not because you need to.** That was the original concept that Snowpack was designed to address. Snowpack treats bundling as an optional production optimization, which means you're free to skip over the extra complexity of bundling until you need it.
By default, `snowpack build` will build your site using the same unbundled approach as the `dev` command. This is fine for most projects, but you also may still want to bundle for production. Legacy browser support, code minification, code-splitting, tree-shaking, dead code elimination, and other performance optimizations can all be handled in Snowpack via bundling.
Bundlers normally require dozens or even hundreds of lines of configuration, but with Snowpack it's just a one-line plugin with no config required. This is possible because Snowpack builds your application _before_ sending it to the bundler, so the bundler never sees your custom source code (JSX, TS, Svelte, Vue, etc.) and instead needs to worry only about building common HTML, CSS, and JS.
```js
// Bundlers plugins are pre-configured to work with Snowpack apps.
// No config required!
{
"plugins": [["@snowpack/plugin-webpack"]]
}
```
See [our bundling guides](/guides/optimize-and-bundle) for more information about connecting bundled (or unbundled) optimization plugins for your production builds.
## Legacy Browser Support
You can customize the set of browsers you'd like to support via the `package.json` "browserslist" property, going all the way back to IE11. This will be picked up when you run `snowpack build` to build for production.
```js
/* package.json */
"browserslist": ">0.75%, not ie 11, not UCAndroid >0, not OperaMini all",
```
If you're worried about legacy browsers, you should also add a bundler to your production build. Check out our [section on bundling for deployment](/guides/optimize-and-bundle) for more info.
Note: During development (`snowpack dev`) we perform no transpilation for older browsers. Make sure that you're using a modern browser during development.

View file

@ -0,0 +1,11 @@
---
layout: layouts/content.hmx
title: The Dev Server
description: Snowpack's dev server is fast because it only rebuilds the files you change. Powered by ESM (ES modules).
---
![dev command output example](/img/snowpack-dev-startup-2.png)
`snowpack dev` - Snowpack's dev server is an instant dev environment for [unbundled development.](/concepts/how-snowpack-works) The dev server will build a file only when it's requested by the browser. That means that Snowpack can start up instantly (usually in **<50ms**) and scale to infinitely large projects without slowing down. In contrast, it's common to see 30+ second dev startup times when building large apps with a traditional bundler.
Snowpack supports JSX & TypeScript source code by default. You can extend your build even further with [custom plugins](/plugins) that connect Snowpack with your favorite build tools: TypeScript, Babel, Vue, Svelte, PostCSS, Sass... go wild!

View file

@ -0,0 +1,45 @@
---
layout: layouts/content.hmx
title: HMR + Fast Refresh
description: Snowpack's ESM-powered unbundled development means near-instant single file builds that only take 10-25ms to load and update in the browser.
---
Hot Module Replacement (HMR) is the ability to push file updates to the browser without triggering a full page refresh. Imagine changing some CSS, hitting save, and then instantly seeing your change reflected on the page without a refresh. That's HMR.
HMR is not unique to Snowpack. However, Snowpack's ability to leverage ESM for unbundled development introduces near-instant single file builds that only take 10-25ms to load and update in the browser.
Snowpack ships with ready, out-of-the-box HMR support for the following file types:
- CSS
- CSS Modules
- JSON
JavaScript HMR is also supported out-of-the-box, but often requires a few additional lines of code to properly integrate with your frontend framework's "render" function. See "Enabling HMR + Fast Refresh" below.
## Fast Refresh
In addition to normal HMR, Snowpack also supports **Fast Refresh** for most popular frameworks like React, Preact and Svelte. Fast Refresh is a framework-specific enhancement to HMR, which applies single file updates in a way that preserves component state across updates. Changes to a `<Timer />` component, for example, would be applied without resetting the component's internal state.
Fast Refresh makes development even faster, especially when working on popups and other secondary view states that normally would require a click to re-open or re-visit after every change.
## Enabling HMR + Fast Refresh
Snowpack supports HMR for all popular frontend frameworks. **[Create Snowpack App (CSA)](https://github.com/snowpackjs/snowpack/blob/main/create-snowpack-app) ships with HMR enabled by default.** You can setup HMR yourself with just a few lines of code, and Fast Refresh can be enabled automatically via plugin:
- Preact: [@prefresh/snowpack](https://www.npmjs.com/package/@prefresh/snowpack)
- React: [@snowpack/plugin-react-refresh](https://www.npmjs.com/package/@snowpack/plugin-react-refresh)
- Svelte: [@snowpack/plugin-svelte](https://www.npmjs.com/package/@snowpack/plugin-svelte)
- Vue (HMR only): [A few lines of code](https://github.com/snowpackjs/snowpack/blob/main/create-snowpack-app/app-template-vue/src/index.js#L7-L14)
For more advanced HMR integrations, Snowpack created the [esm-hmr spec](https://github.com/snowpackjs/esm-hmr), a standard HMR API for any ESM-based dev environment:
```js
// HMR Code Snippet Example
if (import.meta.hot) {
import.meta.hot.accept(({ module }) => {
// Accept the module, apply it into your application.
});
}
```
Check out the full [ESM-HMR API reference](https://github.com/snowpackjs/esm-hmr) on GitHub.

View file

@ -0,0 +1,62 @@
---
layout: layouts/content.hmx
title: How Snowpack Works
description: Snowpack serves your application unbundled during development. Each file is built only once and is cached until it changes.
---
### Summary
**Snowpack is a modern, lightweight build tool for faster web development.** Traditional JavaScript build tools like webpack and Parcel need to rebuild & rebundle entire chunks of your application every time you save a single file. This rebundling step introduces lag between hitting save on your changes and seeing them reflected in the browser.
Snowpack serves your application **unbundled during development.** Each file needs to be built only once and then is cached forever. When a file changes, Snowpack rebuilds that single file. There's no time wasted re-bundling every change, just instant updates in the browser (made even faster via [Hot-Module Replacement (HMR)](/concepts/hot-module-replacement)). You can read more about this approach in our [Snowpack 2.0 Release Post.](/posts/2020-05-26-snowpack-2-0-release/)
Snowpack's **unbundled development** still supports the same **bundled builds** that you're used to for production. When you go to build your application for production, you can plug in your favorite bundler via an official Snowpack plugin for Webpack or Rollup (coming soon). With Snowpack already handling your build, there's no complex bundler config required.
**Snowpack gets you the best of both worlds:** fast, unbundled development with optimized performance in your bundled production builds.
![webpack vs. snowpack diagram](/img/snowpack-unbundled-example-3.png)
### Unbundled Development
**Unbundled development** is the idea of shipping individual files to the browser during development. Files can still be built with your favorite tools (like Babel, TypeScript, Sass) and then loaded individually in the browser with dependencies thanks to ESM `import` and `export` syntax. Any time you change a file, Snowpack rebuilds only that file.
The alternative is **bundled development.** Almost every popular JavaScript build tool today focuses on bundled development. Running your entire application through a bundler introduces additional work and complexity to your dev workflow that is unnecessary now that ESM is widely supported. Every change -- on every save -- must be rebundled with the rest of your application before your changes can be reflected in your browser.
Unbundled development has several advantages over the traditional bundled development approach:
- Single-file builds are fast.
- Single-file builds are deterministic.
- Single-file builds are easier to debug.
- Project size doesnt affect dev speed.
- Individual files cache better.
That last point is key: **Every file is built individually and cached indefinitely.** Your dev environment will never build a file more than once and your browser will never download a file twice (until it changes). This is the real power of unbundled development.
### Using NPM Dependencies
NPM packages are mainly published using a module syntax (Common.js, or CJS) that can't run on the web without some build processing. Even if you write your application using browser-native ESM `import` and `export` statements that would all run directly in the browser, trying to import any one npm package will force you back into bundled development.
**Snowpack takes a different approach:** Instead of bundling your entire application for this one requirement, Snowpack processes your dependencies separately. Here's how it works:
```
node_modules/react/**/* -> http://localhost:3000/web_modules/react.js
node_modules/react-dom/**/* -> http://localhost:3000/web_modules/react-dom.js
```
1. Snowpack scans your website/application for all used npm packages.
2. Snowpack reads these installed dependencies from your `node_modules` directory.
3. Snowpack bundles all of your dependencies separately into single JavaScript files. For example: `react` and `react-dom` are converted to `react.js` and `react-dom.js`, respectively.
4. Each resulting file can be run directly in the browser, and imported via ESM `import` statements.
5. Because your dependencies rarely change, Snowpack rarely needs to rebuild them.
After Snowpack builds your dependencies, any package can be imported and run directly in the browser with zero additional bundling or tooling required. This ability to import npm packages natively in the browser (without a bundler) is the foundation that all unbundled development and the rest of Snowpack is built on top of.
```html
<!-- This runs directly in the browser with `snowpack dev` -->
<body>
<script type="module">
import React from 'react';
console.log(React);
</script>
</body>
```

View file

@ -0,0 +1,76 @@
<script hmx="setup">
import Card from '../components/Card.jsx';
// mocked for now, to be added later
// 1. import {paginate} from 'magicthing';
// 2. export default function ({paginate}) {
function paginate(options) {
if (options.tag === 'guide') {
return [
{title: 'Test guide 1', href:"#"},
{title: 'Test guide 2', href:"#"},
];
}
if (options.tag === 'communityGuides') {
return [{title: 'Test communityGuides', href:"#"}];
}
return [];
}
export function setup({/* paginate */}) {
return {
title: 'Guides',
description: "Snowpack's usage and integration guides.",
layout: 'layouts/main.hmx',
props: {
guides: paginate({
files: '/posts/guides/*.md',
// sort: ((a, b) => new Date(b) - new Date(a)),
tag: 'guide',
limit: 10,
// page: query.page,
}),
communityGuides: paginate({
files: '/posts/guides/*.md',
// sort: ((a, b) => new Date(b) - new Date(a)),
tag: 'communityGuides',
limit: 10,
}),
}
};
}
</script>
<head>
</head>
<body>
<h2 class="content-title">
{title}
</h2>
<h3 class="content-title">
Using Snowpack
</h3>
<div class="content">
<ul>
{props.guides.map((post) => {
return <li><a href={post.href}>{post.title}</a></li>;
})}
</ul>
</div>
<br/>
<br/>
<h3 class="content-title">
Popular Integration Guides
</h3>
<div class="card-grid card-grid-4">
{props.communityGuides.map((post) => {
return <Card item={post} />;
})}
</div>
</body>

View file

@ -0,0 +1,22 @@
---
layout: layouts/content.hmx
title: 'Babel'
tags: communityGuide
published: true
img: '/img/logos/babel.svg'
imgBackground: '#323330'
description: How to use Babel in your Snowpack project.
---
[Babel](https://babeljs.io/) is a popular JavaScript transpiler that includes a huge ecosystem of plugins.
**You probably don't need Babel!** Snowpack has built-in support for JSX and TypeScript transpilation. Only use Babel if you need to customize how your JavaScript/TypeScript files are built using custom Babel plugins/presets.
**To use Babel with Snowpack:** add the [@snowpack/plugin-babel](https://www.npmjs.com/package/@snowpack/plugin-babel) plugin to your project.
```diff
// snowpack.config.js
"plugins": [
+ ["@snowpack/plugin-babel"]
]
```

View file

@ -0,0 +1,111 @@
---
layout: layouts/content.hmx
title: The Snowpack Guide to connecting your favorite tools
description: 'How do you use your favorite tools in Snowpack? This Guide will help you get started'
published: true
---
One of the most common questions we get is "How do I connect my favorite tool to Snowpack?" In this guide we'll go over the three different ways that you can integrate third-party tooling into your Snowpack dev environment or build pipeline:
- Snowpack plugin
- Integrated CLI script (via `@snowpack/plugin-run-script`)
- Run separately, outside of Snowpack (ex: in your `package.json`)
## Integrating a Tool With a Snowpack Plugin
The best way to connect a new tool to Snowpack is to search our [plugin catalog](/plugins) for a relevant plugin. Most likely, someone already created a plugin to help you integrate your favorite tool with ease.
To add a plugin first install using your package manager, then add the plugin name to the `plugins` section in your Snowpack configuration file. Many plugins have their own totally optional configuration options. These are covered in each plugin's documentation.
For example, if you'd like to use sass, you can install [`@snowpack/plugin-sass`
](https://www.npmjs.com/package/@snowpack/plugin-sass) with npm:
```bash
npm install @snowpack/plugin-sass
```
Then if you don't already have a Snowpack configuration file (`snowpack.config.js`) you can create one with this command:
```bash
snowpack init
```
Open up `snowpack.config.js` and add the name of your new plugin to the plugins object:
```diff
// snowpack.config.js
plugins: [
- /* ... */
+ '@snowpack/plugin-sass'
],
```
What about the other optional configuration options? [The `@snowpack/plugin-sass` documentation](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-sass) lists all the options and where to put them in the `snowpack.config.js` file. If I wanted the `compressed` output `style` I'd turn the `@snowpack/plugin-sass` value into an array with an object containing the configuration:
```diff
// snowpack.config.js
plugins: [
- '@snowpack/plugin-sass'
+ ['@snowpack/plugin-sass', { style: 'compressed'}]
],
```
If there isn't a plugin yet, you might be interested in making one. Check out our [Plugin API](/reference/plugins)
## Connect any other Script/CLI using plugin-run-script and plugin-build-script
If you can't find a plugin that fits your needs and don't want to write your own, you can also run CLI commands directly as a part of your build using one of our two utility plugins: `@snowpack/plugin-build-script` & `@snowpack/plugin-run-script`.
#### @snowpack/plugin-build-script
```js
// snowpack.config.json
// [npm install @snowpack/plugin-build-script]
{
"plugins": [
["@snowpack/plugin-build-script", { "cmd": "postcss", "input": [".css"], "output": [".css"]}]
],
}
```
This plugin allows you to connect any CLI into your build process. Just give it a `cmd` CLI command that can take input from `stdin` and emit the build result via `stdout`. Check out the [plugin documentation](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-build-script) for more information.
#### @snowpack/plugin-run-script
```js
// snowpack.config.json
// [npm install @snowpack/plugin-run-script]
{
"plugins": [
["@snowpack/plugin-run-script", { "cmd": "eleventy", "watch": "$1 --watch" }]
],
}
```
This plugin allows you to run any CLI command as a part of your dev and build workflow. This plugin doesn't affect your build output, but it is useful for connecting developer tooling directly into Snowpack. Use this to add meaningful feedback to your dev console as you type, like TypeScript type-checking and ESLint lint errors. This doesn't affect how Snowpack builds your site. Check out the [plugin documentation](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-run-script) for more information.
### Examples
#### PostCSS
```js
// snowpack.config.json
"plugins": [
["@snowpack/plugin-build-script", {"cmd": "postcss", "input": [".css"], "output": [".css"]}]
]
```
The [`postcss-cli`](https://github.com/postcss/postcss-cli) package must be installed manually. You can configure PostCSS with a `postcss.config.js` file in your current working directory.
#### ESLint
```js
// snowpack.config.json
"plugins": [
["@snowpack/plugin-run-script", {
"cmd": "eslint src --ext .js,jsx,.ts,.tsx",
// Optional: Use npm package "eslint-watch" to run on every file change
"watch": "esw -w --clear src --ext .js,jsx,.ts,.tsx"
}]
]
```

View file

@ -0,0 +1,66 @@
---
layout: layouts/content.hmx
title: Hot Module Replacement (HMR)
description: Enable Snowpack's Hot Module Replacement (HMR) on your development server.
published: false
---
<div class="stub">
This article is a stub, you can help fix it by removing duplicate content from /concepts/hot-module-replacement and writing it in a <a href="https://documentation.divio.com/how-to-guides/">guide format</a>
</div>
Hot Module Replacement (HMR) is the ability for Snowpack to push file changes to the browser without triggering a full page refresh. This article is about enabling HMR and connecting to the HMR dev server.
For instructions on using HMR, refer to the `import.meta.hot` API documentation.
### Is HMR Connected?
You can tell if HMR is connected by checking your browser dev console. If you see the following message, that means that HMR is enabled and connected.
```
[ESM-HMR] listening for file changes..
```
### Enable HMR: Snowpack Dev Server
HMR is enabled by default when you run `snowpack dev`. The Snowpack dev server will add the necessary scripts for your browser, and no configuration is required for most users. You can toggle this support off during development via the [`devOptions.hmr` configuration option](/reference/configuration).
### Enable HMR: Custom Server
_Note: Full HMR is not yet supported. Only full page reloads are currently working. Follow updates here: [https://github.com/snowpackjs/snowpack/issues/1935](https://github.com/snowpackjs/snowpack/issues/1935)_
If you use your own server (ex: Rails) to serve your application during development, there are a couple of small steps to enable HMR.
HMR is not enabled by default if you are using `snowpack build --watch` for local development (instead of `snowpack dev`). Set `devOptions.hmr: true` in your Snowpack configuration (or, use `--hmr`) to enable HMR support in your application.
We also recommend that you manually add the Snowpack HMR client to your HTML (development only, not needed in production):
```html
<!-- Load the script to enable HMR. -->
<script type="module" src="/_snowpack/hmr-client.js"></script>
```
### Configuring HMR
HMR is powered by a WebSocket connection between the client and Snowpack. If you are having trouble connecting to the client, you may need need to tell it where Snowpack's HMR Websocket server is running.
First, make sure that `devOptions.hmr` is set to true. This guarantees that the HMR Websocket is running and ready to accept connections in both `dev` and `build`.
By default, the client will try to connect to the HMR server at the current host (ex: `localhost`) using one of two ports:
- `snowpack dev`: The same port as the dev server
- `snowpack build`: port `12321`
You can control this by setting `devOptions.hmrPort` manually via configuration or setting the following global script variable somewhere on the page **before** the `hmr-client.js` script runs:
```html
<!-- Optional: Set the HMR websocket URL, overrides default -->
<script>
window.HMR_WEBSOCKET_URL = 'ws://localhost:4444';
</script>
<script type="module" src="/_snowpack/hmr-client.js"></script>
```
### Disable HMR
Set `devOptions.hmr` to false to disable HMR in all cases.

View file

@ -0,0 +1,27 @@
---
layout: layouts/content.hmx
title: SSL Certificates
description: How to use HTTPs during development and generate SSL certifcates for your Snowpack build.
---
<div class="notification">
This guide has an example repo:
<a href="https://github.com/snowpackjs/snowpack/tree/main/examples/https-ssl-certificates/">
examples/https-ssl-certificates
</a>
</div>
```
npm start -- --secure
```
Snowpack provides an easy way to use a local HTTPS server during development through the use of the `--secure` flag. When enabled, Snowpack will look for a `snowpack.key` and `snowpack.crt` file in the root directory and use that to create an HTTPS server with HTTP2 support enabled.
### Generating SSL Certificates
You can automatically generate credentials for your project via either:
- [devcert (no install required, but openssl is a prerequisite)](https://github.com/davewasmer/devcert-cli): `npx devcert-cli generate localhost`
- [mkcert (install required)](https://github.com/FiloSottile/mkcert): `mkcert -install && mkcert -key-file snowpack.key -cert-file snowpack.crt localhost`
In most situations you should add personally generated certificate files (`snowpack.key` and `snowpack.crt`) to your `.gitignore` file.

View file

@ -0,0 +1,29 @@
---
layout: layouts/content.hmx
title: 'Jest'
tags: communityGuide
img: '/img/logos/jest.svg'
imgBackground: '#d14c53'
published: true
description: How to use Jest, a popular test runner, with Snowpack.
---
[Jest](https://jestjs.io/) is a popular Node.js test runner for Node.js & web projects. Jest can be used with any frontend project as long as you configure how Jest should build your frontend files to run on Node.js. Many projects will try to manage this configuration for you, since it can get complicated.
Snowpack ships pre-built Jest configuration files for several popular frameworks. If you need to use Jest for any reason,consider extending one of these packages:
- React: [@snowpack/app-scripts-react](https://www.npmjs.com/package/@snowpack/app-scripts-react)
- Preact: [@snowpack/app-scripts-preact](https://www.npmjs.com/package/@snowpack/app-scripts-preact)
- Svelte: [@snowpack/app-scripts-svelte](https://www.npmjs.com/package/@snowpack/app-scripts-svelte)
Note: You will need a `jest.setup.js` file in the root directory of your project.
### Example
```js
// jest.config.js
// Example: extending a pre-built Jest configuration file
module.exports = {
...require('@snowpack/app-scripts-preact/jest.config.js')(),
};
```

View file

@ -0,0 +1,54 @@
---
layout: layouts/content.hmx
title: Optimize & Bundle for Production
published: true
description: How to optimize your Snowpack build for production, with or without a bundler.
---
`snowpack build` builds your site into web native JS, CSS, and HTML files. This "unbundled" deployment can be enough for small sites, but many developers prefer to optimize and bundle their final site for production performance.
Snowpack can run all sorts of optimizations on your final build to handle legacy browser support, code minification, code-splitting, tree-shaking, dead code elimination, preloading, bundling, and more.
Snowpack build optimizations come in two flavors: **built-in** (esbuild) & **plugin** (webpack, rollup, or whatever else you might like to run).
### Option 1: Built-in Optimizations
Snowpack recently released a built-in optimization pipeline powered by [esbuild](https://esbuild.github.io/). Using this built-in optimizer, you can now bundle, transpile, and minify your production builds 10x-100x faster than Webpack or Rollup. However, esbuild is still young and [not yet production-ready](https://esbuild.github.io/faq/#production-readiness). At the moment, we only recommended this for smaller projects.
```js
// snowpack.config.js
// Example: Using Snowpack's built-in bundling support
module.exports = {
optimize: {
bundle: true,
minify: true,
target: 'es2018',
},
};
```
The full supported interface is:
```ts
export interface OptimizeOptions {
entrypoints: 'auto' | string[] | ((options: { files: string[] }) => string[]);
preload: boolean;
bundle: boolean;
splitting: boolean;
treeshake: boolean;
manifest: boolean;
minify: boolean;
target: 'es2020' | 'es2019' | 'es2018' | 'es2017';
}
```
### Option 2: Optimize Plugins
Snowpack supports popular bundlers via plugin:
- webpack (recommended!): [@snowpack/plugin-webpack](https://www.npmjs.com/package/@snowpack/plugin-webpack)
- Rollup: [snowpack-plugin-rollup-bundle](https://github.com/ParamagicDev/snowpack-plugin-rollup-bundle)
**For now, we recommend using @snowpack/plugin-webpack until our built-in optimize support is more mature.**
Check out our [Plugins Catalog](/plugins) to browse all available Snowpack plugins, and read the [Plugins Guide](/guides/plugins) if you're interested in creating your own.

View file

@ -0,0 +1,316 @@
---
layout: layouts/content.hmx
title: Creating Your Own Plugin
description: Learn the basics of our Plugin API through working examples.
---
A **Snowpack plugin** lets you extend Snowpack with new behaviors. Plugins can hook into different stages of the Snowpack build pipeline to add support for new file types and your favorite dev tools. Add plugins to support Svelte, compile Sass to CSS, convert SVGs to React components, bundle your final build, type check during development, and much more.
This guide takes you though creating and publishing your first plugin.
- The basic structure of Snowpack plugins
- How to choose the right hooks from the Snowpack Plugin API
- How to publish your plugin and add it to our [Plugin](/plugins) directory
Prerequisites: Snowpack plugins are written in JavaScript and run via Node.js so basic knowledge of both is required.
## Creating and testing your first plugin
In this step you'll create a simple plugin scaffold that you can turn into a fuctional plugin based on the examples in the guide.
Create a directory for your plugin called `my-snowpack-plugin` and inside it create a `my-snowpack-plugin.js` file:
```js
// my-snowpack-plugin.js
// Example: a basic Snowpack plugin file, customize the name of the file and the value of the name in the object
// snowpackConfig = The Snowpack configuration object
// pluginOptions = user-provided configuration options
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'my-snowpack-plugin',
};
};
```
To test your new plugin, run `npm init` to create a basic `package.json` then run `npm link` in your plugins directory to expose the plugin globally (on your development machine).
For testing, [create a new, example Snowpack project](/tutorials/getting-started) in a different directory. In your example Snowpack project, run `npm install && npm link my-snowpack-plugin` (use the name from your plugins `package.json`).
> The alternative would be to use `npm install --save-dev path_to_your_plugin`, which would create the "symlink-like" entry in your example Snowpack projects `package.json`
In your example Snowpack project, add your plugin to the `snowpack.config.js` along with any plugin options youd like to test:
```js
// snowpack.config.js
// Example: enabling a Snowpack plugin called "my-snowpack-plugin"
{
"plugins": [
"my-snowpack-plugin"
]
}
```
## Testing and Troubleshooting
- TODO: create a full how to test procedure
- HINT: Add `--verbose` to the command to see the steps, e.g. `snowpack dev --verbose` or `snowpack build --verbose`
## Adding user-configurable options to your plugin
TODO make this a real example
In this step, you'll learn how to add user-configurable options to your plugin and to use them in your plugin code.
In your example Snowpack project, instead of enabling the plugin as a string containing the plugin name, use an array. The first item is name of your plugin and the second a new object containing the plugin options.
```diff
// snowpack.config.js
{
"plugins": [
- "my-snowpack-plugin"
+ ["my-snowpack-plugin", { "optionA": "foo", "optionB": true }]
]
}
```
You access these through the `pluginOptions`
```diff
// my-snowpack-plugin.js
module.exports = function (snowpackConfig, pluginOptions) {
+ let optionA = pluginOptions.optionA
+ let optionB = pluginOptions.optionB
return {
name: 'my-snowpack-plugin'
};
};
```
### Plugin Use-Cases
Snowpack uses an internal **Build Pipeline** to build files in your application for development and production. Every source file passes through the build pipeline, which means that Snowpack can build more than just JavaScript. Images, CSS, SVGs and more can all be built by Snowpack.
#### Build Plugins
Snowpack finds the first plugin that claims to `resolve` the given file. It then calls that plugin's `load()` method to load the file into your application. This is where compiled languages (TypeScript, Sass, JSX, etc.) are loaded and compiled to something that can run on the web (JS, CSS, etc).
#### Transform Plugins
Once loaded, every file passes through the build pipeline again to run through matching `transform()` methods of all plugins that offer the method. Plugins can transform a file to modify its contents before finishing the file build.
#### Dev Tooling Plugins
Snowpack plugins support a `run()` method which lets you run any CLI tool and connect its output into Snowpack. You can use this to run your favorite dev tools (linters, TypeScript, etc.) with Snowpack and automatically report their output back through the Snowpack developer console. If the command fails, you can optionally fail your production build.
#### Bundler Plugins
Snowpack builds you a runnable, unbundled website by default, but you can optimize this final build with your favorite bundler (webpack, Rollup, Parcel, etc.) through the plugin `optimize()` method. When a bundler plugin is used, Snowpack will run the bundler on your build automatically to optimize it.
See our official [@snowpack/plugin-webpack](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-webpack) bundler plugin for an example of using the current interface.
### Example: Getting Started
To create a Snowpack plugin, you can start with the following file template:
```js
// my-snowpack-plugin.js
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'my-snowpack-plugin',
// ...
};
};
```
```json
// snowpack.config.json
{
"plugins": [
["./my-snowpack-plugin.js", { "optionA": "foo", "optionB": "bar" }]
]
}
```
A Snowpack plugin should be distributed as a function that can be called with plugin-specific options to return a plugin object.
Snowpack will automatically call this function to load your plugin. That function accepts 2 parameters, in this order:
1. the [Snowpack configuration object](/reference/configuration) (`snowpackConfig`)
1. (optional) user-provided config options (`pluginOptions`)
### Example: Transform a File
For our first example, well look at transforming a file.
```js
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'my-commenter-plugin',
async transform({ id, contents, isDev, fileExt }) {
if (fileExt === '.js') {
return `/* Im a comment! */ ${contents}`;
}
},
};
};
```
The object returned by this function is a **Snowpack Plugin**. A plugin consists of a `name` property and some hooks into the Snowpack lifecycle to customizes your build pipeline or dev environment. In the example above we have:
- The **name** property: The name of your plugin. This is usually the same as your package name if published to npm.
- The **transform** method: A function that allows you to transform & modify built files. In this case, we add a simple comment (`/* Im a comment */`) to the beginning of every JS file in your build.
This covers the basics of single-file transformations. In our next example, well show how to compile a source file and change the file extension in the process.
### Example: Build From Source
When you build files from source, you also have the ability to transform the file type from source code to web code. In this example, we'll use Babel to load several types of files as input and output JavaScript in the final build:
```js
const babel = require('@babel/core');
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'my-babel-plugin',
resolve: {
input: ['.js', '.jsx', '.ts', '.tsx', '.mjs'],
output: ['.js'],
},
async load({ filePath }) {
const result = await babel.transformFileAsync(filePath);
return result.code;
},
};
};
```
This is a simplified version of the official Snowpack Babel plugin, which builds all JavaScript, TypeScript, and JSX files in your application with the `load()` method.
The `load()` method is responsible for loading and build files from disk while the `resolve` property tells Snowpack which files the plugin can load and what to expect as output. In this case, the plugin claims responsibility for files matching any of the file extensions found in `resolve.input`, and outputs `.js` JavaScript (declared via `resolve.output`).
**See it in action:** Let's say that we have a source file at `src/components/App.jsx`. Because the `.jsx` file extension matches an extension in our plugin's `resolve.input` array, Snowpack lets this plugin claim responsibility for loading this file. `load()` executes, Babel builds the JSX input file from disk, and JavaScript is returned to the final build.
### Example: Multi-File Building
For a more complicated example, well take one input file (`.svelte`) and use it to generate 2 output files (`.js` and `.css`).
```js
const fs = require('fs').promises;
const svelte = require('svelte/compiler');
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'my-svelte-plugin',
resolve: {
input: ['.svelte'],
output: ['.js', '.css'],
},
async load({ filePath }) {
const fileContents = await fs.readFile(filePath, 'utf-8');
const { js, css } = svelte.compile(fileContents, { filename: filePath });
return {
'.js': js && js.code,
'.css': css && css.code,
};
},
};
};
```
This is a simplified version of the official Snowpack Svelte plugin. Don't worry if you're not familiar with Svelte, just know that building a Svelte file (`.svelte`) generates both JS & CSS for our final build.
In that case, the `resolve` property takes only a single `input` file type (`['.svelte']`) but two `output` file types (`['.js', '.css']`). This matches the result of Svelte's build process and the returned entries of our `load()` method.
**See it in action:** Let's say that we have a source file at `src/components/App.svelte`. Because the `.svelte` file extension matches an extension in our plugin's `resolve.input` array, Snowpack lets this plugin claim responsibility for loading this file. `load()` executes, Svelte builds the file from disk, and both JavaScript & CSS are returned to the final build.
Notice that `.svelte` is missing from `resolve.output` and isn't returned by `load()`. Only the files returned by the `load()` method are included in the final build. If you wanted your plugin to keep the original source file in your final build, you could add `{ '.svelte': contents }` to the return object.
### Example: Server-Side Rendering (SSR)
Plugins can produce server-optimized code for SSR via the `load()` plugin hook. The `isSSR` flag tells the plugin that Snowpack is requesting your file for the server, and that it will expect a response that will run on the server.
Some frameworks/languages (like React) run the same code on both the browser and the server. Others (like Svelte) will create different output for the server than the browser. In the example below, we use the `isSSR` flag to tell the Svelte compiler to generate server-optimized code when requested by Snowpack.
```js
const svelte = require('svelte/compiler');
const fs = require('fs');
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'basic-svelte-plugin',
resolve: {
input: ['.svelte'],
output: ['.js', '.css'],
},
async load({ filePath, isSSR }) {
const svelteOptions = {
/* ... */
};
const codeToCompile = fs.readFileSync(filePath, 'utf-8');
const result = svelte.compile(codeToCompile, {
...svelteOptions,
ssr: isSSR,
});
// ...
},
};
};
```
If you're not sure if your plugin needs special SSR support, you are probably fine to skip this and ignore the `isSSR` flag in your plugin. Many languages won't need this, and SSR is always an intentional opt-in by the user.
### Example: Optimizing & Bundling
Snowpack supports pluggable bundlers and other build optimizations via the `optimize()` hook. This method runs after the build and gives plugins a chance to optimize the final build directory. Webpack, Rollup, and other build-only optimizations should use this hook.
```js
module.exports = function(snowpackConfig, pluginOptions) {
return {
name: 'my-custom-webpack-plugin',
async optimize({ buildDirectory }) {
await webpack.run({...});
}
};
};
```
This is an (obviously) simplified version of the `@snowpack/plugin-webpack` plugin. When the build command has finished building your application, this plugin hook is called with the `buildDirectory` path as an argument. It's up to the plugin to read build files from this directory and write any changes back to the directory. Changes should be made in place, so write files only at the end and be sure to clean up after yourself (if a file is no longer needed after optimizing/bundling, it is safe to remove).
### Testing
To develop and test a Snowpack plugin, the strategy is the same as with other npm packages:
- Create your new plugin project (either with `npm init` or `yarn init`) with, for example, npm name: `my-snowpack-plugin` and paste in it the above-mentioned code snipped
- Run `npm link` in your plugins project folder to expose the plugin globally (in regard to your development machine).
- Create a new, example Snowpack project in a different location for testing
- In your example Snowpack project, run `npm install && npm link my-snowpack-plugin` (use the name from your plugins `package.json`).
- Be aware that `npm install` will remove your linked plugin, so on any install, you will need to redo the `npm link my-snowpack-plugin`.
- (The alternative would be to use `npm install --save-dev &lt;folder_to_your_plugin_project&gt;`, which would create the "symlink-like" entry in your example Snowpack projects `package.json`)
In your example Snowpack project, add your plugin to the `snowpack.config.json` along with any plugin options youd like to test:
```json
{
"plugins": [
["my-snowpack-plugin", { "option-1": "testing", "another-option": false }]
"
}
```
### Publishing a Plugin
To share a plugin with the world, you can publish it to npm. For example, take a look at [snowpack-plugin-starter-template](https://github.com/snowpackjs/snowpack-plugin-starter-template) which can get you up-and-running quickly. You can either copy this outright or simply take what you need.
In general, make sure to mind the following checklist:
- ✔️ Your `package.json` file has a `main` entry pointing to the final build
- ✔️ Your code is compiled to run on Node >= 10
- ✔️ Your package README contains a list of custom options, if your plugin is configurable
### Tips / Gotchas
- Remember: A source file will always be loaded by the first `load()` plugin to claim it, but the build result will be run through every `transform` function.
- Snowpack will always keep the original file name (`App`) and only ever change the extension in the build.
- Extensions in Snowpack always have a leading `.` character (e.g. `.js`, `.ts`). This is to match Nodes `path.extname()` behavior, as well as make sure were not matching extension substrings (e.g. if we matched `js` at the end of a file, we also dont want to match `.mjs` files by accident; we want to be explicit there).
- The `resolve.input` and `resolve.output` file extension arrays are vital to how Snowpack understands your build pipeline, and are always required for `load()` to run correctly.
- If `load()` doesn't return anything, the file isnt loaded and the `load()` of the next suitable plugin is called.
- If `transform()` doesn't return anything, the file isnt transformed.
- If you want to build a plugin that runs some code only on initialization (such as `@snowpack/plugin-dotenv`), put your side-effect code inside the function that returns your plugin. But be sure to still return a plugin object. A simple `{ name }` object will do.

View file

@ -0,0 +1,34 @@
---
layout: layouts/content.hmx
title: 'PostCSS'
tags: communityGuide
published: true
img: '/img/logos/postcss.svg'
imgBackground: '#f8f8f2'
description: How to use PostCSS in your Snowpack project.
---
[PostCSS](https://postcss.org/) is a popular CSS transpiler with support for [a huge ecosystem of plugins.](https://github.com/postcss/postcss#plugins)
**To use PostCSS with Snowpack:** add the [@snowpack/plugin-postcss](https://www.npmjs.com/package/@snowpack/plugin-postcss) plugin to your project.
```diff
// snowpack.config.js
"plugins": [
+ "@snowpack/plugin-postcss"
]
```
PostCSS requires a [`postcss.config.js`](https://github.com/postcss/postcss#usage) file in your project. By default, the plugin looks in the root directory of your project, but you can customize this yourself with the `config` option. See [the plugin README](https://www.npmjs.com/package/@snowpack/plugin-postcss) for all available options.
```js
// postcss.config.js
// Example (empty) postcss config file
module.exports = {
plugins: [
// ...
],
};
```
Be aware that this plugin will run on all CSS in your project, including any files that compiled to CSS (like `.scss` Sass files, for example).

View file

@ -0,0 +1,21 @@
---
layout: layouts/content.hmx
title: Preact
tags: communityGuide
img: '/img/logos/preact.svg'
imgBackground: '#333333'
description: With Snowpack you can import and use Preact without any custom configuration needed.
---
You can import and use Preact without any custom configuration needed.
**To use `preact/compat`:** (the Preact+React compatability layer) alias the "compat" package to React in your install options:
```js
// Example: Lets you import "react" in your application, but uses preact internally
// snowpack.config.json
"alias": {
"react": "preact/compat",
"react-dom": "preact/compat"
}
```

View file

@ -0,0 +1,41 @@
---
layout: layouts/content.hmx
title: React + babel-plugin-import-global
published: false
---
<div class="notification">
This guide has an example repo:
<a href="https://github.com/snowpackjs/snowpack/examples/react-global-imports">examples/react-global-imports</a>
</div>
_Based on [app-template-react][app-template-react]_
Example of using Snowpack in conjuction with [babel-plugin-import-global][babel-plugin-import-global]. This is useful when you need to need to inject an import statement at the top of every file, such as React:
```jsx
// "import React from 'react'" no longer needed!
function MyComponent() {
// …
}
export default MyComponent;
```
To recreate this setup, follow 2 steps:
1. Create a [babel.config.js](./babel.config.js) file in the root of the project. Copy the settings shown.
2. Install [@snowpack/plugin-babel][snowpack-babel] and add it to [snowpack.config.js](./snowpack.config.js)
### ⚠️ Caveat
When you use [@snowpack/plugin-babel][snowpack-babel], you miss out on the faster builds that come from Snowpacks default JS builder, [esbuild][esbuild] (we dont run both together to avoid conflict). However, if you skip Babel, you will have to manually place `import` statements yourself at the top of every file.
Wed recommend being explicit and manually managing every `import` statement yourself. You can simplify your setup, speed up your builds, and you might see benefits from being explicit. In order to do this, simply use our [React starter template][app-template-react]. No setup required.
But if youve weighed the tradeoffs and decide that a slower build is worth it to get global import functionality, then start from the example here.
[app-template-react]: https://github.com/snowpackjs/snowpack/create-snowpack-app/app-template-react
[babel-plugin-import-global]: https://www.npmjs.com/package/babel-plugin-import-global
[esbuild]: https://esbuild.github.io/
[snowpack-babel]: https://github.com/snowpackjs/snowpack/plugins/plugin-babel

View file

@ -0,0 +1,38 @@
---
layout: layouts/content.hmx
title: React + Loadable Components
published: false
---
<div class="notification">
This guide has an example repo:
<a href="https://github.com/snowpackjs/snowpack/examples/react-loadable-components">examples/react-loadable-components</a>
</div>
_Based on [app-template-react][app-template-react]_
You can lazy load React components in Snowpack when needed with Reacts builtin `React.lazy` ([docs][react-lazy]):
```jsx
import React, { useState, useEffect, Suspense } from 'react';
const Async = React.lazy(() => import('./Async'));
function Component() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<Async />
</Suspense>
</div>
);
}
```
This works out-of-the-box in Snowpack, with no configuration needed!
### Learn more
- [`React.lazy` documentation on reactjs.org][react-lazy]
[react-lazy]: https://reactjs.org/docs/code-splitting.html#reactlazy

View file

@ -0,0 +1,59 @@
---
layout: layouts/content.hmx
title: Routing
published: true
description: This guide will walk you through some common routing scenarios and how to configure the routes option to support them in development.
---
As a web build tool, Snowpack has no knowledge of how (or where) your application is served in production. But Snowpack's dev server can be customized to recreate something close to your production environment for local development.
This guide will walk you through some common routing scenarios and how to configure the `routes` option to support them in development.
### Scenario 1: SPA Fallback Paths
Single Page Applications (SPA) give the client application complete control over routing logic. The web host itself has no idea what is a valid route and what is a 404, since that logic lives completely in the client. Therefore, every route (valid or not) must be served the same HTML response that will load and run the HTML/JS/CSS application in the browser. This special file is called the "SPA Fallback".
To implement this pattern, you'll want to define a single "catch-all" route for development:
```js
// snowpack.config.js
"routes": [
{"match": "routes", "src": ".*", "dest": "/index.html"}
]
```
This tells Snowpack's dev server to serve the fallback `/index.html` URL for all routes (`.*` in RegEx means "match everything").
`"match": "routes"` refers to all URLs that either do not include a file extension or that include the ".html" file extension. If you changed the above example to `"match": "all"` instead, then all URLs (including JS, CSS, Image files and more) would respond with the fallback HTML file.
### Scenario 2: Proxy API Paths
Many modern frontend applications will talk directly to an API. Often this API is hosted as a seperate application at another domain (ex: `api.example.com/users`) and no special server configuration is needed to talk with it. However in some cases, your API may be hosted at the same domain as your website using a different path scheme (ex: `www.example.com/api/users`).
To serve the correct API response to a URL like `/api/users` in development, you can configure Snowpack to proxy some requests to another server. In this example, we'll proxy all "/api/\*" requests to another server that we have running locally on port `3001`:
```js
// snowpack.config.js
const httpProxy = require('http-proxy');
const proxy = httpProxy.createServer({ target: 'http://localhost:3001' });
module.exports = {
routes: [
{
src: '/api/.*',
dest: (req, res) => {
// remove /api prefix (optional)
req.url = req.url.replace(/^\/api/, '');
proxy.web(req, res);
},
},
],
};
```
We recommend the [http-proxy](https://github.com/http-party/node-http-proxy) library for proxying requests to another server, which supports a wide range of options to customize how each request is proxied. But feel free to implement the `dest` proxy function however you like. Your own server logic could even be called directly inside of the `dest` function, however this is not recommended over proxying.
### Scenario 3: Custom Server Rendering
If you only use Snowpack to build assets and rely on your own custom server (ex: Rails, Laravel, etc) for serving HTML, then you probably have no use for routing. Consider reading our guide on [Server-Side Rendering (SSR)](/guides/server-side-render) which explains how to integrate Snowpack into your own server as middleware.

View file

@ -0,0 +1,24 @@
---
layout: layouts/content.hmx
title: 'Sass'
tags: communityGuide
published: true
img: '/img/logos/sass.svg'
imgBackground: '#bf4080'
description: How to use SASS with Snowpack using the Snowpack SASS plugin
---
<div class="stub">
This article is a stub, you can help expand it into <a href="https://documentation.divio.com/how-to-guides/">guide format</a>
</div>
[Sass](https://www.sass-lang.com/) is a stylesheet language thats compiled to CSS. It allows you to use variables, nested rules, mixins, functions, and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized and makes it easy to share design within and across projects.
**To use Sass with Snowpack:** use [@snowpack/plugin-sass](https://www.npmjs.com/package/@snowpack/plugin-sass).
```diff
// snowpack.config.js
"plugins": [
+ "@snowpack/plugin-sass"
]
```

View file

@ -0,0 +1,87 @@
---
layout: layouts/content.hmx
title: Server-Side Rendering (SSR)
description: This guide will walk you through three different options for setting up Snowpack with your own custom server.
published: true
---
Server-side rendering (SSR) can refer to several similar developer stories:
- Using Snowpack with a server web framework like Rails or Express
- Using Snowpack to power a server-side frontend framework kit like Next.js or SvelteKit
- Any project configuration where your HTML is generated at runtime, outside of your static build.
This guide will walk you through three options for setting up Snowpack with your own custom server:
1. `snowpack build --watch` - Serve files out of the static build directory.
2. `startServer({ ... })` - Serve files on-demand via Snowpack's JavaScript API.
3. `getServerRuntime({ ... })` - Run your built JS files server-side, directly inside of Node.js.
### Option 1: Static Serving
Serving built files directly out of Snowpack's `build/` directory is the easiest way to get started with Snowpack. Run `snowpack build` to build your site to a static directory, and then make sure that your HTML server response includes the appropriate `script` & `link` tags to load your Snowpack-built JavaScript and CSS:
```html
<!-- Example: If you own the server HTML response, make sure that you host the built assets and load the correct JS/CSS files in your HTML. -->
<script type="module" src="/dist/index.js"></script>
```
During development, Snowpack will rebuild files on every change thanks to the `--watch` command. To enable dev features like automatic page reloads and hot module replacement (HMR), check out the ["Custom Server" section](/guides/hmr#enable-hmr%3A-custom-server) of our HMR guide for more info.
This setup also has the benefit of pulling from the same `build/` directory in both development and production. You can control this `build/` output behavior yourself by passing different `--out` CLI flags to Snowpack for development vs production. You can even pass entirely different config files via the `--config` CLI flag, or put custom logic in your `snowpack.config.js` file to behave differently for different builds.
The downside of this static approach is that you need to wait for Snowpack to build the entire `build/` directory on startup before your site will run. This is something that all other build tools (like Webpack) have to deal with, but Snowpack has the ability to build files only when they are requested by the browser, leading to ~0ms startup wait time.
### Option 2: On Demand Serving (Middleware)
The best developer experience is achieved by loading files on-demand. This removes any need for work on startup, giving you a faster developer environment no matter how large your project grows.
```js
const {startServer} = require('snowpack');
const server = await startServer({ ... });
// Example: Express
// On request, build each file on request and respond with its built contents
app.use((req, res, next) => {
try {
const buildResult = await server.loadUrl(req.url);
res.send(buildResult.contents);
} catch (err) {
next(err);
}
});
```
Note that you'll still need to set up static file serving out of the `build/` directory for production deployments. For that reason, this can be seen as an enhancement over the static setup in Option 1 for faster development speeds.
While our official API is written in JavaScript and requires Node.js to run, you could implement your own API for any language/environment using the `snowpack dev` CLI command to start the server and loading assets directly by fetching each URL.
### Option 3: Server-Side Rendering (SSR)
Some frontend applications are also designed to run on the server. In the two previous sections, we've just been loading and serving Snowpack files to the client. In this final section, we'll look into how your project can run Snowpack-built JavaScript on the server and return server-rendered HTML to the client for a faster first page load.
Snowpack provides an Node.js SSR Runtime API to help you run & render your application server-side. `getServerRuntime()` returns a `runtime` instance that can be used to import Snowpack-built modules into your current Node.js process, on-demand. This runtime handles the transformation from browser ESM to Node.js Common.js (CJS) so that it can run directly in server without issues.
```js
const {readFileSync} = require('fs');
const {startServer} = require('snowpack');
const server = await startServer({ ... });
const runtime = server.getServerRuntime();
// Advanced Example: Express + React SSR
app.use(async (req, res, next) => {
// Server-side import our React component
const importedComponent = await runtime.importModule('/dist/MyReactComponent.js');
const MyReactComponent = importedComponent.exports.default;
// Render your react component to HTML
const html = ReactDOMServer.renderToString(React.createElement(MyReactComponent, null));
// Load contents of index.html
const htmlFile = fs.readFileSync('./index.html', 'utf8');
// Inserts the rendered React HTML into our main div
const document = htmlFile.replace(/<div id="app"><\/div>/, `<div id="app">${html}</div>`);
// Sends the response back to the client
res.send(document);
});
```
`getServerRuntime()` is a lower-level tool to help you implement SSR in your project. However, building a custom SSR setup is an advanced task. If you prefer not to implement this yourself, check out some of the new Snowpack-powered application frameworks and static site generators like [SvelteKit](https://svelte.dev/blog/whats-the-deal-with-sveltekit) and [Microsite](https://www.npmjs.com/package/microsite).

View file

@ -0,0 +1,74 @@
---
layout: layouts/content.hmx
title: Streaming Imports
published: true
stream: Fetch your npm dependencies on-demand from a remote ESM CDN.
---
Snowpack v3.0 introduces a new feature called **Streaming Imports** that fetches imported packages on-demand during development and building. By managing your frontend dependencies with Snowpack, you can leave `npm` for your tooling-only packages or even drop your dependency on `npm`/`yarn`/`pnpm` all togther.
## Enable Streaming Imports
```js
// snowpack.config.js
"packageOptions": {
"source": "remote"
}
```
Set `packageOptions.source` to "remote" to enable streaming imports. This tells Snowpack to fetch your imports from our remote CDN instead of bundling them locally. Read our [full documentation on `packageOptions`](/reference/configuration#packageoptions.source%3Dremote) to learn more about customizing this behavior.
## How Streaming Imports Work
When you enable streaming imports, `snowpack` will start fetching all imports from `https://pkg.snowpack.dev`. For example, `import "preact"` in your project will become something like `import "https://pkg.snowpack.dev/preact"` in the browser. This tells Snowpack (or the browser) to import your package by URL, and only fetch the package ESM when needed. Snowpack is able to cache the response for future, offline use.
`pkg.snowpack.dev` is our ESM Package CDN, powered by [Skypack](https://www.skypack.dev/). Every npm package is hosted as ESM, and any legacy non-ESM packages are upconverted to ESM on the CDN itself.
## Benefits of Streaming Imports
Streaming dependencies have several benefits over the traditional "npm install + local bundling" approach:
- **Speed:** Skip the install + build steps for dependencies, and load your dependencies as pre-build ESM code directly from an ESM CDN like [Skypack](https://www.skypack.dev/). Dependencies are cached locally for offline reuse.
- **Safety:** ESM packages are pre-built and never given access to [run code on your machine](https://www.usenix.org/system/files/sec19-zimmermann.pdf). Packages only run in the browser sandbox.
- **Simplicity:** ESM packages are managed by Snowpack, so frontend projects that don't need Node.js (Rails, PHP, etc.) can drop the `npm` CLI entirely if they choose.
- **No Impact on Final Build:** Streaming imports are still transpiled and bundled with the rest of your final build, and tree-shaken to your exact imports. The end result is a final build that's nearly identical to what it would have been otherwise.
## Snowpack-Managed Dependencies
By default, Snowpack fetches the latest version of every package available. Breaking changes are possible over time without a way to manage your dependencies by version.
Snowpack uses a `snowpack.deps.json` in your project to manage your dependency versions. If you're familiar with `npm install`, your `snowpack.deps.json` file is like a combined `package.json` and `package-lock.json`.
Two commands are available to work with this file: `snowpack add` and `snowpack rm`.
Running `snowpack add [package-name]` for the first time will create a new `snowpack.deps.json` file in your project to store information about your new dependency, like desired SemVer version range and lockfile information.
## Using Streaming Imports with TypeScript
```js
// snowpack.config.js /w TypeScript Support
"packageOptions": {
"source": "remote",
"types": true,
}
```
Setting `types=true` tells Snowpack to install TypeScript types in your project. Snowpack will install those types into a local `.snowpack/types` directory in your project, which you can then point to in your project `tsconfig.json` to get automatic types for your npm packages:
```js
// Example: tsconfig.json /w Snowpack streaming imports
"baseUrl": "./",
"paths": {"*": [".snowpack/types/*"]},
```
When you start your project (with either `snowpack dev` or `snowpack build`) Snowpack will sync this `.snowpack/types` directory and download any new types that you might need. You can also trigger a sync anytime manually via `snowpack prepare`.
## Using Streaming Imports with Non-JS Packages (Svelte, Vue, etc.)
Skypack (the CDN that powers `pkg.snowpack.dev`) will always prefer a package JavaScript entrypoint over any source `.svelte` and `.vue` files. This works for most packages (including most Svelte & Vue packages) but may cause trouble in some projects. In a future release, we'll add better support to build these kinds of packages locally.
## What do I do if a package isn't supported / working?
Skypack (the CDN that powers `pkg.snowpack.dev`) is always improving, and its goal is to support all packages. If you find a package that doesn't work, report it to [Skypack's issue tracker](https://github.com/snowpackjs/skypack-cdn/issues) on GitHub. Many of Snowpack's core contributors also work on Skypack, and will be happy to take a look at the broken package.
In a future release, we'll add better support to replace broken packages locally.

View file

@ -0,0 +1,57 @@
---
layout: layouts/content.hmx
title: 'Tailwind CSS'
tags: communityGuide
published: true
img: '/img/logos/tailwind.svg'
imgBackground: '#f2f8f8'
description: How to use Tailwind CSS with Snowpack.
---
[Tailwind](https://tailwindcss.com) is a popular class-based CSS utility library.
### Using Tailwind with Native CSS
The easiest way to use Tailwind is via native CSS `@import` _or_ JS `import`.
```css
/* index.css */
@import 'tailwindcss/dist/tailwind.css';
```
```js
/* index.js */
import 'tailwindcss/dist/tailwind.css';
```
This imports Tailwind's full CSS build into your application. This simple usage comes at the cost of performance: Tailwind's full CSS build is 3.5+ MB of CSS. For any serious production use, the Tailwind team **strongly** recommends using [PostCSS](https://postcss.org/).
#### Using Tailwind with PostCSS
Follow our [PostCSS guide](/guides/postcss) to set up PostCSS in your Snowpack project. Then, add Tailwind and autoprefixer as plugins to your `postcss.config.js`:
```js
// postcss.config.js
// Taken from: https://tailwindcss.com/docs/installation#using-tailwind-with-postcss
module.exports = {
plugins: [
// ...
require('tailwindcss'),
require('autoprefixer'),
// ...
],
};
```
Once the plugin is enabled, you can replace your native CSS `dist` imports with Tailwind's more powerful `base`, `components`, and `utilities` imports:
```diff
/* index.css */
- @import 'tailwindcss/dist/tailwind.css';
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
```
Follow the official [Tailwind CSS Docs](https://tailwindcss.com/docs/installation/#using-tailwind-with-postcss) for more information.

View file

@ -0,0 +1,15 @@
---
layout: layouts/content.hmx
title: Testing
published: true
description: How to choose and use a JavaScript test runner for your Snowpack site.
---
Snowpack supports all of the popular JavaScript testing frameworks that you're already familiar with. Mocha, Jest, Jasmine, AVA and Cypress are all supported in Snowpack applications, if integrated correctly.
**We currently recommend [@web/test-runner](https://www.npmjs.com/package/@web/test-runner) (WTR) for testing in Snowpack projects.** When benchmarked, it performed faster than Jest (our previous recommendation) while also providing an environment for testing that more closely matches production. Most importantly, WTR runs the same Snowpack build pipeline that you've already configured for your project, so there's no second build configuration needed to run your tests. This improves test confidence while removing 100s of extra build dependencies to your project.
### Testing Guides
- [@web/test-runner](/guides/web-test-runner) (Recommended)
- [jest](/guides/jest)

View file

@ -0,0 +1,76 @@
---
layout: layouts/content.hmx
title: Snowpack Upgrade Guide
published: true
description: How to upgrade to Snowpack v3 from older versions of Snowpack.
---
Snowpack v3.0 was released on January 12th with several new features and some breaking changes. This guide is designed to help you upgrade a project from older versions of Snowpack v1 or v2.
## Upgrading from Snowpack v3 Release Candidate
Our v3.0 Release Candidate was meant to be a close-to-final release, but some major changes still got in between then and the v3.0 final release. Snowpack will warn when any outdated APIs are used, and guide you through the upgrade process.
In the future, Snowpack Release Candidates will be much closer to final API.
## Upgrading from Snowpack v2
Snowpack v3.0 was mainly designed around new features, and therefore didn't have many major breaking changes introduced. However, there are some changes to be aware of:
- **Config name changes:** There was some cleanup of legacy behavior and renaming of old configuration values. Snowpack will warn you of all known name changes when run Snowpack v3.0 for the first time, with instructions to help you upgrade.
- **package.json "homepage" no longer sets "baseUrl":** This was a behavior of Create React App that we'd originally tried to match. However, it became confusing to explain to users. In Snowpack v3.0, set "buildOptions.baseUrl" directly.
- **Improved support for relative paths in configuration:** All relative paths in configuration files are now relative to the configuration file itself. Previously, all relative config paths were resolved based on the current working directory of wherever you ran Snowpack, which meant that behavior of the config file changed depending on where you ran it. You can also now set the project `"root"`/`--root` directory, which is useful if you run Snowpack from a different directory than the project iself (ex: in monorepos).
- **More clear build file naming:** Snowpack v3.0 introduced some cleanup around build file names that you may see when you upgrade projects. The biggest change is to files like `.svelte` and `.vue`, which now have their JS & CSS built to `.svelte.js` and `.svelte.css` respectively. This change shouldn't be noticable to most, but it is good to know.
- **More clear handling of absolute import URLs:** In Snowpack, it's now possible to import something by its final URL using an absolute URL. `import "/dist/index.js"`, for example, will now import whatever file is built to `/dist/index.js`. Previously, this behavior was undefined. Relative URLs can still be used to import files relative to the source file itself.
## Upgrading from Snowpack v1
Snowpack v1 only supported installing npm packages as ESM, and had a more limited scope than Snowpack does today. If you are coming from Snowpack v1.0, you may be able to use our internal package installer library [esinstall](https://www.npmjs.com/package/esinstall) directly. `esinstall` is a JavaScript library that implements most of what Snowpack v1.0 gave you via the command-line.
`snowpack build` builds your site into web native JS, CSS, and HTML files. This "unbundled" deployment can be enough for small sites, but many developers prefer to optimize and bundle their final site for production performance.
Snowpack can run all sorts of optimizations on your final build to handle legacy browser support, code minification, code-splitting, tree-shaking, dead code elimination, preloading, bundling, and more.
Snowpack build optimizations come in two flavors: **built-in** (esbuild) & **plugin** (webpack, rollup, or whatever else you might like to run).
### Option 1: Built-in Optimizations
Snowpack recently released a built-in optimization pipeline powered by [esbuild](https://esbuild.github.io/). Using this built-in optimizer, you can now bundle, transpile, and minify your production builds 10x-100x faster than Webpack or Rollup. However, esbuild is still young and [not yet production-ready](https://esbuild.github.io/faq/#production-readiness). At the moment, we only recommended this for smaller projects.
```js
// snowpack.config.js
// Example: Using Snowpack's built-in bundling support
{
"optimize": {
"bundle": true,
"minify": true,
"target": 'es2018'
}
}
```
The full supported interface is:
```ts
export interface OptimizeOptions {
entrypoints: 'auto' | string[] | ((options: { files: string[] }) => string[]);
preload: boolean;
bundle: boolean;
splitting: boolean;
treeshake: boolean;
manifest: boolean;
minify: boolean;
target: 'es2020' | 'es2019' | 'es2018' | 'es2017';
}
```
### Option 2: Optimize Plugins
Snowpack supports popular bundlers via plugin:
- webpack (recommended!): [@snowpack/plugin-webpack](https://www.npmjs.com/package/@snowpack/plugin-webpack)
- Rollup: [snowpack-plugin-rollup-bundle](https://github.com/ParamagicDev/snowpack-plugin-rollup-bundle)
**For now, we recommend using @snowpack/plugin-webpack until our built-in optimize support is more mature.**
Check out our [Plugins Catalog](/plugins) to browse all available Snowpack plugins, and read the [Plugins Guide](/guides/plugins) if you're interested in creating your own.

View file

@ -0,0 +1,19 @@
---
layout: layouts/content.hmx
title: Vue
tags: communityGuide
img: '/img/logos/vue.png'
imgBackground: '#f6f9f6'
description: How to use Vue with Snowpack using the Vue Plugin.
---
<div class="stub">
This article is a stub, you can help expand it into <a href="https://documentation.divio.com/how-to-guides/">guide format</a>
</div>
To support `.vue` files you will need the [Vue Plugin](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-vue), which uses Vue 3.
```js
// snowpack.config.json
"plugins": ["@snowpack/plugin-vue"]
```

View file

@ -0,0 +1,35 @@
---
layout: layouts/content.hmx
title: 'WASM'
tags: communityGuide
published: true
img: '/img/logos/wasm.svg'
imgBackground: '#f2f2f8'
description: How to use WASM in your Snowpack project.
---
[WASM (short for WebAssembly)](https://webassembly.org/) is a portable compilation target for programming languages, enabling deployment on the web for client and server applications.
**To use WASM with Snowpack:** Use the browser's native [`WebAssembly`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) & [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) APIs to load a WASM file into your application:
```js
// Example: Load WASM in your project
const wasm = await WebAssembly.instantiateStreaming(
fetch('/example.wasm'),
/* { ... } */
);
```
In the future, we may add `import "/example.wasm"` ESM import support to automate this support for you. However, today WASM import support differs from bundler-to-bundler.
In any case, WASM import support would just be a shortcut or wrapper around the code snippet above. You can recreate this helper today in your own project:
```js
// Example: WASM Loader (move this into some utilility/helper file for reuse)
export function loadWasm(url, importObject = {module: {}, env: {abort() {}}}) => {
const result = await WebAssembly.instantiateStreaming(fetch(url), importObject);
return result.instance; // or, return result;
}
const wasm = await loadWasm('/example.wasm');
```

View file

@ -0,0 +1,21 @@
---
layout: layouts/content.hmx
title: '@web/test-runner'
tags: communityGuide
img: '/img/logos/modern-web.svg'
imgBackground: '#f2f2f8'
description: How to use @web/test-runner in your Snowpack project.
---
[@web/test-runner](https://www.npmjs.com/package/@web/test-runner) is our recommended test runner for Snowpack projects. Read more about why we recommend @web/test-runner in our [Snowpack Testing Guide](/guides/testing).
To use [@web/test-runner](https://www.npmjs.com/package/@web/test-runner) in your project, [follow the instructions here](https://modern-web.dev/docs/test-runner/overview/) and make sure that you add the Snowpack plugin to your config file:
```js
// web-test-runner.config.js
module.exports = {
plugins: [require('@snowpack/web-test-runner-plugin')()],
};
```
[See an example setup](https://github.com/snowpackjs/snowpack/blob/main/create-snowpack-app/app-template-react) in one of our Create Snowpack App starter templates.

View file

@ -0,0 +1,49 @@
---
layout: layouts/content.hmx
title: 'Web Workers'
tags: communityGuide
published: true
description: How to use Web Workers in your Snowpack project.
---
[Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) are a simple means for web content to run scripts in background threads.
**To use Web Workers with Snowpack:** Use the browser's native [Web Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Web_Workers_API) directly:
```js
// Example: Load a Web Worker in your project
const myWorker = new Worker(new URL('./worker.js', import.meta.url));
```
Passing a `URL` to the Worker constructor (instead of a string literal) is recommended, but not required. Using a string literal (ex: `new Worker('./worker.js')`) may prevent some optimizations when you build your site for production.
Also note that the URL passed to the `Worker` must match the final URL which may differ from the path on disk. For example, `./worker.js` would still be used even if the original file on disk was `worker.ts`. `mount` destinations should also be used here, if needed.
### ESM Web Worker Support
**ESM syntax (`import`/`export`) in Web Workers is still not supported in all modern browsers.** Snowpack v3.0.0 and the Snowpack Webpack v5 plugin will both support automatic bundling once released. Until then, you'll need to write self-contained, single-file Web Workers (no ESM `import`/`export` statements) or pre-bundle your web workers yourself.
```js
const worker = new Worker(new URL('./esm-worker.js', import.meta.url), {
name: 'my-worker',
type: 'module',
});
```
<!--
TO REPLACE THE PREVIOUS PARAGRAPH ON v3.0.0 LAUNCH DAY:
Modern browsers have begun to support ESM syntax (`import`/`export`) inside of Web Workers. However, some notable exceptions still exist. To use ESM syntax inside of a web worker, consult [caniuse.com](https://caniuse.com/mdn-api_worker_worker_ecmascript_modules) and choose a supported browser for your local development. When you build for production, choose a bundler that will bundle your Web Worker to remove ESM import/export syntax. Currently, Snowpack's builtin bundler and @snowpack/plugin-webpack both support automatic Web Worker bundling to remove ESM syntax from web workers.
```js
const worker = new Worker(
new URL('./esm-worker.js', import.meta.url),
{
name: 'my-worker',
type: import.meta.env.MODE === 'development' ? "module" : "classic"
}
);
```
-->

View file

@ -0,0 +1,14 @@
---
layout: layouts/content.hmx
title: Workbox
tags: communityGuide
description: The Workbox CLI integrates well with Snowpack.
---
<div class="stub">
This article is a stub, you can help expand it into <a href="https://documentation.divio.com/how-to-guides/">guide format</a>
</div>
The [Workbox CLI](https://developers.google.com/web/tools/workbox/modules/workbox-cli) integrates well with Snowpack. Run the wizard to bootstrap your first configuration file, and then run `workbox generateSW` to generate your service worker.
Remember that Workbox expects to be run every time you deploy, as a part of a production build process. If you don't have one yet, create package.json [`"deploy"` and/or `"build"` scripts](https://michael-kuehnel.de/tooling/2018/03/22/helpers-and-tips-for-npm-run-scripts.html) to automate your production build process.

View file

@ -0,0 +1,98 @@
<script hmx="setup">
import Menu from '../components/Menu.hmx';
import Hero from '../components/Hero.hmx';
export function setup() {
return {
layout: 'layouts/base.hmx',
props: {}
}
}
</script>
<head>
<!-- Head Stuff -->
</head>
<body>
<Hero bar={title}></Hero>
<div foo={title} class="container" style="margin: 0 auto">
<section class="snow-view__docs is-full is-home">
<aside id="nav-primary" class="snow-view-nav">
<Menu></Menu>
</aside>
<article class="snow-view-main">
<div class="content">
<article class="grid-body">
<a class="img-banner" href="https://osawards.com/javascript/2020" target="_blank"
rel="noopener noreferrer">
<img src="/img/JSAwardWinner.png" alt="2020 JavaScript Open Source Award Winner banner" />
</a>
<div class="content markdown-body feature-list">
<div class="feature-list-top">
<p>
<strong>Snowpack is a lightning-fast frontend build tool, designed for the modern web.</strong>
It is an alternative to heavier, more complex bundlers like webpack or Parcel in your development
workflow. Snowpack leverages JavaScript's native module system (<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">known
as
ESM</a>) to avoid unnecessary work and stay fast no matter how big your project grows.
</p>
<p>Once you try it, it's impossible to go back to anything else.</p>
</div>
<ul class="feature-list-bullets">
<li class="feature-list-bullet">
<h3>Instant startup</h3>
Snowpack's unbundled web development server
<strong>starts up in 50ms or less</strong>
and stays fast in large projects.
</li>
<li class="feature-list-bullet">
<h3>Build once, cache forever</h3>
Snowpack never builds the same file twice. Powered by JavaScripts native module system (ESM) in the
browser.
</li>
<li class="feature-list-bullet">
<h3>HMR feat. Fast Refresh</h3>
No refresh required. See changes reflected instantly in the browser with
<a href="/concepts/hot-module-replacement">HMR + Fast Refresh</a>
for React, Preact & Svelte.
</li>
<li class="feature-list-bullet">
<h3>Out-of-the-box support</h3>
Enjoy Snowpack's built-in support for JSX, TypeScript, React, Preact, CSS Modules
<a href="/reference/supported-files">and more.</a>
</li>
<li class="feature-list-bullet">
<h3>Optimize for production</h3>
Build for production with built-in optimizations and plugin support for your favorite bundlers.
</li>
<li class="feature-list-bullet">
<h3>Plugins? Plugins!</h3>
Babel? Sass? MDX? Browse the entire
<a href="/plugins">Snowpack Plugin Catalog</a>
to connect your favorite build tool (or
<a href="/reference/plugins">create your own!</a>)
</li>
</ul>
<div class="feature-list-buttons">
<a href="/tutorials/quick-start" class="button button-primary feature-list-button">Get started</a>
<a href="/concepts/how-snowpack-works" class="button feature-list-button">Learn more</a>
</div>
</div>
</article>
</div>
</article>
</section>
</div>
<!-- Place this tag in your head or just before your close body tag. -->
<script async="async" defer="defer" src="https://buttons.github.io/buttons.js"></script>
</body>

View file

@ -0,0 +1,73 @@
<script hmx="setup">
import Card from '../components/Card.jsx';
import CompanyLogo from '../components/CompanyLogo.jsx';
import NewsAssets from '../components/NewsAssets.svelte';
import NewsTitle from '../components/NewsTitle.vue';
import news from '../data/news.json';
import users from '../data/users.json';
export function setup({ findContent }) {
return {
title: 'Community & News',
description: "Snowpack community news and companies that use Snowpack.",
layout: 'layouts/main.hmx',
// Using Snowpack? Want to be featured on snowpack.dev?
// Add your project, organization, or company to the end of this list!
props: {
news,
users,
}
};
}
</script>
<head> </head>
<body>
<NewsTitle title={title} />
<p>
Get the latest news, blog posts, and tutorials on Snowpack. <a href="/feed.xml">Also available via RSS.</a>
</p>
<p>
Got something that you think we should feature?
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_data/news.js">Submit it!</a>
</p>
<div class="card-grid card-grid-3">
<article class="discord-banner">
<a href="https://discord.gg/snowpack" style="flex-shrink: 0; height: 48px;"><img alt="Join us on Discord!"
src="https://img.shields.io/discord/712696926406967308.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2"
style="height: 48px; border: none; margin-right: 1rem; filter: brightness(1.2) contrast(1.5);" /></a>
<div>Join us on Discord to discuss Snowpack, meet other developers in our community, and show off what youre
working on!</div>
</article>
{props.news.reverse().map((item) => <Card:dynamic item={item} />)}
</div>
<div class="content">
<h3>Who's Using Snowpack?</h3>
<div class="company-logos">
{props.users.map((user) => <CompanyLogo user={user} />)}
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_template/news.md" target="_blank"
title="Add Your Project/Company!" class="add-company-button">
<svg style="height: 22px; margin-right: 8px;" aria-hidden="true" focusable="false" data-prefix="fas"
data-icon="plus" class="company-logo" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path fill="currentColor"
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z">
</path>
</svg>
Add your logo
</a>
</div>
<NewsAssets />
</div>
</body>

View file

@ -0,0 +1,36 @@
<script hmx="setup">
import news from '../data/news.json';
import users from '../data/users.json';
import PluginSearchPage from '../components/PluginSearchPage.jsx';
export function setup({ findContent }) {
return {
title: 'The Snowpack Plugin Catalog',
description: 'Snowpack plugins allow for configuration-minimal tooling integration.',
layout: 'layouts/main.hmx',
// Using Snowpack? Want to be featured on snowpack.dev?
// Add your project, organization, or company to the end of this list!
props: {
news,
users,
}
};
}
</script>
<head>
</head>
<body>
<h2 class="content-title">
{ title }
</h2>
<h3 class="pluginPage-subheading">Customize Snowpack with optimized build plugins.</h3>
<p class="pluginPage-intro">To learn more about our plugin system, check out the
<a href="/reference/plugins">Plugin API.</a><br />Can't find what you need?
<a href="/reference/plugins">Creating your own plugin is easy!</a>
</p>
<PluginSearchPage:dynamic />
</body>

View file

@ -0,0 +1,147 @@
---
layout: layouts/post.hmx
bannerVideo: '/img/extra-space-4.mp4'
permalink: '/posts/2020-05-26-snowpack-2-0-release/'
title: Snowpack v2.0
description: 'Build web applications with less tooling and faster iteration.'
tagline: v2.0.0 release post
date: 2020-05-26
---
After 40+ beta versions & release candidates we are very excited to introduce **Snowpack 2.0: A build system for the modern web.**
- Starts up in <50ms and stays fast in large projects.
- Bundle-free development with bundled production builds.
- Built-in support for TypeScript, JSX, CSS Modules and more.
- Works with React, Preact, Vue, Svelte, and all your favorite libraries.
- [Create Snowpack App (CSA)](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/cli) starter templates.
<br/>
```bash
# install with npm
npm install --save-dev snowpack
# install with yarn
yarn add --dev snowpack
```
## The Road to Snowpack 2.0
Snowpack 1.0 was designed for a simple mission: install npm packages to run directly in the browser. The theory was that JavaScript packages are the only thing still **_requiring_** the use of a bundler during development. Remove that requirement, remove the bundler, and speed up web development for everyone.
Guess what? It worked! Thousands of developers started using Snowpack to install their dependencies and build websites with less tooling. A whole new type of faster, lighter-weight dev environment suddenly became possible.
**Snowpack 2.0 is a build system designed for this new era of web development.** Snowpack removes the bundler from your dev environment, leveraging native [ES Module (ESM)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) support to serve built files directly to the browser. This isn't just a faster tool, it's a new approach to web build systems.
## The Rise of O(1) Build Systems
![webpack vs. snowpack diagram](/img/snowpack-unbundled-example-3.png)
**Bundling is a process of `O(n)` complexity.** When you change a file, you can't just rebuild that one file. You often need to rebuild and rebundle an entire chunk of your application across multiple related files to properly accept the new changes.
**Snowpack is an O(1) build system.** The term was first coined by [Ives van Hoorne](https://www.youtube.com/watch?v=Yu9zcJJ4Uz0) and it perfectly encapsulates our vision for the future of web development. Every file built with Snowpack can be expressed as a function: `build(file) => result`. When a file is changed during development, only that file is rebuilt.
This has several advantages over the traditional bundled dev approach:
- O(1) builds are faster.
- O(1) builds are predictable.
- O(1) builds are easy to reason about & configure.
- Project size doesn't affect build time during development.
- Individual files cache better.
That last point is key: every built file is cached individually and reused indefinitely. **If you never change a file, you will never need to re-build it again.**
## `dev` A Faster Dev Environment
![dev command output example](/img/snowpack-dev-startup-2.png)
Run `snowpack dev` to start your new web dev environment and the first thing you'll notice is **how flippin' fast O(1) build tooling is.** Snowpack starts up in less than 50ms. That's no typo: 50 milliseconds or less.
With no bundling work needed to start, your server spins up immediately. On your very first page load, Snowpack builds your first requested files and then caches them for future use. Even if your project contains a million different files, Snowpack builds only those needed to load the current page. This is how Snowpack stays fast.
`snowpack dev` includes a development server and a bunch of familiar features right out of the box:
- TypeScript Support
- JSX Support
- Hot Module Replacement (HMR)
- Importing CSS & CSS Modules
- Importing Images & Other Assets
- Custom Routing
- Proxying Requests
## Customizing Your Build
[Build Scripts](/concepts/build-pipeline) let you connect your favorite build tools. With Snowpack, you express every build as a linear `input -> build -> output` workflow. This allow Snowpack to pipe your files into and out of any existing UNIX-y CLI tools without the need for a special plugin ecosystem.
```js
// snowpack.config.json
{
"scripts": {
// Pipe every "*.css" file through the PostCSS CLI
// stdin (source file) > postcss > stdout (build output)
"build:css": "postcss",
}
}
```
If you've ever used your `package.json` "scripts" config, this format should feel familiar. We love the simplicity of using your CLIs directly without an unnecessary plugin system. We hope this pattern offers a similar intuitive design.
If you want more control over your build (or want to write your own build tool) Snowpack also supports [third-party JavaScript plugins](/plugins). [Check out our docs](/concepts/build-pipeline) to learn more about customizing your build.
## `build` Bundling for Production
![build output example](/img/snowpack-build-example.png)
To be clear, Snowpack isn't against bundling for production. In fact, we recommend it. File minification, compression, dead-code elimination and network optimizations can all make a bundled site run faster for your users, which is the ultimate goal of any build tool.
Snowpack treats bundling as a final, production-only build optimization. By bundling as the final step, you avoid mixing build logic and bundle logic in the same huge configuration file. Instead, your bundler gets already-built files and can focus solely on what it does best: bundling.
Snowpack maintains official plugins for both Webpack & Parcel. Connect your favorite, and then run `snowpack build` to build your site for production.
```js
// snowpack.config.json
{
// Optimize your production builds with Webpack
"plugins": [["@snowpack/plugin-webpack", {/* ... */}]]
}
```
If you don't want to use a bundler, that's okay too. Snowpack's default build will give you an unbundled site that also runs just fine. This is what the Snowpack project has been all about from the start: **Use a bundler because you want to, and not because you need to.**
## Try Snowpack Today
We are so excited to share this all with you today. Download Snowpack to experience the future of web development.
```
npm i snowpack@latest --save-dev
```
If you already have an existing Snowpack application, Snowpack 2.0 will walk you through updating any outdated configuration. Snowpack's original package installer still works as expected, and with the new `dev` & `build` commands Snowpack even manages your web packages for you.
**[Check out our docs site to learn more.](https://www.snowpack.dev/)**
#### Create Snowpack App
The easiest way to get started with Snowpack is with [Create Snowpack App (CSA)](https://github.com/snowpackjs/snowpack). CSA automatically initializes a starter application for you with a pre-configured, Snowpack-powered dev environment.
```bash
npx create-snowpack-app new-dir --template [SELECT FROM BELOW] [--use-yarn]
```
- [@snowpack/app-template-blank](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-blank)
- [@snowpack/app-template-react](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-react)
- [@snowpack/app-template-react-typescript](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-react-typescript)
- [@snowpack/app-template-preact](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-preact)
- [@snowpack/app-template-svelte](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-svelte)
- [@snowpack/app-template-vue](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-vue)
- [@snowpack/app-template-lit-element](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-lit-element)
- [@snowpack/app-template-11ty](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-11ty)
- **[See all community templates](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app)**
🐹 Happy hacking!
---
_Thank you to all of our [80+ contributors](https://github.com/snowpackjs/snowpack/graphs/contributors) for making this release possible._
_Thanks to [Melissa McEwen](https://twitter.com/melissamcewen) & [@TheoOnTwitch](https://twitter.com/TheoOnTwitch) for helping to edit this post._

View file

@ -0,0 +1,98 @@
---
layout: layouts/post.hmx
title: Snowpack 2.7
description: 'A new plugin API plus smaller, faster production builds.'
tagline: v2.7.0 release post
permalink: '/posts/2020-07-30-snowpack-2-7-release/'
date: 2020-07-30
bannerImage: '/img/banner-2.jpg'
---
Happy release day! We are excited to announce Snowpack v2.7 with a handful of new features improving stability and the overall developer experience:
- **Redesigned plugin API** plus [new guides for plugin authors](/plugins)
- **Import aliasing** and new ways to customize Snowpack
- **Improved build performance** with smaller, faster builds
- **New Svelte + TypeScript** app templates
- **Bug fixes, usability improvements & more!**
<br/>
Plus, we hit some VERY exciting project milestones last month:
- ❤️ **150** [open source contributors](https://github.com/snowpackjs/snowpack/graphs/contributors) (and growing!)
- 🏆 **1000+** discussions, issues, and pull requests
- ⭐️ **10,000+** stars on GitHub
- 👋 **New companies using Snowpack:** [Alibaba](https://www.1688.com/) & [Airhacks](https://airhacks.com/)
<br/>
If you've been waiting for an excuse to give Snowpack a try, now is a great time to start! Try out a Create Snowpack App (CSA) template or install Snowpack into any existing project:
```bash
# install with npm
npm install --save-dev snowpack
# install with yarn
yarn add --dev snowpack
```
## Redesigned Plugin API
Snowpack v2.7 features an major rewrite of our internal build pipeline to support a more reliable and expressive plugin API. New optimizations and file type builders are unlocked with the redesigned `load()`, `transform()`, `run()` and `optimize()` plugin hooks (with more on the way in future versions).
![snowpack screenshot](/img/snowpack-27-screenshot-1.png)
Snowpack 2.7 is fully backwards compatible with older plugins, so you can upgrade Snowpack without worrying about version mismatches.
Every hook is documented in our new [Plugins Guide](/plugins) for plugin authors. The new API is heavily inspired by [Rollup](https://rollupjs.org/), so we hope it already feels familiar to many of you.
## Simplified Configuration
![snowpack screenshot](/img/snowpack-27-screenshot-3.png)
Snowpack v2.0 originally introduced the concept of build `"scripts"` as a way to configure anything from file building to HTTP request proxying. Scripts were flexible, but hard to document and frustrating to debug.
Our internal plugin rewrite presented an opportunity to improve the developer experience while keeping the flexibility of direct CLI tooling. You can now connect third-party tooling directly into Snowpack's build pipeline using one of two new utility plugins:
- `@snowpack/plugin-build-script`: Use any CLI directly to build files for Snowpack.
- `@snowpack/plugin-run-script`: Run arbitrary CLI commands during dev/build.
Other options like `mount`, `proxy`, and `alias` (see below) are now easier to customize as well with top-level config options that take the guesswork out of common configuration.
The `"scripts"` configuration format will continue to be supported in Snowpack v2, but we recommend migrating any custom scripts to `"plugins"` and plan to remove support in a future major release.
## New: Import Aliasing
![snowpack screenshot](/img/snowpack-27-screenshot-2.png)
In previous versions of Snowpack, import aliasing was hard to understand and configure (and it didnt support all types of aliasing). Starting in Snowpack v2.7, [Import Aliases](/reference/configuration) gets a new top-level `alias` config so that you can define as many custom aliases as you'd like. Package import aliases are also supported.
## Improved Build Performance
Snowpack's official webpack plugin is now more powerful than ever, with new support for multi-page website bundling and better default performance settings (based on the [latest research from Google](https://web.dev/granular-chunking-nextjs/)). Special shout out to [@mxmul](https://github.com/mxmul) (Yelp) for leading these community contributions!
If you don't use a bundler in production, you'll still see a smaller build. That's because Snowpack v2.7 now ships with minification on by default. We plan to keep improving the default unbundled build performance story over the next few releases, so stay tuned.
## Svelte + TypeScript Support
![snowpack screenshot](/img/svelte-ts.png)
Last week, [Svelte announced official support for TypeScript](https://svelte.dev/blog/svelte-and-typescript). We're huge fans of both projects and couldn't pass up the chance to test the new support out in a brand new Svelte + TypeScript app template for Snowpack.
Visit [Create Snowpack App](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app) for a list of all of our new app templates.
## Thank You, Contributors!
Finally, Snowpack wouldn't be possible without the [150+ contributors](https://github.com/snowpackjs/snowpack/graphs/contributors) who contributed features, fixes, and documentation improvements. Thanks again for all of your help.
-- Snowpack Maintainers
<div class="notification">
Psst... In case you missed it, <a href="https://www.skypack.dev/">check out our latest project: Skypack</a> - the new JavaScript CDN that lets you load any npm package directly in the browser.
</div>
<a href="https://twitter.com/pikapkg" target="_blank">
<svg aria-hidden="true" width="32" focusable="false" data-prefix="fab" data-icon="twitter" class="svg-inline--fa fa-twitter fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg>
<a href="https://twitter.com/pikapkg">Follow @pikapkg on Twitter and don't miss future updates!</a>
</a>

View file

@ -0,0 +1,110 @@
---
layout: layouts/post.hmx
title: 'Snowpack v3.0 Release Candidate'
tagline: New features to change the way you build for the web.
description: 'New features to change the way you build for the web. Snowpack v3.0 will release on January 6th, 2021 (the one-year anniversary of its original launch post). This is our biggest release yet with some serious new features, including a new way to load npm packages on-demand that lets you skip the `npm install` step entirely.'
date: 2020-12-03
---
**tl;dr:** Snowpack v3.0 will release on January 6th, 2021 (the one-year anniversary of its original launch post). This is our biggest release yet with some serious new features, including **a new way to load npm imports on-demand** and skip the frontend `npm install` step entirely.
**Update:** Release was delayed for a week for some finishing touches. New release date is January 13th! [More info on Discord](https://discord.com/channels/712696926406967308/783454799051489301/796785330932940800).
Best of all: it's all available to try today!
## What's New?
Snowpack v3 will focus on the polish & official release of four features already available today in the current version of Snowpack (v2.18.0) under the `experiments` flag:
- `experiments.source` - Streaming npm imports, no install step required.
- `experiments.optimize` - Built-in bundling, preloading, and asset minifying.
- `experiments.routes` - Advanced config for HTML fallbacks and API proxies.
- `import 'snowpack'` - A brand new JavaScript API for Snowpack integrations.
<video preload="auto" autoplay loop muted playsinline>
<source src="/img/snowpackskypack.webm" type="video/webm">
<source src="/img/snowpackskypack.mp4" type="video/mp4">
</video>
## New: Streaming Package Imports
Snowpack has always pushed the limits of frontend development, and this release is no different. Snowpack v3.0 introduces an exciting new feature to speed up & simplify your development workflow.
Typically, JavaScript dependencies are installed and managed locally by a package manager CLI like `npm`, `yarn` or `pnpm`. Packages are often bloated with unrelated files and almost never run directly in the browser. Additional steps are required to process, build and bundle these installed packages so that they can actually run in browser.
**What if we could simplify this? What if Snowpack could skip the "npm install" step entirely and just fetch the relevant, pre-built package code on-demand via ESM?**
```js
// you do this:
import * as React from 'react';
// but get behavior like this:
import * as React from 'https://cdn.skypack.dev/react@17.0.1';
```
That URL in the example above points to [Skypack](https://www.skypack.dev/), a popular JavaScript CDN that we built to serve every npm package as ESM. Importing dependencies by URL like this is well supported in Snowpack, Deno, and all major browsers. But writing these URLs directly into your source code isn't ideal and makes development impossible without a network connection.
**Snowpack v3.0 brings together the best of both worlds:** Get the simplicity of `import 'react'` in your own source code and let Snowpack fetch these dependencies behind the scenes, pre-built and ready to run in the browser. Snowpack caches everything for you automatically, so you can continue to work offline without relying on Skypack besides the first package fetch.
This has several benefits over the traditional "npm install" approach:
- **Speed:** Skip the install + build steps for dependencies, and load your dependencies as pre-build ESM code.
- **Safety:** ESM packages are pre-built into JavaScript for you and never given access to [run code on your machine](https://www.usenix.org/system/files/sec19-zimmermann.pdf). Third-party code only ever run in the browser sandbox.
- **Simplicity:** ESM packages are managed by Snowpack, so frontend projects that don't need Node.js (Rails, PHP, etc.) can drop the npm CLI entirely if they choose.
- **Same Final Build:** When you build your site for production, package code is transpiled with the rest of your site and tree-shaken to your exact imports, resulting in a final build that's nearly identical.
If this all sounds too wild for you, don't worry. This is **100% opt-in** behavior for those who want it. By default, Snowpack will continue to pull your npm package dependencies out of your project `node_modules` directory like it always has.
Check out our guide on [Streaming Package Imports](/guides/streaming-imports) to learn more about how to enable this new behavior in your project today. In a future release, we hope to open this up to custom ESM package sources and other CDNs as well.
![js api](/img/post-snowpackv3-esbuild.png)
## Built-in Optimizations, Powered by esbuild
[esbuild](https://esbuild.github.io/) is a marvel: it performs 100× faster than most other popular bundlers and over 300× faster than Parcel (by esbuild's own benchmarks). esbuild is written in Go, a compiled language that can parallelize heavy bundling workloads where other popular bundlers -- written in JavaScript -- cannot.
Snowpack already uses esbuild internally as our default single-file builder for JavaScript, TypeScript and JSX files. Snowpack v3.0 takes this integration one step further, with a new built-in build optimization pipeline. Bundle, minify, and transpile your site for production in 1/100th of the time of other bundlers.
Snowpack is able to adopt esbuild today thanks to an early bet that we made on the future of bundling: **bundling is a post-build optimization, and not the core foundation that everything is built on top of.** Thanks to this early design decision, esbuild can be plugged in and swapped out of your Snowpack build as easily as any other bundler.
esbuild is still a young project, but it's future looks promising. In the meantime, we will also continue to invest in the existing Webpack & Rollup bundler plugins for a long time to come.
To get started, check out the `experiments.optimize` option in our newest [Optimizing Your Snowpack Build](/guides/optimize-and-bundle) guide.
![js api](/img/post-snowpackv3-routes.png)
## Routing
Snowpack's new `experiments.routes` configuration lets you define routes that align your dev environment with production. This unlocks some interesting new use-cases, including:
- **API Proxies** - Route all `/api/*` URLs to another URL or localhost port.
- **SPA Fallbacks** - Serve an app shell `index.html` to all requested routes.
- **Faster Site Loads** - Speed up your site and serve different HTML shell files for each route.
- **Island Architecture** - Serve HTML that renders individual components on the page, in parallel. (Made popular by [Jason Miller](https://twitter.com/_developit) in [this blog post](https://jasonformat.com/islands-architecture/)).
- **Mimic Vercel/Netlify** - Re-create your Vercel or Netlify routes in development. Or, create a Snowpack plugin to automatically generate these routes from your `vercel.json` or `_redirects` file at startup.
While API proxying and SPA fallbacks have already been supported in Snowpack for a while now, this brings them all together into a single, expressive new API.
![js api](/img/post-snowpackv3-jsapi.png)
## A New JavaScript API
Snowpack's new JavaScript API grants you more advanced control over Snowpack's dev server and build pipeline, helping you build more powerful integrations on top of Snowpack to unlock new kinds of dev tooling and server-side rendering (SSR) solutions.
The Svelte team recently made news with [SvelteKit](https://svelte.dev/blog/whats-the-deal-with-sveltekit): An official, zero-effort SSR app framework for Svelte apps. SvelteKit is powered internally by Snowpack, using our brand-new JavaScript API to manage your build pipeline and build files on-demand. Snowpack speeds up development and helps to cut SvelteKit's startup time to near-zero.
Check out our new [JavaScript API reference](/reference/javascript-interface) to start building your own custom integrations on top of Snowpack. Or, read through our new guide on [Server-Side Rendering](/guides/server-side-render) to get started with a custom SSR integration for production.
## Installation
You can install the Snowpack v3.0 release candidate today by running:
```
npm install snowpack@next
```
Since all v3.0 features already exist in Snowpack today, our existing documentation site applies to both v2 & v3. At this point only very old, undocumented, legacy behavior has been removed from the `next` v3.0 branch.
Features under the `experiments` flag may continue to change as we get closer to the official release date. By the end of the year, you can expect that these features will move out from behind the `experiments` flag and into top-level config objects in the `next` v3.0 branch.
Learn more at [snowpack.dev](https://www.snowpack.dev). Happy hacking!

View file

@ -0,0 +1,120 @@
---
layout: layouts/post.hmx
title: 'Snowpack v3.0'
description: Snowpack v3.0 is here! Our biggest release yet with some serious new features, including pre-bundled streaming imports, built-in bundling & optimizations, new JavaScript APIs, and more.'
date: 2021-01-13
---
Snowpack v3.0 is here! This is our biggest release yet with brand new features including:
- **Pre-bundled streaming imports** - Import any npm package, on-demand.
- **Integrated build optimizations** - Built-in bundling, preloading, minification, and more.
- **JavaScript API** - Integrate with Snowpack's brand new native JS API.
- **Node.js Runtime API** - Import your Snowpack-built files directly into Node.js.
- **Bug fixes, stability improvements, and a whole lot more!**
Install the newest version of Snowpack to get started:
```
$ npm install snowpack@^3.0.0
```
Or, try out one of our updated [Create Snowpack App](https://www.npmjs.com/package/create-snowpack-app) starter templates:
```
$ npx create-snowpack-app new-project-directory --template @snowpack/app-template-react
```
## Reimagining Web Development for ESM
1 year ago, Snowpack first released with the mission to reimagine web development for modern JavaScript and ESM. Snowpack leverages modern web features to deliver a frontend build tool that needs just 50ms to start up & react to new file changes, regardless of project size. In comparison, traditional web bundlers could take several seconds or even full minutes to start up in large projects.
Snowpack v3.0 marks another huge leap on our mission to push web development forward with the release of **streaming imports**. Streaming imports make it possible to import any package directly into your project, pre-built and pre-bundled for immediate use. It's the power of the entire JavaScript ecosystem, at your fingertips.
<video preload="auto" autoplay loop muted playsinline>
<source src="/img/streaming-imports-demo.webm" type="video/webm">
<source src="/img/streaming-imports-demo.mp4" type="video/mp4">
</video>
## What are Streaming Imports?
The typical web developer installs and manages their JavaScript dependencies locally using a package manager CLI like `npm`, `yarn` or `pnpm`. These npm packages can't run directly in the browser, so additional work is needed to resolve, process, build and bundle these packages for the browser before you can actually use them.
**What if we could simplify this? What if you could skip the "npm install" step entirely and just fetch the relevant, pre-built package code on-demand via ESM import?**
```js
// you do this:
import * as React from 'react';
// but get behavior like this:
import * as React from 'https://cdn.skypack.dev/react@17.0.1';
```
That URL in the example above points to [Skypack](https://www.skypack.dev/), a popular JavaScript CDN that we built to serve every package on npm as ESM. Importing dependencies by URL like this is well supported in Snowpack, Deno, and all major browsers. But writing these URLs directly into your source code isn't ideal and makes development impossible without a network connection.
**Snowpack v3.0 brings together the best of both worlds:** Get the simplicity of `import 'react'` in your own source code and let Snowpack fetch these dependencies behind the scenes, pre-built and ready to run in the browser. Snowpack caches everything for you automatically, so you can continue to work offline after the first package fetch.
This new workflow has several benefits over the traditional "npm install" approach:
- **Speed:** Skip the install + build steps for dependencies, and load your dependencies on-demand as pre-build, pre-bundled ESM code.
- **Safety:** ESM packages are pre-built into JavaScript for you and never given access to [run code on your machine](https://www.usenix.org/system/files/sec19-zimmermann.pdf). Third-party code only ever runs sandboxed in the browser.
- **Less Tooling:** ESM packages are managed by Snowpack, so frontend projects that don't need Node.js (Rails, PHP, etc.) can drop the npm CLI entirely if they choose.
- **Identical Final Build:** When you build your site for production, package code is transpiled with the rest of your site and tree-shaken to your exact set of imports.
This is our bet on the future of web development. But if this all sounds too wild for you or you have some technical reason to keep managing your dependencies with npm, don't worry. This is **100% opt-in** behavior for those who want it. By default, Snowpack will continue to pull your npm package dependencies out of your project `node_modules` directory like it always has.
Check out our guide on [Streaming Package Imports](/guides/streaming-imports) to learn more about how to enable this new behavior in your project today.
![js api](/img/post-snowpackv3-esbuild.png)
## Built-in Optimizations, Powered by esbuild
[esbuild](https://esbuild.github.io/) is a marvel: it performs 100x faster than most other popular bundlers their own benchmarks. esbuild is written in Go, a compiled language that can parallelize heavy bundling workloads where other popular bundlers -- written in JavaScript -- cannot.
Snowpack already uses esbuild internally as our default single-file builder for JavaScript, TypeScript and JSX files. Snowpack v3.0 takes this integration one step further, with a new built-in build optimization pipeline. Bundle, minify, and transpile your site for production in 1/100th of the time of other bundlers.
Snowpack is able to adopt esbuild today thanks to an early bet that we made on the future of bundling: **bundling is just a post-build optimization.** Thanks to this early design decision, esbuild can be plugged in and swapped out of your Snowpack build as easily as any other bundler.
esbuild is still a young project, but its future looks promising. In the meantime, we will also continue to invest in the existing bundler plugins for a long time to come, so that more mature projects can continue to use mature bundlers like Webpack & Rollup.
To get started, check out the `optimize` option in our newest [Optimizing Your Snowpack Build](/guides/optimize-and-bundle) guide.
![js api](/img/post-snowpackv3-jsapi.png)
## A New JavaScript API
Snowpack's new JavaScript API grants you more advanced control over Snowpack's dev server and build pipeline, helping you build more powerful integrations on top of Snowpack to unlock new kinds of dev tooling and server-side rendering (SSR) solutions.
[SvelteKit](https://svelte.dev/blog/whats-the-deal-with-sveltekit) is the new official web app framework from the Svelte team, built with Snowpack. SvelteKit uses our new JavaScript API to manage the build pipeline and build files on-demand. Snowpack helps SvelteKit speed up development, with zero rapid updates on file change and zero upfront server start-up cost.
[Microsite](https://www.npmjs.com/package/microsite) is another exciting new project built with Snowpack. Microsite is a Static Site Generator (SSG) for Preact that features automatic partial hydration, so that you send as little JavaScript down to the client as possible.
Check out our new [JavaScript API reference](/reference/javascript-interface) to start building your own custom integrations on top of Snowpack.
![js api](/img/post-snowpackv3-runtime.png)
## A New Node.js Runtime
Speaking of Svelte, this next feature comes directly out of our collaboration with the Svelte team. As a part of building out SvelteKit, Rich Harris created a server-side runtime for Snowpack. This runtime lets you import any Snowpack-built file directly into Node.js, handling things like ESM->CJS conversion and CSS extraction automatically.
The result is a unified build pipeline across both Node.js and the frontend, with all of the on-demand build performance benefits of Snowpack. Importing frontend code to run in Node.js unlocks features like true server-side rendering (SSR), test runner integrations for Jest/uvu/Mocha, and more.
Check out our new [SSR guide](/guides/server-side-render) to get started and learn more about all of the different ways that you can connect to your Snowpack build.
<div style="text-align:center; font-size: 120px; margin-top: 5rem; margin-bottom: -2rem; line-height: 1;">🥳</div>
## Snowpack's One Year Anniversary
Last week marked Snowpack's one-year anniversary of the original v1.0.0 release. Looking back, I'm blown away by everything that's happened since:
- 150+ releases (from `v0.0.1`, all the way to v3.0 today)
- [100+ Snowpack plugins](https://www.snowpack.dev/plugins) to choose from (and growing fast!)
- [100+ individual contributors](https://github.com/snowpackjs/snowpack/graphs/contributors)
- [15,000+ stars on GitHub](https://github.com/snowpackjs/snowpack/stargazers)
- #1 Developer Productivity Boost Winner, [2020 JS Open Source Awards](https://osawards.com/javascript/2020)
- #1 Highest Developer Interest, [2020 State of JS](https://2020.stateofjs.com/en-US/technologies/build-tools/)
- #1 Highest Developer Satisfaction (tied), 2020 State of JS
A huge thank you to everyone who has contributed code to Snowpack, and the hundreds of developers joining us on GitHub and on [Discord](https://discord.com/invite/snowpack). This project wouldn't exist today without you and your support. Thank you!
-- Fred K. Schott [(@FredKSchott)](https://twitter.com/FredKSchott)

View file

@ -0,0 +1,35 @@
<script hmx="setup">
import Subnav from '../components/Subnav.hmx';
import { content as Menu } from '../components/Menu.hmx';
// import contentful from 'skypack:contentful';
export default async function ({ params }) {
const entry = await contentful.getEntry(params.slug);
return { title: entry.fields.title, description: entry.fields.description, layout: 'layouts/base.hmx', props: { entry } };
}
</script>
<div class="container">
<section class="snow-view__docs has-subnav">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<Subnav title={title} />
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{title}
</h2>
<div class="content-layout">
<div class="content-body">
<ContentfulRichText document={entry.fields.body} />
</div>
</div>
</div>
</article>
</section>
</div>

View file

@ -0,0 +1,41 @@
---
layout: layouts/content.hmx
title: Command Line API
description: The Snowpack Command Line tool's API, commands, and flags.
---
### Commands
```
$ snowpack --help
snowpack init Create a new project config file.
snowpack dev Develop your app locally.
snowpack build Build your app for production.
...
```
### Flags
```bash
# Show helpful info
$ snowpack --help
# Show additional debugging logs
$ snowpack --verbose
# {devOptions: {open: 'none'}}
$ snowpack dev --open none
# {buildOptions: {clean: true/false}}
$ snowpack build --clean
$ snowpack build --no-clean
```
**CLI flags will be merged with (and take priority over) your config file values.** Every config value outlined below can also be passed as a CLI flag. Additionally, Snowpack also supports the following flags:
- **`--config [path]`** Set the path to your project config file.
- **`--help`** Show this help.
- **`--version`** Show the current version.
- **`--reload`** Clear the local cache. Useful for troubleshooting installer issues.

View file

@ -0,0 +1,72 @@
---
layout: layouts/content.hmx
title: Common Error Details
description: How to troubleshoot common issues and error messagesm, plus our resources for getting help.
---
This page details several common issues and error messages. For further help we have an active [GitHub Discussion forum](https://github.com/snowpackjs/snowpack/discussions)and [Discord](https://discord.gg/snowpack). Developers and community contributors frequently answer questions on both.
### No such file or directory
```
ENOENT: no such file or directory, open …/node_modules/csstype/index.js
```
This error message would sometimes occur in older versions of Snowpack.
**To solve this issue:** Upgrade to Snowpack `v2.6.0` or higher. If you continue to see this unexpected error in newer versions of Snowpack, please file an issue.
### Package exists but package.json "exports" does not include entry
Node.js recently added support for a package.json "exports" entry that defines which files you can and cannot import from within a package. Preact, for example, defines an "exports" map that allows you to to import "preact/hooks" but not "preact/some/custom/file-path.js". This allows packages to control their "public" interface.
If you see this error message, that means that you've imported a file path not allowed in the export map. If you believe this to be an error, reach out to the package author to request the file be added to their export map.
### Uncaught SyntaxError: The requested module '/\_snowpack/pkg/XXXXXX.js' does not provide an export named 'YYYYYY'
If you are using TypeScript, this error could occur if you are importing something that only exists in TypeScript (like a type or interface) and doesn't actually exist in the final JavaScript code. This issue is rare since our built-in TypeScript support will automatically extract and remove only type-only imports.
**To solve:** Make sure to use `import type { MyInterfaceName }` instead.
This error could also appear if named imports are used with older, Common.js npm packages. Thanks to improvements in our package scanner this is no longer a common issue for most packages. However, some packages are written or compiled in a way that makes automatic import scanning impossible.
**To solve:** Use the default import (`import pkg from 'my-old-package'`) for legacy Common.js/UMD packages that cannot be analyzed. Or, add the package name to your `packageOptions.namedExports` configuration for runtime import scanning.
```js
// snowpack.config.js
{
"packageOptions": {
"namedExports": ["@shopify/polaris-tokens"]
}
}
```
### Installing Non-JS Packages
When installing packages from npm, you may encounter some file formats that can run only with additional parsing/processing. First check to see if there is a [Snowpack plugin for the type of file](/plugins).
Because our internal installer is powered by Rollup, you can also add Rollup plugins to your [Snowpack config](/reference/configuration) to handle these special, rare files:
```js
/* snowpack.config.js */
module.exports = {
rollup: {
plugins: [require('rollup-plugin-sass')()],
},
};
```
Refer to [Rollups documentation on plugins](https://rollupjs.org/guide/en/#using-plugins) for more information.
### RangeError: Invalid WebSocket frame: RSV1 must be clear
**To solve this issue:** Use any other port than `8080` for the dev server. To do so, specify a port in your [Snowpack config](/reference/configuration):
```js
/* snowpack.config.js */
module.exports = {
devOptions: {
port: 3000,
},
};
```

View file

@ -0,0 +1,475 @@
---
layout: layouts/content.hmx
title: snowpack.config.js
description: The Snowpack configuration API reference.
---
```js
// Example: snowpack.config.js
// The added "@type" comment will enable TypeScript type information via VSCode, etc.
/** @type {import("snowpack").SnowpackUserConfig } */
module.exports = {
plugins: [
/* ... */
],
};
```
To generate a basic configuration file scaffold in your Snowpack project run `snowpack init`.
## root
**Type**: `string`
**Default**: `/`
Specify the root of a project using Snowpack. (Previously: `config.cwd`)
## workspaceRoot
**Type**: `string`
Specify the root of your workspace or monorepo, if you are using one. When configured, Snowpack will treat any sibling packages in your workspace like source files, and pass them through your unbundled Snowpack build pipeline during development. This allows for fast refresh, HMR support, file change watching, and other dev improvements when working in monorepos.
When you build your site for production, symlinked packages will be treated like any other package, bundled and tree-shaken into single files for faster loading.
## install
Deprecated! Moved to `packageOptions.knownEntrypoints`
## extends
**Type**: `string`
Inherit from a separate "base" config.
Can be a relative file path, an npm package, or a file within an npm package. Your configuration will be merged on top of the extended base config.
## exclude
**Type**: `string[]`
**Default**: `['**/node_modules/**/*']`
Exclude any files from the Snowpack pipeline.
Supports glob pattern matching.
## mount
```
mount: {
[path: string]: string | {url: string, resolve: boolean, static: boolean}
}
```
Mount local directories to custom URLs in your built application.
- `mount.url` | `string` | _required_ : The URL to mount to, matching the string in the simple form above.
- `mount.static` | `boolean` | _optional_ | **Default**: `false` : If true, don't build files in this directory. Copy and serve them directly from disk to the browser.
- `mount.resolve` | `boolean` | _optional_ | **Default**: `true`: If false, don't resolve JS & CSS imports in your JS, CSS, and HTML files. Instead send every import to the browser, as written.
-
Example:
```js
// snowpack.config.js
// Example: Basic "mount" usage
{
"mount": {
"src": "/dist",
"public": "/"
}
}
```
You can further customize this the build behavior for any mounted directory by using the expanded object notation:
<!-- snowpack/src/config.ts -->
```js
// snowpack.config.js
// Example: expanded object notation "mount" usage
{
"mount": {
// Same behavior as the "src" example above:
"src": {url: "/dist"},
// Mount "public" to the root URL path ("/*") and serve files with zero transformations:
"public": {url: "/", static: true, resolve: false}
}
}
```
## alias
**Type**: `object` (package: package or path)
Configure import aliases for directories and packages.
Note: In an older version of Snowpack, all mounted directories were also available as aliases by **Default**. As of Snowpack 2.7, this is no longer the case and no aliases are defined by **Default**.
```js
// snowpack.config.js
// Example: alias types
{
alias: {
// Type 1: Package Import Alias
"lodash": "lodash-es",
"react": "preact/compat",
// Type 2: Local Directory Import Alias (relative to cwd)
"components": "./src/components"
"@app": "./src"
}
}
```
## plugins
**Type**: `array` containing pluginName `string` or an array [`pluginName`, {`pluginOptions`}
Enable Snowpack plugins and their options.
Also see our [Plugin guide](/guides/plugins)
```js
// snowpack-config.js
// Example: enable plugins both simple and expanded
{
plugins: [
// Simple format: no options needed
'plugin-1',
// Expanded format: allows you to pass options to the plugin
['plugin-2', { 'plugin-option': false }],
];
}
```
## devOptions
**Type**: `object` (option name: value)
Configure the Snowpack dev server.
### devOptions.secure
**Type**: `boolean`
**Default**: `false`
Toggles whether Snowpack dev server should use HTTPS with HTTP2 enabled.
### devOptions.hostname
**Type**: `string`
**Default**: `localhost`
The hostname that the dev server is running on. Snowpack uses this information to configure the HMR websocket and properly open your browser on startup (see: [`devOptions.open`](#devoptions.open)).
### devOptions.port
**Type**: `number`
**Default**: `8080`
The port the dev server runs on.
### devOptions.fallback
**Type**: `string`
**Default**: `"index.html"`
The HTML file to serve for non-resource routes.
When using the Single-Page Application (SPA) pattern, this is the HTML "shell" file that gets served for every (non-resource) user route.
⚠️ Make sure that you configure your production servers to serve this.
### devOptions.open
**Type**: `string`
**Default**: `"**Default**"`
Configures how the dev server opens in the browser when it starts.
Any installed browser, e.g., "chrome", "firefox", "brave". Set "none" to disable.
### devOptions.output
**Type**: `"stream" | "dashboard"`
**Default**: `"dashboard"`
Set the output mode of the `dev` console:
- `"dashboard"` delivers an organized layout of console output and the logs of any connected tools. This is recommended for most users and results in the best logging experience.
- `"stream"` is useful when Snowpack is run in parallel with other commands, where clearing the shell would clear important output of other commands running in the same shell.
### devOptions.hmr
**Type**: `boolean`
**Default**: `true`
Toggles HMR on the Snowpack dev server.
### devOptions.hmrDelay
**Type**: `number` (milliseconds)
**Default**: `0`
Milliseconds to delay HMR-triggered browser update.
### devOptions.hmrPort
**Type**: `number`
**Default**: [`devOptions.port`](#devoptions.port)
The port where Snowpack's HMR Websocket runs.
### devOptions.hmrErrorOverlay
**Type**: `boolean`
**Default**: `true`
Toggles a browser overlay that displays JavaScript runtime errors when running HMR.
### devOptions.out
**Type**: `string`
**Default**: `"build"`
_NOTE:_ Deprecated, see `buildOptions.out`.
## installOptions
**Type**: `object`
_NOTE:_ Deprecated, see `packageOptions`.
## packageOptions
**Type**: `object`
Configure how npm packages are installed and used.
### packageOptions.external
**Type**: `string[]`
**Example**: `"external": ["fs"]`
Mark some imports as external. Snowpack will ignore these imports and leave them as-is in your final build.
This is an advanced feature: Bare imports are not supported in any major browser, so an ignored import will usually fail when sent directly to the browser. This will most likely fail unless you have a specific use-case that requires it.
### packageOptions.source
**Type**: `"local" | "remote"`
**Default**: `"local"`
**Example**: `"source": "local"`
Your JavaScript npm packages can be consumed in two different ways: **local** and **remote**. Each mode supports a different set of package options. You can choose between these two different modes by setting the `packageOptions.source` property.
### packageOptions.source=local
Load your dependencies from your local `node_modules/` directory. Install and manage your dependencies using `npm` (or any other npm-ready package manager) and a project `package.json` file.
This is traditional Snowpack behavior matching Snowpack v2. This mode is recommended for anyone already using npm to manage their frontend dependencies.
#### packageOptions.knownEntrypoints
**Type**: `string[]`
Known dependencies to install with Snowpack. Used for installing packages any dependencies that cannot be detected by our automatic import scanner (ex: package CSS files).
#### packageOptions.polyfillNode
**Type**: `boolean`
**Default**: `false`
This will automatically polyfill any Node.js dependencies as much as possible for the browser
Converts packages that depend on Node.js built-in modules (`"fs"`, `"path"`, `"url"`, etc.). You can see the full list of supported polyfills at the [rollup-plugin-node-polyfills documentation](https://github.com/ionic-team/rollup-plugin-node-polyfills)
If you'd like to customize this polyfill behavior, you can provide your own Rollup plugin for the installer:
```js
// Example: If `--polyfill-node` doesn't support your use-case, you can provide your own custom Node.js polyfill behavior
module.exports = {
packageOptions: {
polyfillNode: false,
rollup: {
plugins: [require('rollup-plugin-node-polyfills')({crypto: true, ...})],
},
},
};
```
When `source="remote"`, Node.js polyfills are always provided. Configuring this option is only supported in `source="local"` mode.
#### packageOptions.env
**Type**: `{[ENV_NAME: string]: (string true)}`
Sets a `process.env.` environment variable inside the installed dependencies.
If set to true (ex: `{NODE_ENV: true}` or `--env NODE_ENV`) this will inherit from your current shell environment variable. Otherwise, set to a string (ex: `{NODE_ENV: 'production'}` or `--env NODE_ENV=production`) to set the exact value manually.
This option is only supported in `source="local"` mode. `source="remote"` does not support this feature yet.
#### packageOptions.packageLookupFields
**Type**: `string[]`
**Example**: `"packageLookupFields": ["svelte"]`
Set custom lookup fields for dependency `package.json` file entrypoints, in addition to the defaults like "module", "main", etc.
This option is only supported in `source="local"` mode. `source="remote"` does not support this feature yet.
#### packageOptions.packageExportLookupFields
**Type**: `string[]`
**Example**: `"packageExportLookupFields": ["svelte"]`
Set custom lookup fields for dependency `package.json` ["exports" mappings.](https://nodejs.org/api/packages.html#packages_package_entry_points)
This option is only supported in `source="local"` mode. `source="remote"` does not support this feature yet.
#### packageOptions.rollup
**Type**: `Object`
Allows customization of Snowpack's internal Rollup configuration.
Snowpack uses Rollup internally to install your packages. This `rollup` config option gives you deeper control over the internal Rollup configuration that we use.
- packageOptions.rollup.plugins | `RollupPlugin[]` - Provide an array of custom Rollup plugins that will run on every installed package. Useful for dealing with non-standard file types in your npm packages.
- packageOptions.rollup.dedupe | `string[]` - If needed, deduplicate multiple versions/copies of a packages to a single one. This helps prevent issues with some packages when multiple versions are installed from your node_modules tree. See [rollup-plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve#usage) for more documentation.
- packageOptions.rollup.context | `string` - Specify top-level `this` value. Useful to silence install errors caused by legacy common.js packages that reference a top-level this variable, which does not exist in a pure ESM environment. Note that the `'THIS_IS_UNDEFINED'` warning ("'this' keyword is equivalent to 'undefined' ... and has been rewritten") is silenced by default, unless `--verbose` is used.
This option is only supported in `source="local"` mode. `source="remote"` does not support custom Rollup install options.
### packageOptions.source=remote
Enable streaming package imports. Load dependencies from our remote CDN. Manage your dependencies using `snowpack` and a project `snowpack.deps.json` file.
[Learn more about Streaming Remote Imports](/guides/streaming-imports).
#### packageOptions.origin
**Type**: `string`
**Default**: `https://pkg.snowpack.dev`
The remote origin to import packages from. When you import a new package, Snowpack will fetch those resources from this URL.
Currently, the origin must implement a specific response format that Snowpack can parse for ESM. In future versions of Snowpack we plan to add support for custom CDNs and import origins.
#### packageOptions.cache
**Type**: `string`
**Default**: `.snowpack`
The location of your project cache folder, relative to the project root. Snowpack will save cached data to this folder. For example, if `packageOptions.types` is set to true, Snowpack will save TypeScript types to a `types` directory within this folder.
#### packageOptions.types
**Type**: `boolean`
**Default**: `false`
If true, Snowpack will download TypeScript types for every package.
## buildOptions
**Type**: `object` (option name: value)
Configure your final build.
### buildOptions.out
**Type**: `string`
**Default**: `"build"`
The local directory that we output your final build to.
### buildOptions.baseUrl
**Type**: `string`
**Default**: `/`
In your HTML, replace all instances of `%PUBLIC_URL%` with this
Inspired by the same [Create React App](https://create-react-app.dev/docs/using-the-public-folder/) concept. This is useful if your app will be deployed to a subdirectory.
### buildOptions.clean
**Type**: `boolean`
**Default**: `true`
Set to `false` to prevent Snowpack from deleting the build output folder (`buildOptions.out`) between builds.
### buildOptions.webModulesUrl
_NOTE:_ Deprecated, see `buildOptions.metaUrlPath`.
### buildOptions.metaDir
_NOTE:_ Deprecated, see `buildOptions.metaUrlPath`.
### buildOptions.metaUrlPath
**Type**: `string`
**Default**: `_snowpack`
Rename the default directory for Snowpack metadata. In every build, Snowpack creates meta files for loading things like [HMR](/concepts/hot-module-replacement), [Environment Variables](/reference/environment-variables), and your built npm packages.
When you build your project, this will be a path on disk relative to the `buildOptions.out` directory.
### buildOptions.sourcemap
**Type**: `boolean`
**Default**: `false`
Generates source maps.
**_Experimental:_** Still in progress, you may encounter some issues when using source maps until this support is finalized.
### buildOptions.watch
**Type**: `boolean`
**Default**: `false`
Run Snowpack's build pipeline through a file watcher. This option works best for local development when you have a custom frontend server (ex: Rails, PHP, etc.) and the Snowpack dev server cannot be used.
### buildOptions.htmlFragments
**Type**: `boolean`
**Default**: `false`
Toggles whether HTML fragments are transformed like full HTML pages.
HTML fragments are HTML files not starting with "<!doctype html>".
### buildOptions.jsxFactory
**Type**: `string`
**Default**: `React.createElement` (or `h` if Preact import is detected)
Set the name of the function used to create JSX elements.
### buildOptions.jsxFragment
**Type**: `string`
**Default**: `React.Fragment` (or `Fragment` if Preact import is detected)
Set the name of the function used to create JSX fragments.
## testOptions
Configure your tests.
### testOptions.files
**Type**: `string[]`
**Default**: `["__tests__/**/*", "**/*.@(spec|test).*"]`
Specifies your test files. If `NODE_ENV` is set to "test", Snowpack includes these files in your site build and scan them for installable dependencies. Otherwise, Snowpack excludes these files.
## experiments
**Type**: `object` (option name: value)
This section is currently empty! In the future, this section may be used for experimental and not yet finalized.

View file

@ -0,0 +1,58 @@
---
layout: layouts/content.hmx
title: Environment Variables
description: Using environment variables with Snowpack
---
For your safety, Snowpack supports only environment variables which begin with `SNOWPACK_PUBLIC_*`. We do this because everything in your web application is sent to the browser, and we don't want you to accidentally share sensitive keys/env variables with your public web application. Prefixing your frontend web env variables with `SNOWPACK_PUBLIC_` is a good reminder that they will be shared with the world.
## Setting environment variables
You can set environment variables with snowpack in three different ways:
### Option 1: CLI
Set environment variables when you run the snowpack CLI:
```bash
SNOWPACK_PUBLIC_API_URL=api.google.com snowpack dev
```
### Option 2: Config file
Set environment variables by adding to `process.env.*` at the top of your `snowpack.config.js` file.
```js
// snowpack.config.js
process.env.SNOWPACK_PUBLIC_API_URL = 'api.google.com';
// ...rest of config
```
Note that your application won't _read_ these environment variables from `process.env`, but variables that are set here will be available on `import.meta.env` (see below).
### Option 3: Plugin
Use a plugin such as [plugin-dotenv](https://www.npmjs.com/package/@snowpack/plugin-dotenv) to load environment variables from a `.env` file.
## Reading environment variables
You can read environment variables directly in your web application via `import.meta.env`. If you've ever used `process.env` in Create React App or any Webpack application, this behaves exactly the same.
```js
// `import.meta.env` - Read process.env variables in your web app
fetch(`${import.meta.env.SNOWPACK_PUBLIC_API_URL}/users`).then(...)
// Supports destructuring as well:
const {SNOWPACK_PUBLIC_API_URL} = import.meta.env;
fetch(`${SNOWPACK_PUBLIC_API_URL}/users`).then(...)
// Instead of `import.meta.env.NODE_ENV` use `import.meta.env.MODE`
if (import.meta.env.MODE === 'development') {
// ...
```
`import.meta.env.MODE` and `import.meta.env.NODE_ENV` are also both set to the current `process.env.NODE_ENV` value, so that you can change app behavior based on dev vs. build. The env value is set to `development` during `snowpack dev`, and `production` during `snowpack build`. Use this in your application instead of `process.env.NODE_ENV`.
You can also use environment variables in HTML files. All occurrences of `%SNOWPACK_PUBLIC_*%`, `%PUBLIC_URL%`, and `%MODE%` will be replaced at build time.
**Remember:** that these env variables are statically injected into your application for everyone at **build time**, and not runtime.

View file

@ -0,0 +1,20 @@
---
layout: layouts/content.hmx
title: Hot Module Replacement (HMR) API
description: Snowpack implements HMR via the esm-hmr spec, an attempted standard for ESM-based Hot Module Replacement (HMR).
---
Snowpack implements HMR via the [esm-hmr](https://github.com/pikapkg/esm-hmr) spec, an attempted standard for ESM-based Hot Module Replacement (HMR).
```js
// HMR Code Snippet Example
if (import.meta.hot) {
import.meta.hot.accept(({ module }) => {
// Accept the module, apply it into your application.
});
}
```
Full API Reference: [snowpack/esm-hmr on GitHub](https://github.com/snowpackjs/esm-hmr)
[Learn more](/concepts/hot-module-replacement) about HMR, Fast Refresh, and how it's meant to work in Snowpack.

View file

@ -0,0 +1,198 @@
---
layout: layouts/content.hmx
title: JavaScript API
description: Snowpack's JavaScript API is for anyone who wants to integrate with some custom build pipeline or server-side rendering engine.
---
Most users will interact with Snowpack via the [command-line](/reference/cli-command-line-interface) interface (CLI). However, Snowpack also ships a JavaScript API for anyone to build on top of.
This page contains reference information on Snowpack's public API and all related data types. A full set of all data types defined within the project (public and private) can be found in [the package's `types.d.ts` file](https://unpkg.com/browse/snowpack@3.0.10/lib/types.d.ts).
### createConfiguration()
`createConfiguration(config?: SnowpackUserConfig) => SnowpackConfig`
```js
import {createConfiguration} from 'snowpack';
const config = createConfiguration({...});
```
Almost everything that you do with Snowpack requires a configuration object. Snowpack is designed to work with zero config, and the `config` argument that this function takes can be full, empty, or only contain a couple of properties. The rest of the configuration object will be filled out with Snowpack's usual set of defaults, outlined in our [snowpack.config.js documentation.](/reference/configuration).
The easiest way to think about the difference is that `SnowpackUserConfig` is the externally-documented configuration format, and `SnowpackConfig` is our internal representation with all optional/undefined values populated with the actual defaults.
### loadConfiguration()
`loadConfiguration(overrides?: SnowpackUserConfig, configPath?: string | undefined) => Promise<SnowpackConfig>`
```js
import {loadConfiguration} from 'snowpack';
const config = loadConfiguration({...}, '/path/to/snowpack.config.js');
```
Similar to `createConfiguration`, but this function will actually check the file system to load a configuration file from disk.
All paths within that configuration file are relative to the file itself.
### startServer()
`function startServer({config: SnowpackUserConfig}) => Promise<SnowpackDevServer>`
```js
import {startServer} from 'snowpack';
const config = createConfiguration({...});
const server = await startServer({config}); // returns: SnowpackDevServer
```
Start a new Snowpack dev server instance. This is the equivalent of running `snowpack dev` on the command line.
Once started, you can load files from your dev server and Snowpack will build them as requested. This is an important feature to understand: Snowpack's dev server does zero file building on startup, and instead builds files only once they are requested via the server's `loadUrl` method.
### SnowpackDevServer
#### SnowpackDevServer.port
The port that the server is listening on.
#### SnowpackDevServer.loadUrl()
`loadUrl(reqUrl: string, opt?: {isSSR?: boolean; allowStale?: boolean; encoding?: string}): Promise<LoadResult<Buffer | string>>;`
```ts
const server = await startServer({config});
const {contents} = server.loadUrl('/dist/index.js', {...});
```
Load a file and return the result. On the first request of a URL, this will kick off a build that will then be cached for all future requests during the life of the server.
You can pass `allowStale: true` to enable Snowpack's cold cache for cached results from past sessions. However, Snowpack provides no guarentee on the freshness of the cold-cache data.
#### SnowpackDevServer.getUrlForFile()
`getUrlForFile(fileLoc: string) => string | null;`
```ts
const server = await startServer({config});
const fileUrl = server.getUrlForFile('/path/to/index.jsx');
const {contents} = server.loadUrl(fileUrl, {...});
```
A helper function to find the final hosted URL for any source file. Useful when combined with `loadUrl`, since you may only know a file's location on disk without knowing it's final hosted URL.
#### SnowpackDevServer.sendResponseError()
`sendResponseError(req: http.IncomingMessage, res: http.ServerResponse, status: number) => void;`
A helper function to send an error response in a server response handler. Useful when integrating Snowpack with Express, Koa, or any other Node.js server.
#### SnowpackDevServer.onFileChange()
`onFileChange({filePath: string}) => void;`
Listen for watched file change events. Useful for situations where you might want to watch the file system for changes yourself, and can save overhead/performance by hooking into our already-running watcher.
#### SnowpackDevServer.shutdown()
`shutdown() => Promise<void>;`
```ts
const server = await startServer({ config });
await server.shutdown();
```
Shut down the Snowpack dev server. Cleanup any long-running commands, file watchers, etc.
#### SnowpackDevServer.getServerRuntime()
`getServerRuntime({invalidateOnChange?: boolean}) => ServerRuntime;`
```ts
const server = await startServer({ config });
const runtime = server.getServerRuntime();
const { helloWorld } = (await runtime.importModule('/dist/index.js')).exports;
helloWorld();
```
Returns an ESM Server Runtime that lets Node.js import modules directly out of Snowpack's build cache. Useful for SSR, test running frontend code, and the overall unification of your build pipeline.
For more information, check out our guide on [Server-Side Rendering](/guides/server-side-render) using the `getServerRuntime()` API.
#### ServerRuntime
```ts
interface ServerRuntime {
/** Import a Snowpack-build JavaScript file into Node.js. */
importModule(url: string) => Promise<ServerRuntimeModule>;
/** Invalidate a module in the internal runtime cache. */
invalidateModule(url: string) => void;
}
```
#### ServerRuntimeModule
```ts
interface ServerRuntimeModule {
/** The imported module. */
exports: any;
/** References to all internal CSS imports. Useful for CSS extraction. */
css: string[];
}
```
### build()
`build({config: SnowpackUserConfig}) => Promise<SnowpackBuildResult>`
```js
import {build} from 'snowpack';
const config = createConfiguration({...});
const {result} = await build({config}); // returns: SnowpackBuildResult
```
#### SnowpackBuildResult.result
An in-memory manifest of all build inputs & output files.
#### SnowpackBuildResult.shutdown
In `--watch` mode, the `build()` function will resolve but the build itself will continue. Use this function to shut down the build watcher.
In normal build mode (non-watch mode) this function will throw with a warning.
#### SnowpackBuildResult.onFileChange
In `--watch` mode, the `build()` function will resolve but the build itself will continue. Use this function to respond to file change events without having to spin up your own file watcher.
In normal build mode (non-watch mode) this function will throw with a warning.
### getUrlForFile()
`getUrlForFile(fileLoc: string, config: SnowpackConfig) => string | null`
```js
import { getUrlForFile } from 'snowpack';
const fileUrl = getUrlForFile('/path/to/file.js', config);
```
A helper function to find the final hosted URL for any source file. Useful when combined with `loadUrl`, since you may only know a file's location on disk without knowing it's final hosted URL.
Similar to `SnowpackDevServer.getUrlForFile()`, but requires a second `config` argument to inform the result.
### clearCache()
`clearCache() => Promise<void>`
```js
import { clearCache } from 'snowpack';
await clearCache();
```
Equivalent of using the `--reload` flag with the `snowpack` CLI. Clears all cached data in Snowpack. Useful for troubleshooting, or clearing the cache after making some change that Snowpack couldn't detect.
### logger
```js
import { logger } from 'snowpack';
```
You can control Snowpack's internal logger directly by importing it. Note that this is an advanced feature not needed for most users. Instead, use the `verbose` config option to enable debug logging and control log message verbosity.

View file

@ -0,0 +1,111 @@
---
layout: layouts/content.hmx
title: Plugin API
description: The Snowpack Plugin API and how to use it.
---
Looking to get started writing your own plugin? Check out our [Plugin Guide](/guides/plugins) for an overview of how plugins work and a walk-through to help you create your own.
Looking for a good summary? Check out our ["SnowpackPlugin" TypeScript definition](https://github.com/snowpackjs/snowpack/blob/main/snowpack/src/types.ts#L130) for a fully documented and up-to-date overview of the Plugin API and all supported options.
### Overview
```js
// my-first-snowpack-plugin.js
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'my-first-snowpack-plugin',
config() {
console.log('Success!');
},
};
};
// To use this plugin, add it to your snowpack.config.js:
//
// "plugins": [
// ["./my-first-snowpack-plugin.js", {/* pluginOptions */ }]
// ]
```
A **Snowpack Plugin** is an object interface that lets you customize Snowpack's behavior. Snowpack provides different hooks for your plugin to connect to. For example, you can add a plugin to handle Svelte files, optimize CSS, convert SVGs to React components, run TypeScript during development, and much more.
Snowpack's plugin interface is inspired by [Rollup](https://rollupjs.org/). If you've ever written a Rollup plugin before, then hopefully these concepts and terms feel familiar.
### Lifecycle Hooks
#### config()
```js
config(snowpackConfig) {
// modify or read from the Snowpack configuration object
}
```
Use this hook to read or make changes to the completed Snowpack configuration object. This is currently the recommended way to access the Snowpack configuration, since the one passed to the top-level plugin function is not yet finalized and may be incomplete.
#### load()
Load a file from disk and build it for your application. This is most useful for taking a file type that can't run in the browser (TypeScript, Sass, Vue, Svelte) and returning JS and/or CSS. It can even be used to load JS/CSS files directly from disk with a build step like Babel or PostCSS.
#### transform()
Transform a file's contents. Useful for making changes to all types of build output (JS, CSS, etc.) regardless of how they were originally loaded from disk.
#### run()
Run a CLI command, and connect it's output into the Snowpack console. Useful for connecting tools like TypeScript.
#### optimize()
Snowpacks bundler plugin API is still experimental and may change in a future release. See our official bundler plugins for an example of using the current interface:
- Example: [@snowpack/plugin-webpack](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-webpack)
- Example: [snowpack-plugin-rollup-bundle](https://github.com/ParamagicDev/snowpack-plugin-rollup-bundle)
#### onChange()
Get notified any time a watched file changes. This can be useful when paired with the `markChanged()` plugin method, to mark multiple files changed at once.
See [@snowpack/plugin-sass](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-sass/plugin.js) for an example of how to use this method.
### Plugin Properties
#### knownEntrypoints
```
// Example: Svelte plugin needs to make sure this dependency can be loaded.
knownEntrypoints: ["svelte/internal"]
```
A list of any npm dependencies that are added as a part of `load()` or `transform()` that Snowpack will need to know about. Snowpack analyzes most dependency imports automatically when it scans the source code of a project, but some imports are added as a part of a `load()` or `transform()` step, which means that Snowpack would never see them. If your plugin does this, add them here.
#### resolve
```
// Example: Sass plugin compiles Sass files to CSS.
resolve: {input: [".sass"], output: [".css"]}
// Example: Svelte plugin compiles Svelte files to JS & CSS.
resolve: {input: [".svelte"], output: [".js", ".css"]}
```
If your plugin defines a `load()` method, Snowpack will need to know what files your plugin is responsible to load and what its output will look like. **`resolve` is needed only if you also define a `load()` method.**
- `input`: An array of file extensions that this plugin will load.
- `output`: The set of all file extensions that this plugin's `load()` method will output.
- [Full TypeScript definition](https://github.com/snowpackjs/snowpack/tree/main/snowpack/src/types/snowpack.ts).
### Plugin Methods
#### this.markChanged()
```js
// Called inside any plugin hooks
this.markChanged('/some/file/path.scss');
```
Manually mark a file as changed, regardless of whether the file changed on disk or not. This can be useful when paired with the `markChanged()` plugin hook, to mark multiple files changed at once.
- See [@snowpack/plugin-sass](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-sass/plugin.js) for an example of how to use this method.
- [Full TypeScript definition](https://github.com/snowpackjs/snowpack/blob/main/snowpack/src/types.ts).

View file

@ -0,0 +1,119 @@
---
layout: layouts/content.hmx
title: Supported Files
description: Snowpack ships with built-in support for many file types including json, js, ts, jsx, css, css modules, and images.
---
Snowpack ships with built-in support for the following file types, no configuration required:
- JavaScript (`.js`, `.mjs`)
- TypeScript (`.ts`, `.tsx`)
- JSON (`.json`)
- JSX (`.jsx`, `.tsx`)
- CSS (`.css`)
- CSS Modules (`.module.css`)
- Images & Assets (`.svg`, `.jpg`, `.png`, etc.)
- WASM (`.wasm`)
To customize build behavior and support new languages [check out our tooling guide](/guides/connecting-tools)
### JavaScript & ESM
Snowpack was designed to support JavaScript's native ES Module (ESM) syntax. ESM lets you define explicit imports & exports that browsers and build tools can better understand and optimize for. If you're familiar with the `import` and `export` keywords in JavaScript, then you already know ESM!
```js
// ESM Example - src/user.js
export function getUser() {
/* ... */
}
// src/index.js
import { getUser } from './user.js';
```
All modern browsers support ESM, so Snowpack is able to ship this code directly to the browser during development. This is what makes Snowpack's **unbundled development** workflow possible.
Snowpack also lets you import non-JavaScript files directly in your application. Snowpack handles all this for you automatically so there's nothing to configure, using the following logic:
### TypeScript
Snowpack includes built-in support to build TypeScript files (`*.ts`) to JavaScript.
Note that this built-in support is build only. By default, Snowpack does not type-check your TypeScript code. To integrate type checking into your development/build workflow, add the [@snowpack/plugin-typescript](https://www.npmjs.com/package/@snowpack/plugin-typescript) plugin.
### JSX
Snowpack includes built-in support to build JSX files (`*.jsx` & `*.tsx`) to JavaScript.
If you are using Preact, Snowpack will detect this and switch to use the Preact-style JSX `h()` function. This is all done automatically for you. If you need to customize this behavior, consider adding the [@snowpack/plugin-babel](https://www.npmjs.com/package/@snowpack/plugin-babel) plugin for full compiler customization via Babel.
**Note: Snowpack's default build does not support JSX in `.js`/`.ts` files.** If you can't use the `.jsx`/`.tsx` file extension, you can use [@snowpack/plugin-babel](https://www.npmjs.com/package/@snowpack/plugin-babel) to build your JavaScript instead.
### JSON
```js
// Load the JSON object via the default export
import json from './data.json';
```
Snowpack supports importing JSON files directly into your application. Imported files return the full JSON object in the default import.
### CSS
```js
// Load and inject 'style.css' onto the page
import './style.css';
```
Snowpack supports importing CSS files directly into your application. Imported styles expose no exports, but importing one will automatically add those styles to the page. This works for all CSS files by default, and can support compile-to-CSS languages like Sass & Less via plugins.
If you prefer not to write CSS, Snowpack also supports all popular CSS-in-JS libraries (ex: styled-components) for styling.
### CSS Modules
```js
// 1. Converts './style.module.css' classnames to unique, scoped values.
// 2. Returns an object mapping the original classnames to their final, scoped value.
import styles from './style.module.css';
// This example uses JSX, but you can use CSS Modules with any framework.
return <div className={styles.error}>Your Error Message</div>;
```
Snowpack supports CSS Modules using the `[name].module.css` naming convention. Like any CSS file, importing one will automatically apply that CSS to the page. However, CSS Modules export a special default `styles` object that maps your original classnames to unique identifiers.
CSS Modules help you enforce component scoping & isolation on the frontend with unique-generated class names for your stylesheets.
### Other Assets
```jsx
import imgReference from './image.png'; // img === '/src/image.png'
import svgReference from './image.svg'; // svg === '/src/image.svg'
import txtReference from './words.txt'; // txt === '/src/words.txt'
// This example uses JSX, but you can use import references with any framework.
<img src={imgReference} />;
```
All other assets not explicitly mentioned above can be imported via ESM `import` and will return a URL reference to the final built asset. This can be useful for referencing non-JS assets by URL, like creating an image element with a `src` attribute pointing to that image.
### WASM
```js
// Loads and intializes the requested WASM file
const wasm = await WebAssembly.instantiateStreaming(fetch('/example.wasm'));
```
Snowpack supports loading WASM files directly into your application using the browser's [`WebAssembly`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) API. Read our [WASM guide](/guides/wasm) to learn more.
### Import NPM Packages
```js
// Returns the React & React-DOM npm packages
import React from 'react';
import ReactDOM from 'react-dom';
```
Snowpack lets you import npm packages directly in the browser. Even if a package was published using a legacy format, Snowpack will up-convert the package to ESM before serving it to the browser.
When you start up your dev server or run a new build, you may see a message that Snowpack is "installing dependencies". This means that Snowpack is converting your dependencies to run in the browser. This needs to run only once, or until you next change your dependency tree by adding or removing dependencies.

View file

@ -0,0 +1,237 @@
---
layout: layouts/content.hmx
title: 'Starting a New Project'
description: This guide shows you how to set up Snowpack from scratch in a Node.js project. Along the way learn key concepts of Snowpack and unbundled development.
---
Welcome to Snowpack! This guide shows you how to set up Snowpack from scratch in a Node.js project. Along the way learn key concepts of Snowpack and unbundled development
In this guide you'll learn
- What makes Snowpack so fast? (hint: unbundled development!)
- What are JavaScript ES Modules (ESM)?
- Creating your first project
- Starting Snowpack's development server
- Building your first project
- Customizing Snowpack with plugins
> 💡 Tip: This guide walks you through creating the [Snowpack minimal app template](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/) from scratch. Spin up a copy of the final [using the create-snowpack-app command line tool](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/).
Prerequisites: Snowpack is a command line tool installed from npm. This guide assumes a basic understanding of JavaScript, npm, and how to run commands in the terminal.
Snowpack also requires a modern browser during development. Any semi-recent release of Firefox, Chrome, Safari, or Edge for example.
## Install Snowpack
To get started, create an empty directory for your new Snowpack project. Create the new directory using your favorite GUI or by running the command line as shown here:
```bash
mkdir my-first-snowpack
cd my-first-snowpack
```
Snowpack is a package installed from npm. Create a `package.json` file in your project directory to manage your dependencies. Run this command in your project to create a simple, empty `package.json`:
```bash
npm init
```
> 💡 Tip: In a hurry? Run `npm init --yes` to skip the prompts and generate a package.json with npm's default, recommended fields.
Now install Snowpack to your `dev dependencies` with this command:
```
npm install --save-dev snowpack
```
> 💡 Tip: Snowpack can install globally via `npm install -g snowpack`. But, we recommend installing locally in every project via `--save-dev`/`--dev`. Run the Snowpack command-line tool locally via package.json "scripts", npm's `npx snowpack`, or via `yarn snowpack`.
## Snowpack's development server
Adding a basic HTML file allows us to run Snowpack's development server, an instant development environment for unbundled development. The development server builds a file only when it's requested by the browser. That means that Snowpack can start up instantly (usually in **<50 ms**) and scale to infinitely large projects without slowing down. In contrast, it's common to see 30+ second development startup times when building large apps with a traditional bundler.
Create an `index.html` in your project with the following contents:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Starter Snowpack App" />
<title>Starter Snowpack App</title>
</head>
<body>
<h1>Welcome to Snowpack!</h1>
</body>
</html>
```
Add the Snowpack development server to `package.json` under as the `start` script:
```diff
"scripts": {
+ "start": "snowpack dev",
"test": "echo \"Error: no test specified\" && exit 1"
},
```
Run the following on the command line to start the Snowpack development server
```
npm run start
```
If all went well, Snowpack automatically opens your site in a new browser!
<div class="frame"><img src="/img/guides/getting-started/run-snowpack.jpg" alt="Side by side of the terminal showing the dev server output. The dev server output displays the localhost address the project is running on. In a browser window you can see the running project on localhost, which is 'Welcome to Snowpack' on a white background." class="screenshot"/></div>
Congratulations! You now have a Snowpack project up and running! Try changing the index.html and saving while the server is running, the site should refresh and show changes automatically.
## Using JavaScript
Learn more about how Snowpack processes JavaScript by adding a simple "hello world" script. JavaScript's native ES Module (ESM) syntax is the magic behind Snowpack's unbundled development. There's a good chance that you're already familiar with ESM, and you just don't know it! ESM lets you define explicit imports & exports that browsers and build tools can better understand and optimize for. If you're familiar with the `import` and `export` keywords in JavaScript, then you already know ESM!
Create a new JavaScript file called `hello-world.js` that exports a single `helloWorld` function:
```js
// my-first-snowpack/hello-world.js
export function helloWorld() {
console.log('Hello World!');
}
```
Then create an `index.js` that imports your new module using ESM syntax:
```js
// my-first-snowpack/index.js
import { helloWorld } from './hello-world.js';
helloWorld();
```
Snowpack scans for files referenced in `index.html`, so add your `index.js` to `index.html` at the bottom of the `<body>` tag:
```diff
<body>
<h1>Welcome to Snowpack!</h1>
+ <script type="module" src="/index.js"></script>
</body>
```
Check your console on your Snowpack site. You should see "Hello World!" Try making a change to the module. Snowpack rebuilds that module without rebuilding the rest of your code. Snowpack builds **every file individually and caches it indefinitely.** Your development environment never builds a file more than once and your browser never downloads a file twice (until it changes). This is the real power of unbundled development, and the secret behind what makes Snowpack so fast.
<div class="frame"><img src="/img/guides/getting-started/hello-world.gif" alt="Gif showing the code next to the project running in the browser. On save the console shows 'Hello World!'. On edit and save of the `hello-world.js` file to be 'Hello everyone!' instead, that instantly shows in the browser console." class="screenshot"/></div>
## Using npm Packages
Snowpack builds any npm package into ESM web modules. npm packages are mainly published using a module syntax (Common.js, or CJS) that can't run on the web without some build processing. Even if you write your application using browser-native ESM `import` and `export` statements that would all run directly in the browser, trying to import any one npm package forces you back into bundled development.
**Snowpack takes a different approach:** instead of bundling your entire application for this one requirement, Snowpack processes your dependencies separately. Here's how it works:
```
node_modules/react/**/* -> http://localhost:3000/web_modules/react.js
node_modules/react-dom/**/* -> http://localhost:3000/web_modules/react-dom.js
```
1. Snowpack scans your website/application for all used npm packages.
2. Snowpack reads these installed dependencies from your `node_modules` directory.
3. Snowpack bundles all your dependencies separately into single JavaScript files. For example: `react` and `react-dom` convert to `react.js` and `react-dom.js`, respectively.
4. Each resulting file runs directly in the browser, and imported via ESM `import` statements.
5. Because your dependencies rarely change, Snowpack rarely needs to rebuild them.
After Snowpack builds your dependencies, import any package and run it directly in the browser with zero extra bundling or tooling. This ability to import npm packages natively in the browser (without a bundler) is the foundation that all unbundled development and the rest of Snowpack builds on top of.
Snowpack lets you import npm packages directly in the browser. Even if a package is using a legacy format, Snowpack up-converts the package to ESM before serving it to the browser.
> 💡 Tip: when you start up your development server or run a new build, you may see a message that Snowpack is "installing dependencies." This means that Snowpack is converting your dependencies to run in the browser.
Install the canvas-confetti package from npm and use it with the following command:
```bash
npm install --save canvas-confetti
```
Now head to `index.js` and add this code:
```diff
helloWorld();
+import confetti from 'canvas-confetti';
+confetti.create(document.getElementById('canvas'), {
+ resize: true,
+ useWorker: true,
+ })({ particleCount: 200, spread: 200 });
```
> 💡 Tip: did you know, with Snowpack you can also add this code directly to your HTML if you prefer!
You should now see a nifty confetti effect on your site.
<div class="frame"><img src="/img/guides/getting-started/npm-snowpack-confetti.gif" alt="Gif showing the code next to the project running in the browser. When the code snippet is added and saved, a confetti effect shows in the browser" class="screenshot"/></div>
> 💡 Tip: not all npm modules may work well in the browser. Modules dependent on Node.js built-in modules need a polyfill. You can enable this polyfill by setting Snowpacks [`packageOptions.polyfillNode` configuration option](/reference/configuration#packageoptions.polyfillnode) to `true`.
## Adding CSS
Snowpack natively supports many file types. CSS and CSS Modules for example. Add a simple CSS file to see how it works.
Add the following css as a new `index.css` file:
```css
body {
font-family: sans-serif;
}
```
Include it in your project by adding it to index.html in the `<head>`
```diff
<meta name="description" content="Starter Snowpack App" />
+ <link rel="stylesheet" type="text/css" href="/index.css" />
<title>Starter Snowpack App</title>
```
<div class="frame"><img src="/img/guides/getting-started/snowpack-font-css.jpg" alt="image showing the effects of the new CSS file: the font has changed from serif to sans-serif" class="screenshot"/></div>
## Build for production/deployment
OK you've now built a very simple website and you want to launch it. It's time to use `snowpack build`.
By default, `snowpack build` builds your site using the same unbundled approach as the `dev` command. Building is integrated with your development setup which guarantees a near-exact copy of the same code that you saw during development.
Add the `snowpack build` command to package.json so it's easier to run on the command line:
```diff
"scripts": {
"start": "snowpack dev",
+ "build": "snowpack build",
"test": "echo \"Error: no test specified\" && exit 1"
},
```
Now you can run this in your terminal:
```bash
npm run build
```
You should see a new directory called `build` that contains a copy of your Snowpack project ready for deployment.
<div class="frame"><img src="/img/guides/getting-started/snowpack-build.gif" alt="GIF terminal running Snowpack build, showing output, then clicking on the new `build` directory" class="screenshot"/></div>
## Next Steps
You've just learned the major concepts of unbundled developments and built a tiny Snowpack project. But that's just the beginning with Snowpack.
What's next? Our docs site has several great resources
- [Bundling for production guide](/guides/optimize-and-bundle): how to connect a bundler like Webpack to optimize code for production deployments
- [Plugins](/plugins): a list of plugins that allow you to integrate your favorite tools with Snowpack
- [Templates/Examples](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/cli): pre-built projects you can build on or just explore using many popular frameworks and tools
- [Guides](/guides): Step by step deep dives on building with and for Snowpack. Includes frameworks like React and Svelte.
If you have any questions, comments, or corrections, we'd love to hear from you in the Snowpack [discussion](https://github.com/snowpackjs/snowpack/discussions) forum or our [Snowpack Discord community](https://discord.gg/rS8SnRk).

View file

@ -0,0 +1,61 @@
---
layout: layouts/content.hmx
title: Quick Start
description: A very basic guide for developers who want to run Snowpack as quickly as possible.
---
### Install Snowpack
```bash
# npm:
npm install --save-dev snowpack
# yarn:
yarn add --dev snowpack
# pnpm:
pnpm add --save-dev snowpack
```
### Run the Snowpack CLI
```bash
npx snowpack [command]
yarn run snowpack [command]
pnpm run snowpack [command]
```
Throughout our documentation, we'll use `snowpack [command]` to document the CLI. To run your locally installed version of Snowpack, add the `npx`/`yarn run`/`pnpm run` prefix of the package manager that you used to install Snowpack.
For long-term development, the best way to use Snowpack is with a package.json script. This reduces your own need to remember exact Snowpack commands/configuration, and lets you share some common scripts with the rest of your team (if applicable).
```js
// Recommended: package.json scripts
// npm run start (or: "yarn run ...", "pnpm run ...")
"scripts": {
"start": "snowpack dev",
"build": "snowpack build"
}
```
### Serve your project locally
```
snowpack dev
```
This starts the local dev server for development. By default this serves your current working directory to the browser, and will look for an `index.html` file to start. You can customize which directories you want to serve via the ["mount"](/reference/configuration) configuration.
### Build your project
```
snowpack build
```
This builds your project into a static `build/` directory that you can deploy anywhere. You can customize your build via [configuration](/reference/configuration).
### See all commands & options
```
snowpack --help
```
The `--help` flag will display helpful output.

View file

@ -0,0 +1,343 @@
---
layout: layouts/content-with-cover.hmx
title: 'Getting Started with React'
description: 'Get started with this in-depth tutorial on how to build React applications and websites with Snowpack and developer tools like React Fast Refresh'
date: 2020-12-01
tags: communityGuide
cover: '/img/ReactGuide.jpg'
img: '/img/ReactGuide.jpg'
---
Snowpack is a great fit for [React](https://reactjs.org/) projects of any size. It's easy to get started and can scale to projects containing thousands of components and pages without any impact on development speed. Unlike traditional React application tooling, Snowpack saves you from getting bogged down with complex bundler setups and configuration files.
In this guide, you'll go from an empty directory to a fully configured Snowpack project with support for React and several other useful developer tools. In the process, you'll learn:
- How to set up your Snowpack development environment
- Adding your first React component
- Working with CSS, images and other web assets
- Enabling [Fast Refresh](https://reactnative.dev/docs/fast-refresh) mode for React
- Connecting your favorite tools
Prerequisites: Snowpack is a command line tool installed from npm. This guide assumes a basic understanding of Node.js, npm, and how to run commands in the terminal. Knowledge of React is not required, Snowpack is a great way to learn React!
> 💡 Tip: if you want to jump to the end to see a full featured React setup, the [Create Snowpack App React template](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-react) comes with everything you'll learn in this guide plus other useful tools.
## Getting started
The easiest way to start a new Snowpack project is with [Create Snowpack App](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/cli), a tool to set up Snowpack in a new directory. `@snowpack/project-template-minimal` is a Create Snowpack App template for a simple, bare-bones Snowpack project setup that the rest of this guide builds on.
To get started, open your terminal and head to a directory where you want to put your new project. Now run the following command in your terminal to create a new directory called `react-snowpack` with the minimal template automatically installed.
```bash
npx create-snowpack-app react-snowpack --template @snowpack/app-template-minimal
```
You can now head to the new directory and start Snowpack with the following two commands:
```bash
cd react-snowpack
npm run start
```
You should see your new website up and running!
> 💡 Tip: the `README.md` in your new project contains useful information about what each file does.
<div class="frame"><img src="/img/guides/react/minimalist-hello-world.png" alt="screenshot of project-template-minimal, which shows 'Hello world' in text on a white background." class="screenshot"/></div>
Now that you have a basic project up and running, to install React, run the following command in your project directory:
```bash
npm install react react-dom --save
```
> 💡 Tip: add the `--use-yarn` or `--use-pnpm` flag to use something other than npm
## Create your first React component
React relies on a special templating language called JSX. If you're familiar with React then you already know JSX: it's React's templating language that allows you to write something like `<App />` or `<Header></Header>` directly in your JavaScript code.
Snowpack has built in support for JSX in files using the `.jsx` extension. That means that there's no plugins or configuration needed to write your first React component. Rename `index.js` file to `index.jsx` so that Snowpack knows to handle JSX in the file:
```bash
mv index.js index.jsx
```
> 💡 Tip: you do not need to update your `index.html` script tag reference to point to `index.jsx`. Browsers don't speak JSX (or TypeScript, for that matter), so any compile-to-JS file formats compile to `.js` in the final browser build. This is good to keep in mind when you're referencing built files in HTML `<script src="">` and `<link href="">` elements.
You can now import React in `index.jsx` and add a simple test component just to make sure it's working:
```diff
/* Add JavaScript code here! */
- console.log('Hello World! You did it! Welcome to Snowpack :D');
+ import React from 'react';
+ import ReactDOM from 'react-dom';
+ ReactDOM.render(<div>"HELLO REACT"</div>, document.getElementById('root'));
```
Since the React code is rendering into an element with the ID `root`, you'll need to add that to `index.html`:
```diff
<body>
- <h1>Welcome to Snowpack!</h1>
+ <div id="root"></div>
<script type="module" src="/index.js"></script>
</body>
```
<div class="frame"><img src="/img/guides/react/minimalist-hello-world-react.png" alt="screenshot of the project, which shows 'HELLO REACT' on a white background" class="screenshot"/></div>
You've just created your first React component in Snowpack!
## Customize your project layout
Since you'll be adding a bunch of new files, you probably don't want them crowding up your top-level root directly. Snowpack is flexible enough to support whatever project layout that you prefer. In this guide, you'll learn how to use a popular project pattern from the React community.
```
📁 src : your React components and their assets (CSS, images)
↳ index.jsx
📁 public : global assets like images, fonts, icons, and global CSS
↳ index.css
↳ index.html
```
Use your favorite visual editor to rearrange and rename, or run these commands in the terminal:
```bash
mkdir src
mkdir public
mv index.jsx src/index.jsx
mv index.html public/index.html
mv index.css public/index.css
```
This means if you are running Snowpack right now, the site is now broken as the files are all in different places. Lets add a "mount" configuration to update your site to your new project layout.
The `mount` configuration changes where Snowpack looks for and builds files. Every Snowpack project comes with a `snowpack.config.js` file for any configuration that you might need. Right now, you should see a configuration file with empty options. Add this to the empty `mount` object:
```diff
mount: {
- /* ... */
+ // directory name: 'build directory'
+ public: '/',
+ src: '/dist',
},
```
<img src="/img/guides/react/folderstructure.png" alt="The original file configuration had Snowpack building the directory structure the same as the directories in the project, including root. Now the config builds only src and public. Src to the dist folder and public to root." />
`mount` is part of the [Snowpack Configuration API](/reference/configuration). It allows you to customize the file structure of your project. The key is the name of the directory and the value is where you'd like them in the final build. With this new configuration, Snowpack builds files in `public` like `public/index.css` directory into `index.css`. It builds files in `src` like `src/index.js` into `/dist/index.js`, so you'll need to change that path in your `index.html`:
```diff
<body>
<h1>Welcome to Snowpack!</h1>
<div id="root"></div>
- <script type="module" src="/index.js"></script>
+ <script type="module" src="/dist/index.js"></script>
</body>
```
You'll need to restart Snowpack for configuration file changes. When you start up again, if it worked, it should look the same.
Create a new file at `src/App.jsx` and paste the following code into this new file to create an `App` component:
```jsx
import React, { useState, useEffect } from 'react';
function App() {
// Create the count state.
const [count, setCount] = useState(0);
// Update the count (+1 every second).
useEffect(() => {
const timer = setTimeout(() => setCount(count + 1), 1000);
return () => clearTimeout(timer);
}, [count, setCount]);
// Return the App component.
return (
<div className="App">
<header className="App-header">
<p>
Page has been open for <code>{count}</code> seconds.
</p>
</header>
</div>
);
}
export default App;
```
Now include it in `index.jsx`
```diff
import React from 'react';
import ReactDOM from 'react-dom';
- ReactDOM.render(<div>"HELLO WORLD"</div>, document.getElementById('root'));
+ import App from './App.jsx';
+ ReactDOM.render(
+ <React.StrictMode>
+ <App />
+ </React.StrictMode>,
+ document.getElementById('root'),
+ );
```
> 💡 Tip: [Strict Mode](https://reactjs.org/docs/strict-mode.html) is a tool for highlighting potential problems in React code.
You shouldn't need to restart Snowpack to see this, it should look like this:
<div class="frame"><img src="/img/guides/react/minimalist-hello-world-react-timer.png" alt="screenshot of the project with text that says 'Page has been open for' and the number of seconds then 'seconds'" class="screenshot"/></div>
## Styling your project
When you add assets like images or CSS, Snowpack includes them in your final build. If you already know React, this process should look pretty familiar.
> 💡 Tip: as you're doing this, you should not need to reload the page or restart Snowpack. Snowpack automatically updates the project in the browser as you edit code.
Add this file [`logo.svg`](https://github.com/snowpackjs/snowpack/blob/main/create-snowpack-app/app-template-react/src/logo.svg) to your `src` directory. Now you can import it into your `App.jsx` and use it in an `img` tag to display it.
```diff
import React, { useState, useEffect } from 'react';
+ import logo from './logo.svg';
function App() {
// Create the count state.
const [count, setCount] = useState(0);
// Create the counter (+1 every second).
useEffect(() => {
const timer = setTimeout(() => setCount(count + 1), 1000);
return () => clearTimeout(timer);
}, [count, setCount]);
// Return the App component.
return (
<div className="App">
<header className="App-header">
+ <img src={logo} className="App-logo" alt="logo" />
<p>
```
<div class="frame"><img src="/img/guides/react/minimalist-hello-world-react-logo.png" alt="the React logo (a blue atom) is now at the top of the page" class="screenshot"/></div>
The project already has index.css for global styles. For CSS that's only for a specific component, a common design pattern is to add it in a CSS file with the same base name as the component. The style file for `App.jsx` would be `App.css` with this pattern.
> 💡 Tip: Snowpack has built-in support for [CSS Modules](/reference/supported-files) and if you'd like to use Sass there is an official [Sass Plugin](/guides/sass/).
Create `src/App.css` and add this CSS:
```css
.App {
text-align: center;
}
.App p {
margin: 0.4rem;
}
.App-logo {
height: 40vmin;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
```
To use this CSS, head to `App.jsx` and import it
```diff
import logo from './logo.svg';
+ import './App.css';
```
<div class="frame"><img src="/img/guides/react/react.gif" alt="The page now has centered items, a grey background, styled fonts, and the React logo has an animation that rotates it." class="screenshot"/></div>
## Making Snowpack Even Faster with Fast Refresh
[React Fast Refresh](https://reactnative.dev/docs/fast-refresh)? What's that? It's a Snowpack enhancement that lets you push individual file changes to update the browser without refreshing the page or clearing component state.
React projects are often interactive and include state. For example, this project you're building has a state that is the amount of time on the page. When developing with state it's useful not to lose it while you edit code. React Fast Refresh shows you updates without refreshing the entire page. Showing you how to add this is also a good intro to Snowpack plugins. Snowpack starts with a minimal setup with the perspective that you can add what you need through the plugin system.
Start by enabling [Hot Module Replacement](/concepts/hot-module-replacement) in your project. HMR is the system that lets Snowpack push updates to the browser without a full page refresh, a requirement for Fast Refresh. You can enable HMR for React by adding a small snippet of code to your `src/index.jsx` file.
```diff
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root'),
);
+ // Hot Module Replacement (HMR) - Remove this snippet to remove HMR.
+ // Learn more: https://www.snowpack.dev/concepts/hot-module-replacement
+ if (import.meta.hot) {
+ import.meta.hot.accept();
+ }
```
Now when you change `App.jsx` the page updates to show your changes without a full refresh.
<div class="frame"><img src="/img/guides/react/hmr.gif" alt="GIF showing code side by side with the app. A change in made to App.jsx and it shows immediately when the file is changed. The counter keeps counting uninterrupted." class="screenshot"/></div>
HMR can save you time on its own, but you may notice in the example above that the counter on the page still resets to 0. This can slow down your development, especially when you're trying to debug a specific component state problem. Lets enable Fast Refresh to preserve component state across updates.
To enable Fast Refresh, you'll need to install the `@snowpack/plugin-react-refresh` package. This package is a Snowpack plugin, which you can use to enhance or customize Snowpack with all sorts of new behaviors. To start, install the package in your project:
```bash
npm install @snowpack/plugin-react-refresh --save-dev
```
Once installed, you'll need to add the plugin to your Snowpack configuration file so that Snowpack knows to use it:
```diff
module.exports = {
mount: {
public: '/',
src: '/dist',
},
- plugins: []
+ plugins: ['@snowpack/plugin-react-refresh'],
};
```
Restart Snowpack to apply the new plugin, and then try changing the `App.jsx` component again. If Fast Refresh is working properly, the counter keeps its value across changes, without resetting to zero.
<div class="frame"><img src="/img/guides/react/react-fast-refresh.gif" alt="GIF showing code side by side with the app. A change in made to App.jsx and it shows immediately when the file is changed. The counter keeps counting uninterrupted." class="screenshot"/></div>
## Going further
Great job! You're now ready to build the React project of your dreams with Snowpack. Want to tweet your accomplishment to the world? Click the button below:
<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-text="I just learned how to build a React app with #Snowpack. Check out the tutorial:" data-show-count="false">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
At this point you have the basics and have a great starter for any React project. But if you compare with the official [Snowpack React template](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-react) you'll notice it has some other developer tools you might find useful:
- [Prettier](https://prettier.io/)—a popular code formatter
- [Tests](/guides/testing)—Snowpack supports any popular JavaScript testing framework
- [`@snowpack/plugin-dotenv`](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-dotenv)—Use `dotenv` in your Snowpack. This is useful for environment specific variables
If you'd like to use Typescript with Snowpack and React, check out the [Snowpack React Typescript](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-react-typescript) starter.
If you have any questions, comments, or corrections, we'd love to hear from you in the Snowpack [discussion](https://github.com/snowpackjs/snowpack/discussions) forum or our [Snowpack Discord community](https://discord.gg/rS8SnRk).

View file

@ -0,0 +1,330 @@
---
layout: layouts/content-with-cover.hmx
title: 'Getting Started with Svelte'
description: 'Get started with this in-depth tutorial on how to build Svelte applications and websites with Snowpack'
date: 2020-12-01
sidebarTitle: Svelte
tags: communityGuide
cover: '/img/SvelteGuide.jpg'
img: '/img/SvelteGuide.jpg'
---
Snowpack is a great fit for [Svelte](https://svelte.dev/) projects of any size. It's easy to get started and can scale to projects containing thousands of components and pages without any impact on development speed. Unlike traditional Svelte application tooling, Snowpack saves you from getting bogged down with complex bundler setups and configuration files.
> Snowpack is … astonishingly fast, and has a beautiful development experience (hot module reloading, error overlays and so on), and we've been working closely with the Snowpack team on features like SSR[Server-side rendering]. The hot module reloading is particularly revelatory. - [Rich Harris, creator of Svelte](https://svelte.dev/blog/whats-the-deal-with-sveltekit)
This guide is a step by step from an empty directory to a fully configured Snowpack project, in the process teaching:
- How to set up your Snowpack development environment
- Adding your first Svelte component
- Importing images and other web assets
- Enabling Hot Module Replacement (HMR)
- Connecting your favorite tools
Prerequisites: Snowpack is a command-line tool installed from npm. This guide assumes a basic understanding of Node.js, npm, and how to run commands in the terminal. Knowledge of Svelte is not required: Snowpack is an excellent way to learn Svelte!
> 💡 Tip: a [Svelte/Snowpack](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-svelte) working example is available in our Create Snowpack App templates.
## Getting started
The easiest way to start a new Snowpack project is with [Create Snowpack App](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/cli), a tool for creating a new project based on our example templates. `@snowpack/app-template-minimal` is a Create Snowpack App template for a simple, bare-bones Snowpack project setup that the rest of this guide builds on.
Run the following command in your terminal to create a new directory called `svelte-snowpack` with the minimal template installed:
```bash
npx create-snowpack-app svelte-snowpack --template @snowpack/app-template-minimal
```
Head to the new `svelte-snowpack` directory and start Snowpack with the following two commands:
```bash
cd svelte-snowpack
npm run start
```
You should see your new website up and running!
<div class="frame"><img src="/img/guides/react/minimalist-hello-world.png" alt="screenshot of project-template-minimal, which shows 'Hello world' in text on a white background." class="screenshot"/></div>
Now that you have a basic project up and running! The next step is to install Svelte. Run the following command in your project directory:
```bash
npm install svelte --save
```
> 💡 Tip: add the `--use-yarn` or `--use-pnpm` flag to use something other than npm
```bash
npm install @snowpack/plugin-svelte --save-dev
```
Snowpack [plugins](/plugins) are a way to extend Snowpack's capabilities without having to do custom configuration yourself. Install the `@snowpack/plugin-svelte` plugin so that Snowpack knows how built `.svelte` files into JavaScript and CSS files that run in the browser:
Once installed, you'll need to add the plugin to your Snowpack configuration file (`snowpack.config.js`) so that Snowpack knows to use it:
```diff
// snowpack.config.js
module.exports = {
mount: {
/* ... */
},
plugins: [
- /* ... */
+ '@snowpack/plugin-svelte'
],
```
Restart your Snowpack dev server to run it with the new configuration. Exit the process (ctrl + c in most Windows/Linux/macOS) and start it again with `npm run start`.
> 💡 Tip: Restart the Snowpack development server when you make configuration changes (changes to the `snowpack.config.js`).
Snowpack will recognize the new dependency (Svelte, or "svelte/internal") and print the following output as installs your dependencies for the frontend:
```bash
[snowpack] installing dependencies...
[snowpack] ✔ install complete! [0.45s]
[snowpack]
⦿ web_modules/ size gzip brotli
├─ svelte-hmr/runtime/hot-api-esm.js 22.17 KB 7.42 KB 6.3 KB
├─ svelte-hmr/runtime/proxy-adapter-dom.js 5.17 KB 1.65 KB 1.38 KB
└─ svelte/internal.js 52.78 KB 13.24 KB 11.45 KB
```
## Create your first Svelte component
You now have your Snowpack environment set up to build `.svelte` files for the browser. Now it's time to create your first Svelte component file!
Create a file named `App.svelte` in your project directory with the following code:
```html
<!-- App.svelte -->
<script>
/* component logic will go here */
</script>
<style>
/* css will go here */
</style>
<div class="App">
<header class="App-header">
<a
class="App-link"
href="https://svelte.dev"
target="_blank"
rel="noopener noreferrer"
>
Learn Svelte
</a>
</header>
</div>
```
Now you can use the new `App.svelte` file in your `index.js`:
```diff
// index.js
/* Add JavaScript code here! */
-console.log('Hello World! You did it! Welcome to Snowpack :D');
+import App from "./App.svelte";
+let app = new App({
+ target: document.body,
+});
+export default app;
```
The page should now say "Learn Svelte". Congratulations! you now have your first Svelte component!
<div class="frame"><img src="/img/guides/svelte/svelte-component-snowpack.gif" alt="code and site side by side, site is a 'Learn Svelte' link on a white background. When the text is edit to add 'Hello world' and the file saves, the changes show up in the site immediately." class="screenshot"/></div>
## Customize your project layout
Snowpack is flexible enough to support whatever project layout that you prefer. In this guide, you'll learn how to use a popular project pattern from the Svelte community.
```
📁 src : your Svelte components and their assets (CSS, images)
↳ index.js
↳ App.svelte
📁 public : global assets like images, fonts, icons, and global CSS
↳ index.css
↳ index.html
```
Use your favorite visual editor to rearrange and rename, or run these commands in the terminal:
```bash
mkdir src
mkdir public
mv index.js src/index.js
mv App.svelte src/App.svelte
mv index.html public/index.html
mv index.css public/index.css
```
This means if you are running Snowpack right now, the site is now broken as the files are all in different places. Lets add a "mount" configuration to update your site to your new project layout.
The `mount` configuration changes where Snowpack scan for and builds files. Head back to the `snowpack.config.js` file you edited when you added `@snowpack/plugin-svelte`. Add this to the empty `mount` object:
```diff
// snowpack.config.js
mount: {
- /* ... */
+ // directory name: 'build directory'
+ public: '/',
+ src: '/dist',
},
```
<img src="/img/guides/folder-structure.png" alt="Graphic shows the original and new folder structures side by side. Arrows indicate that the files are built to where the arrow points. The Original side shows a folder labeled ./ entire directory with an arrow pointing to a folder labeled mysite.com/*. The New side shows a folder labeled ./src/* with an arrow pointing to a folder labeled mysite.com/_dist/*. Then a second folder labeled ./public/* with an arrow pointing to a folder labeled mysite.com/* " />
`mount` is part of the [Snowpack Configuration API](/reference/configuration). It allows you to customize the file structure of your project. The key is the name of the directory and the value is where you'd like them in the final build. With this new configuration, Snowpack builds files in the `public` directory - like `public/index.css` - into `index.css`. Likewise, it builds files in `src` like `src/index.js` into `/dist/index.js`, so change that path in your `index.html`:
```diff
<!-- public/index.html -->
<body>
<h1>Welcome to Snowpack!</h1>
- <script type="module" src="/index.js"></script>
+ <script type="module" src="/dist/index.js"></script>
</body>
```
You'll need to restart Snowpack (stop the process in terminal and then run `npm start` again) for configuration file changes. It should look exactly as it did before, but now using your brand new project folder layout
## Adding an animated Svelte Logo
In Svelte you can add CSS directly to your component. This step demonstrates this capability by adding an animated logo.
[Download `logo.svg`](https://github.com/snowpackjs/snowpack/blob/main/create-snowpack-app/app-template-svelte/public/logo.svg) to your `public` directory. Now you can add it to your `App.svelte`
```diff
<!-- src/App.svelte -->
<header class="App-header">
+ <img src="/logo.svg" class="App-logo" alt="logo" />
<a
class="App-link"
href="https://svelte.dev"
target="_blank"
rel="noopener noreferrer">
Learn Svelte
</a>
```
<div class="frame"><img src="/img/guides/svelte/svelte-logo-snowpack.jpg" alt="Side by side of code and site. The site now has a very large Svelte logo. The code shows the src/App.svelte file " class="screenshot"/></div>
With Svelte, CSS can go directly in your `.svelte` component. Add this code to the top of `App.svelte` between the `<style>` tags:
```html
<!-- src/App.svelte -->
<style>
.App-header {
background-color: #f9f6f6;
color: #333;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
}
.App-logo {
height: 36vmin;
pointer-events: none;
margin-bottom: 3rem;
animation: App-logo-pulse infinite 1.6s ease-in-out alternate;
}
@keyframes App-logo-pulse {
from {
transform: scale(1);
}
to {
transform: scale(1.06);
}
}
</style>
```
<div class="frame"><img src="/img/guides/svelte/svelte-logo-style-snowpack.gif" alt="code and site side by side, when the css is added to the Svelte component, the background becomes a beige, the logo shrinks down, and the logo has a pulsing animation" class="screenshot"/></div>
## Adding a counter to your Svelte component
Snowpack is one of the only Svelte dev environments to support Fast Refresh by default. With Fast Refresh, as you make changes to `.svelte` files, Snowpack pushes live updates to the browser without losing your place or resetting component state. To see this for yourself, go ahead and add a simple timer to your App.svelte component.
Svelte components include component specific scripts in a `<script>` tag. Add the counter here in `App.svelte` between the `<script>` tags:
```html
<!-- src/App.svelte -->
<script>
import { onMount } from 'svelte';
let count = 0;
onMount(() => {
const interval = setInterval(() => count++, 1000);
return () => {
clearInterval(interval);
};
});
</script>
```
Then lower down in your component's body, add this code that displays the results of the timer.
```diff
<!-- src/App.svelte -->
<div class="App">
<header class="App-header">
<img src="/logo.svg" class="App-logo" alt="logo" />
+ <p>Page has been open for <code>{count}</code> seconds.</p>
<a class="App-link" href="https://svelte.dev" target="_blank" rel="noopener noreferrer">
Learn Svelte
</a>
</header>
</div>
```
Change some code on the page (like the "Learn Svelte" button). You'll see the timer does not reset.
<div class="frame"><img src="/img/guides/svelte/svelte-snowpack-counter-1.gif" alt="Showing code and site side by side, when the word 'Hello' is added to the .svelte page and the code is saved, the change shows up in the browser without the timer resetting (it keeps counting)" class="screenshot"/></div>
What about other, non-Svelte files like `src/index.js`? To re-render your Svelte application when other files change, add this code snippet to the bottom:
```diff
<!-- src/index.js-->
export default app;
+// Hot Module Replacement (HMR) - Remove this snippet to remove HMR.
+// Learn more: https://www.snowpack.dev/concepts/hot-module-replacement
+if (import.meta.hot) {
+ import.meta.hot.accept();
+ import.meta.hot.dispose(() => {
+ app.$destroy();
+ });
+}
```
## Going further
Great job! You're now ready to build the Svelte project of your dreams with Snowpack. Want to tweet your accomplishment to the world? Click the button below:
<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-text="I just learned how to build a Svelte app with #Snowpack. Check out the tutorial:" data-show-count="false">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
At this point you have the basics and have a great starter for any Svelte project. The official [Snowpack Svelte](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-svelte) example has a few other tools you might find useful:
- [Prettier](https://prettier.io/)—a popular code formatter
- [Tests](/guides/testing)—Snowpack supports any popular JavaScript testing framework
- [`@snowpack/plugin-dotenv`](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-dotenv)—Use `dotenv` in your Snowpack. This is useful for environment specific variables
We also recommend the official [Svelte](https://svelte.dev/tutorial/basics) tutorial, which teaches more about how Svelte works and how to build Svelte components.
If you'd like to use Typescript with Snowpack and Svelte, check out the [Snowpack Svelte Typescript](https://github.com/snowpackjs/snowpack/tree/main/create-snowpack-app/app-template-svelte-typescript) template.
If you have any questions, comments, or corrections, we'd love to hear from you in the Snowpack [discussion](https://github.com/snowpackjs/snowpack/discussions) forum or our [Snowpack Discord community](https://discord.gg/rS8SnRk).

16739
examples/snowpack/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
{
"name": "snowpack-www",
"version": "3.0.0",
"scripts": {
"start": "astro dev .",
"build": "astro build",
"test": "jest /__test__/",
"format": "prettier --write \"src/**/*.js\" && yarn format:css",
"format:css": "stylelint 'src/**/*.scss' --fix",
"lint": "prettier --check \"src/**/*.js\""
},
"devDependencies": {
"@11ty/eleventy": "^0.11.0",
"@11ty/eleventy-plugin-rss": "^1.0.9",
"@11ty/eleventy-plugin-syntaxhighlight": "^3.0.4",
"@contentful/rich-text-html-renderer": "^14.1.2",
"@contentful/rich-text-types": "^14.1.2",
"@snowpack/plugin-postcss": "^1.0.7",
"@snowpack/plugin-run-script": "^2.3.0",
"@snowpack/plugin-sass": "^1.1.1",
"@snowpack/plugin-svelte": "^3.5.2",
"@snowpack/plugin-vue": "^2.3.0",
"eleventy-plugin-nesting-toc": "^1.2.0",
"luxon": "^1.25.0",
"markdown-it": "^12.0.2",
"markdown-it-anchor": "^6.0.0",
"postcss-cli": "^8.3.0",
"postcss-preset-env": "^6.7.0",
"prettier": "^2.0.5",
"snowpack": "^3.1.0-pre.11",
"stylelint": "^13.8.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-standard": "^20.0.0",
"svelte": "^3.35.0"
},
"dependencies": {
"@material-ui/core": "^4.11.3",
"astro": "file:../../",
"date-fns": "^2.19.0",
"deepmerge": "^4.2.2",
"docsearch.js": "^2.6.3",
"htm": "^3.0.4",
"mdast-util-from-markdown": "^0.8.5",
"mdast-util-toc": "^5.1.0",
"preact": "^10.5.12",
"preact-render-to-string": "^5.1.12",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"vue": "^3.0.7"
}
}

View file

@ -0,0 +1,53 @@
@use './var' as *;
$easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
$easeInExpo: cubic-bezier(0.7, 0, 0.84, 0);
$easeInOutSine: cubic-bezier(0.37, 0, 0.63, 1);
$easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
$easeInOutBack: cubic-bezier(0.68, -0.6, 0.32, 1.6);
$easeInCirc: cubic-bezier(0.55, 0, 1, 0.45);
$easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
$easeInQuad: cubic-bezier(0.11, 0, 0.5, 0);
$quintic: cubic-bezier(0.76, 0.05, 0.86, 0.06);
$transition-fast: 40ms;
$transition-medium: 500ms;
$transition-slow: 1s;
@mixin animation-hover-pop {
transition: transform $transition-fast $easeInExpo,
box-shadow $transition-fast linear;
&:hover {
box-shadow: 0 2px 2px 0 #2e5e82aa;
transform: translateY(-1px);
}
}
@keyframes pulse {
0% {
color: #2a85ca;
border-color: #2a85ca;
}
100% {
}
}
@mixin animation-copy-button {
transition: transform $transition-fast $easeInExpo,
border-color $transition-fast linear, box-shadow $transition-fast linear;
svg,
span {
transition: color $transition-fast linear;
}
&:hover {
box-shadow: 0 2px 2px 0 #2e5e8266;
transform: translateY(-1px);
border-color: #2a85ca;
svg,
span {
color: #2a85ca;
}
}
}

View file

@ -0,0 +1,616 @@
.markdown-body .anchor {
float: left;
margin-left: -20px;
padding-right: 4px;
line-height: 1;
}
.markdown-body .anchor:focus {
outline: none;
}
.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
text-decoration: none;
}
.markdown-body {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
color: #24292e;
line-height: 1.6;
word-wrap: break-word;
}
.markdown-body .pl-c {
color: #6a737d;
}
.markdown-body .pl-c1,
.markdown-body .pl-s .pl-v {
color: #005cc5;
}
.markdown-body .pl-e,
.markdown-body .pl-en {
color: #6f42c1;
}
.markdown-body .pl-s .pl-s1,
.markdown-body .pl-smi {
color: #24292e;
}
.markdown-body .pl-ent {
color: #22863a;
}
.markdown-body .pl-k {
color: #d73a49;
}
.markdown-body .pl-pds,
.markdown-body .pl-s,
.markdown-body .pl-s .pl-pse .pl-s1,
.markdown-body .pl-sr,
.markdown-body .pl-sr .pl-cce,
.markdown-body .pl-sr .pl-sra,
.markdown-body .pl-sr .pl-sre {
color: #032f62;
}
.markdown-body .pl-smw,
.markdown-body .pl-v {
color: #e36209;
}
.markdown-body .pl-bu {
color: #b31d28;
}
.markdown-body .pl-ii {
color: #fafbfc;
background-color: #b31d28;
}
.markdown-body .pl-c2 {
color: #fafbfc;
background-color: #d73a49;
}
.markdown-body .pl-c2::before {
content: '^M';
}
.markdown-body .pl-sr .pl-cce {
color: #22863a;
font-weight: 700;
}
.markdown-body .pl-ml {
color: #735c0f;
}
.markdown-body .pl-mh,
.markdown-body .pl-mh .pl-en,
.markdown-body .pl-ms {
color: #005cc5;
font-weight: 700;
}
.markdown-body .pl-mi {
color: #24292e;
font-style: italic;
}
.markdown-body .pl-mb {
color: #24292e;
font-weight: 700;
}
.markdown-body .pl-md {
color: #b31d28;
background-color: #ffeef0;
}
.markdown-body .pl-mi1 {
color: #22863a;
background-color: #f0fff4;
}
.markdown-body .pl-mc {
color: #e36209;
background-color: #ffebda;
}
.markdown-body .pl-mi2 {
color: #f6f8fa;
background-color: #005cc5;
}
.markdown-body .pl-mdr {
color: #6f42c1;
font-weight: 700;
}
.markdown-body .pl-ba {
color: #586069;
}
.markdown-body .pl-sg {
color: #959da5;
}
.markdown-body .pl-corl {
color: #032f62;
text-decoration: underline;
}
.markdown-body details {
display: block;
}
.markdown-body summary {
display: list-item;
}
.markdown-body a {
background-color: transparent;
}
.markdown-body a:active,
.markdown-body a:hover {
outline-width: 0;
}
.markdown-body strong {
font-weight: inherit;
font-weight: bolder;
}
.markdown-body h1 {
margin: 0.67em 0;
font-size: 2em;
}
.markdown-body img {
border-style: none;
}
.markdown-body hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
.markdown-body input {
margin: 0;
font: inherit;
}
.markdown-body input {
overflow: visible;
}
.markdown-body [type='checkbox'] {
box-sizing: border-box;
padding: 0;
}
.markdown-body * {
box-sizing: border-box;
}
.markdown-body input {
font-size: inherit;
font-family: inherit;
line-height: inherit;
}
.markdown-body a {
color: #0366d6;
text-decoration: none;
}
.markdown-body a:hover {
text-decoration: underline;
}
.markdown-body strong {
font-weight: 600;
}
.markdown-body hr {
height: 0;
margin: 15px 0;
overflow: hidden;
background: transparent;
border: 0;
border-bottom: 1px solid #dfe2e5;
}
.markdown-body hr::before {
display: table;
content: '';
}
.markdown-body hr::after {
display: table;
clear: both;
content: '';
}
.markdown-body table {
border-collapse: collapse;
border-spacing: 0;
}
.markdown-body table {
display: block;
width: 100%;
overflow: auto;
}
.markdown-body table td,
.markdown-body table th {
padding: 6px 13px;
}
.markdown-body table tr {
background-color: #fff;
}
.markdown-body table tr:nth-child(2n) {
background-color: #f6f8fa;
}
.markdown-body details summary {
cursor: pointer;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body h1 {
font-size: 32px;
}
.markdown-body h1,
.markdown-body h2 {
font-weight: 600;
}
.markdown-body h2 {
font-size: 24px;
}
.markdown-body h3 {
font-size: 20px;
}
.markdown-body h3,
.markdown-body h4 {
font-weight: 600;
}
.markdown-body h4 {
font-size: 16px;
}
.markdown-body h5 {
font-size: 14px;
}
.markdown-body h5,
.markdown-body h6 {
font-weight: 600;
}
.markdown-body h6 {
font-size: 12px;
}
.markdown-body p {
margin-top: 0;
margin-bottom: 10px;
}
.markdown-body blockquote {
margin: 0;
}
.markdown-body ol,
.markdown-body ul {
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
}
.markdown-body ol ol,
.markdown-body ul ol {
list-style-type: lower-roman;
}
.markdown-body ol ol ol,
.markdown-body ol ul ol,
.markdown-body ul ol ol,
.markdown-body ul ul ol {
list-style-type: lower-alpha;
}
.markdown-body dd {
margin-left: 0;
}
.markdown-body input::-webkit-inner-spin-button,
.markdown-body input::-webkit-outer-spin-button {
margin: 0;
-webkit-appearance: none;
appearance: none;
}
.markdown-body .border {
border: 1px solid #e1e4e8 !important;
}
.markdown-body .border-0 {
border: 0 !important;
}
.markdown-body .border-bottom {
border-bottom: 1px solid #e1e4e8 !important;
}
.markdown-body .rounded-1 {
border-radius: 3px !important;
}
.markdown-body .bg-white {
background-color: #fff !important;
}
.markdown-body .bg-gray-light {
background-color: #fafbfc !important;
}
.markdown-body .text-gray-light {
color: #6a737d !important;
}
.markdown-body .mb-0 {
margin-bottom: 0 !important;
}
.markdown-body .my-2 {
margin-top: 8px !important;
margin-bottom: 8px !important;
}
.markdown-body .pl-0 {
padding-left: 0 !important;
}
.markdown-body .py-0 {
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.markdown-body .pl-1 {
padding-left: 4px !important;
}
.markdown-body .pl-2 {
padding-left: 8px !important;
}
.markdown-body .py-2 {
padding-top: 8px !important;
padding-bottom: 8px !important;
}
.markdown-body .pl-3,
.markdown-body .px-3 {
padding-left: 16px !important;
}
.markdown-body .px-3 {
padding-right: 16px !important;
}
.markdown-body .pl-4 {
padding-left: 24px !important;
}
.markdown-body .pl-5 {
padding-left: 32px !important;
}
.markdown-body .pl-6 {
padding-left: 40px !important;
}
.markdown-body .f6 {
font-size: 12px !important;
}
.markdown-body .lh-condensed {
line-height: 1.25 !important;
}
.markdown-body .text-bold {
font-weight: 600 !important;
}
.markdown-body::before {
display: table;
content: '';
}
.markdown-body::after {
display: table;
clear: both;
content: '';
}
.markdown-body > :first-child {
margin-top: 0 !important;
}
.markdown-body > :last-child {
margin-bottom: 0 !important;
}
.markdown-body a:not([href]) {
color: inherit;
text-decoration: none;
}
.markdown-body blockquote,
.markdown-body dl,
.markdown-body ol,
.markdown-body p,
.markdown-body table,
.markdown-body ul {
margin-top: 0;
margin-bottom: 16px;
}
.markdown-body hr {
height: 0.25em;
margin: 24px 0;
padding: 0;
background-color: #e1e4e8;
border: 0;
}
.markdown-body blockquote {
padding: 0 1em;
color: #6a737d;
border-left: 0.25em solid #dfe2e5;
}
.markdown-body blockquote > :first-child {
margin-top: 0;
}
.markdown-body blockquote > :last-child {
margin-bottom: 0;
}
.markdown-body kbd {
display: inline-block;
padding: 3px 5px;
color: #444d56;
font-size: 11px;
line-height: 10px;
vertical-align: middle;
background-color: #fafbfc;
border: 1px solid #c6cbd1;
border-bottom-color: #959da5;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #959da5;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 42px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}
.markdown-body h1 {
font-size: 2em;
}
.markdown-body h1,
.markdown-body h2 {
/* border-bottom: 1px solid #eaecef; */
/* padding-bottom: 0.3em; */
}
.markdown-body h1 {
margin-bottom: 0;
padding-bottom: 0;
font-size: 4em;
}
.markdown-body h2 {
font-size: 2.6em;
}
.markdown-body h3 {
font-size: 1.8em;
}
.markdown-body h4 {
font-size: 1.12em;
}
.markdown-body h5 {
font-size: 0.875em;
}
.markdown-body h6 {
color: #6a737d;
font-size: 0.85em;
}
.markdown-body ol,
.markdown-body ul {
padding-left: 2em;
}
.markdown-body ol ol,
.markdown-body ol ul,
.markdown-body ul ol,
.markdown-body ul ul {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body li {
word-wrap: break-all;
}
.markdown-body li > p {
margin-top: 16px;
}
.markdown-body li + li {
margin-top: 0.25em;
}
.markdown-body img {
box-sizing: content-box;
max-width: 100%;
background-color: #fff;
}
.markdown-body img[align='right'] {
padding-left: 20px;
}
.markdown-body img[align='left'] {
padding-right: 20px;
}
.markdown-body iframe {
max-width: 100%;
}

View file

@ -0,0 +1,29 @@
@use './var' as *;
html,
body {
margin: 0;
font-family: $body;
}
* {
box-sizing: border-box;
}
img {
max-width: 100%;
height: auto;
}
p {
line-height: 1.25;
}
.header-logo,
.header-snowpack,
.header-snowpack-subtitle,
.pretty-font,
.version-number {
font-weight: 600;
font-family: $heading;
}

View file

@ -0,0 +1,228 @@
pre,
code {
color: #d4d4d4;
font-size: 14px;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
line-height: 1.5;
direction: ltr;
white-space: pre;
text-align: left;
text-shadow: none;
word-break: normal;
word-spacing: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre::selection,
code::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
pre,
code {
text-shadow: none;
}
}
pre {
margin: 0.5rem 0 16px;
padding: 0.8rem 1rem 0.9rem;
overflow: auto;
background: #282a36;
border-radius: 4px;
}
:not(pre) > code {
padding: 0.1em 0.3em;
color: #db4c69;
background: #f9f2f4;
border-radius: 0.3em;
white-space: pre-wrap;
}
/*********************************************************
* Tokens
*/
.namespace {
opacity: 0.7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #6a9955;
}
.token.punctuation {
color: #d4d4d4;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #b5cea8;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #ce9178;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #d4d4d4;
background: rgb(45, 55, 72);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #c586c0;
}
.token.function {
color: #dcdcaa;
}
.token.regex,
.token.important,
.token.variable {
color: #d16969;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.constant {
color: #9cdcfe;
}
.token.class-name {
color: #4ec9b0;
}
.token.parameter {
color: #9cdcfe;
}
.token.interpolation {
color: #9cdcfe;
}
.token.punctuation.interpolation-punctuation {
color: #569cd6;
}
.token.boolean {
color: #569cd6;
}
.token.property {
color: #9cdcfe;
}
.token.selector {
color: #d7ba7d;
}
.token.tag {
color: #569cd6;
}
.token.attr-name {
color: #9cdcfe;
}
.token.attr-value {
color: #ce9178;
}
.token.entity {
color: #4ec9b0;
cursor: unset;
}
.token.namespace {
color: #4ec9b0;
}
/*********************************************************
* Language Specific
*/
pre[class*='language-javascript'],
code[class*='language-javascript'] {
color: #4ec9b0;
}
pre[class*='language-css'],
code[class*='language-css'] {
color: #ce9178;
}
pre[class*='language-html'],
code[class*='language-html'] {
color: #d4d4d4;
}
.language-html .token.punctuation {
color: #808080;
}
/*********************************************************
* Line highlighting
*/
pre[data-line] {
position: relative;
}
pre > code {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
right: 0;
left: 0;
z-index: 0;
margin-top: 1em;
padding: inherit 0;
line-height: inherit;
white-space: pre;
background: #f7ebc6;
box-shadow: inset 5px 0 0 #f7d87c;
pointer-events: none;
}
pre[class*='language-bash'] .token.function {
color: #d4d4d4;
}
.token.comment {
color: #fff7;
}

View file

@ -0,0 +1,87 @@
@use './var' as *;
.content {
a {
color: #0366d6;
text-decoration: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
font-family: $heading;
line-height: 1.2;
}
h1 {
font-size: 3em;
@media (min-width: 600px) {
font-size: 3.25em;
}
}
h2 {
font-size: 2.75em;
@media (min-width: 600px) {
font-size: 3em;
}
}
h3 {
font-size: 2em;
@media (min-width: 600px) {
font-size: 2.25em;
}
}
h4 {
font-size: 1em;
@media (min-width: 600px) {
font-size: 1.2em;
}
}
ul li,
ol li {
margin-top: 0.5em;
margin-bottom: 0.5em;
line-height: 1.6;
}
p {
margin-top: 1.5em;
margin-bottom: 1.5em;
line-height: 1.7;
}
blockquote {
margin: 0;
padding: 1rem 2rem;
color: #2e5e82;
font-weight: 300;
font-size: 1.1em;
background: linear-gradient(-30deg, #c9efd8, #f9ddff);
border-left: none;
@media (min-width: $breakpoint-m) {
border-radius: 0.5rem;
box-shadow: 0 1px 2px rgba(50, 127, 177, 0.1),
0 1.5rem 3rem rgba(50, 125, 177, 0.1);
}
& *:first-child {
margin-top: 0;
}
& *:last-child {
margin-bottom: 0;
}
}
}

View file

@ -0,0 +1,41 @@
// typography
$body: -apple-system, 'BlinkMacSystemFont', 'Helvetica Neue', 'Segoe UI',
'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', sans-serif;
$heading: 'Overpass', $body;
$code: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;
// breakpoints
$breakpoint-m: 800px;
$breakpoint-l: 1240px;
// nav bar height mobile
$nav-height: 56px;
// colors
$blue: #0a5e9d;
$dark-blue: #2e5e82;
$lightest-blue: #cfe2f2;
$orange: #fa6400;
$color-primary: $dark-blue;
$color-secondary: $blue;
$color-light: $lightest-blue;
$color-strong-contrast: $orange;
$grey: #717171;
$dark-grey: #393939;
$light-grey: #c1c1c1;
$darkest-grey: #333;
$white: #fff;
$light-rainbow-blue: #c9efd8;
$light-rainbow-pink: #f9ddff;
$rainbow-purple: #b224d0;
$rainbow-blue: #267dd6;
$rainbow-green: #24bf62;
$rainbow-yellow: #f0db4f;
$layers: (
'base': 1,
'nav-view': 9,
'nav': 10,
);

View file

@ -0,0 +1,31 @@
// GitHub markdown styles
@use './_github-markdown';
// Syntax highlighting
@use './_prism';
// Global styles
@use './_globals';
// Typography
@use './_typography';
// Components
@use './components/container';
@use './components/hero';
@use './components/icon';
@use './components/logo';
@use './components/nav';
@use './components/old';
@use './components/toc';
@use './components/view';
@use './components/search';
@use './components/feature-list';
@use './components/button';
@use './components/copy-button';
@use './components/card-grid';
// Pages
@use './pages/plugins';
@import 'docsearch.js/dist/cdn/docsearch.min.css';

View file

@ -0,0 +1,42 @@
@use '../var' as *;
@use '../animations' as *;
.button {
box-sizing: border-box;
margin-top: 2px;
margin-bottom: 2px;
padding: 0.3em 1.5em;
font-weight: bold;
font-size: 100%;
font-size: 22px;
font-family: inherit;
font-family: 'Overpass', sans-serif;
white-space: nowrap;
text-align: center;
text-decoration: none;
vertical-align: middle;
background-color: #fefefe;
border: 1px solid #666;
border-radius: 4px;
cursor: pointer;
text-decoration: none !important;
user-select: none;
@include animation-hover-pop;
&-primary {
color: #fff;
background: linear-gradient(45deg, #24bf62, #267dd6, #b224d0);
}
}
a.button {
text-decoration: none !important;
&-primary {
color: #fff;
}
}
.button-container {
display: flex;
flex-wrap: wrap;
}

View file

@ -0,0 +1,105 @@
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
}
.card-grid-3 {
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.card-grid-4 {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.discord-banner {
grid-column: 1 / -1;
border: 1px solid #2e2077;
background-color: #545eec;
display: flex;
align-items: center;
font-size: 16px;
color: white;
font-weight: 500;
padding: 1.25rem;
margin: 1.5rem 0 1rem;
background: #545eec;
box-shadow: 6px 6px 20px #4750c966, -6px -6px 20px #616cff66;
}
.discord-banner > * {
display: block;
}
@media (max-width: 700px) {
.discord-banner {
flex-direction: column;
}
.discord-banner > div {
margin-top: 1rem;
}
}
.card {
display: flex;
grid-column: span 1;
overflow: hidden;
font-family: Open Sans, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI,
Roboto, sans-serif;
color: #1a202c;
-webkit-font-smoothing: antialiased;
box-sizing: border-box;
border: 1px solid #e2e8f0;
}
.card:hover {
border-color: #2a85ca;
box-shadow: 0 2px 2px 0 rgba(46, 94, 130, 0.4);
}
.card:hover .card-image {
opacity: 0.9;
}
.card-image {
width: 100%;
object-fit: cover;
opacity: 0.8;
}
.card-image-small {
flex-grow: 1;
height: 120px;
}
.card-image-large {
height: 200px;
}
.card-text {
padding: 1rem;
}
.card-title {
margin: 0 0 0.25rem 0;
font-weight: 600;
font-size: 20px;
font-family: 'Overpass';
line-height: 1.1;
}
.content-title {
font-family: 'Overpass';
}
.card:nth-child(4n + 0) .card-image {
background: #f2709c;
background: linear-gradient(30deg, #ff9472, #f2709c);
}
.card:nth-child(4n + 1) .card-image {
background: #fbd3e9;
background: linear-gradient(30deg, #bb377d, #fbd3e9);
}
.card:nth-child(4n + 2) .card-image {
background: #b993d6;
background: linear-gradient(30deg, #8ca6db, #b993d6);
}
.card:nth-child(4n + 3) .card-image {
background: #00d2ff;
background: linear-gradient(30deg, #3a7bd5, #00d2ff);
}

View file

@ -0,0 +1,5 @@
.container {
max-width: 1400px;
padding-right: 1.5rem;
padding-left: 1.5rem;
}

View file

@ -0,0 +1,48 @@
@use '../var' as *;
@use '../animations' as *;
.copy-button {
display: flex;
flex: none;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-width: 292px;
padding: 0.75rem 1.25rem;
padding-bottom: 0.75rem;
font-size: 100%;
font-family: Menlo, ui-monospace, SFMono-Regular, Monaco, Consolas,
Liberation Mono, Courier New, monospace;
line-height: 1.5rem;
background-color: white;
border: 1px solid #0006;
border-radius: 4px;
cursor: pointer;
@include animation-copy-button;
svg,
.faded {
color: #ccc;
transition: color 0.1s ease-out;
}
}
// I don't think this is used
.copy-button.active {
animation: pulse 0.5s;
animation-iteration-count: 1;
svg {
color: #ccc;
}
}
@keyframes pulse {
0% {
color: #2a85ca;
border-color: #2a85ca;
}
100% {
}
}

View file

@ -0,0 +1,46 @@
@use '../var' as *;
// A long feature list in columns
.feature-list {
&-top {
text-align: left;
}
&-bullets {
display: grid;
grid-row-gap: 1em;
grid-column-gap: 2em;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
margin: 2.5em 0 !important;
padding: .1em !important;
list-style: none;
h3 {
margin: 0 0 .25em 0;
font-size: 1.25em;
}
}
&-bullet {
display: list-item;
padding: 0.25em;
border-radius: 4px;
&::before {
display: block;
float: left;
margin-right: 6px;
color: green !important;
content: '';
}
}
&-buttons {
margin: 2em 0;
text-align: center;
}
&-button {
display: inline-block;
margin: 0.5em;
}
}

View file

@ -0,0 +1,108 @@
@use '../var' as *;
.hero {
display: flex;
align-items: center;
justify-content: center;
height: 50vh;
min-height: 20rem;
max-height: 30rem;
color: #111;
line-height: 1.5;
background: #2a85ca40;
background-image: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512' title='mountain' class='logo' fill='%23FFFB'%3E%3Cpath d='M634.92 462.7l-288-448C341.03 5.54 330.89 0 320 0s-21.03 5.54-26.92 14.7l-288 448a32.001 32.001 0 0 0-1.17 32.64A32.004 32.004 0 0 0 32 512h576c11.71 0 22.48-6.39 28.09-16.67a31.983 31.983 0 0 0-1.17-32.63zM320 91.18L405.39 224H320l-64 64-38.06-38.06L320 91.18z' /%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: calc(100% + 100px) calc(100% + 64px);
background-size: 50%;
border-bottom: 1px solid #0003;
//margin-top: $nav-height;
@media (min-width: $breakpoint-l) {
margin: 0;
}
a {
color: white;
}
> svg {
display: block;
margin: auto;
opacity: 0.9;
}
.logo {
position: absolute;
right: 0;
width: 100%;
}
.logo path {
fill: #fff;
}
.section {
padding: 1rem * 2;
}
}
.hero-cta {
display: flex;
justify-content: center;
margin: 1.5rem auto 0;
}
.header-link {
padding-left: 2px;
}
.header-logo {
display: flex;
align-items: center;
float: left;
margin: 0 -20px 0 0;
font-weight: bold;
font-size: 36px;
line-height: 1;
@media (min-width: $breakpoint-m) {
margin: 0 20px 0 0;
}
svg {
width: 31px;
height: 31px;
margin-right: 8px;
margin-left: 2px;
padding: 0;
color: #fff;
}
}
.header-snowpack {
margin: 0 auto 0.75rem;
font-weight: 900;
font-size: 3.5rem;
line-height: 1;
letter-spacing: -0.045em;
text-align: center;
opacity: 0.9;
@media (min-width: $breakpoint-m) {
max-width: none;
font-size: 5.75rem;
opacity: 1;
}
}
.header-snowpack-subtitle {
margin: 0;
margin: auto;
font-weight: 500;
font-size: 2rem;
line-height: 1;
letter-spacing: -1px;
text-align: center;
@media (min-width: $breakpoint-m) {
font-size: 3rem;
}
}

View file

@ -0,0 +1,21 @@
/**
* Icon
* SVG icons and the like
*/
.snow-icon {
display: block;
width: 1em;
height: 1em;
fill: currentColor;
// ----------
// Modifiers
// ----------
// note: this is just an example; make others!
&__lg {
width: 2em;
height: 2em;
}
}

View file

@ -0,0 +1,29 @@
@use '../var' as *;
/**
* Snowpack Logo
* That iconic mountain you know and love
*/
.snow-logo {
display: inline-flex;
align-items: center;
// -----------
// Components
// -----------
&-icon {
display: block;
width: 1em;
height: 1em;
margin-right: 0.25em;
fill: currentColor;
}
&-type {
font-weight: 700;
font-family: $heading;
letter-spacing: -0.03em;
}
}

View file

@ -0,0 +1,118 @@
@use '../var' as *;
/**
* Top nav
* The thing at the top
*/
.snow-nav {
position: sticky;
top: 0;
z-index: map-get($map: $layers, $key: 'nav');
display: grid;
grid-template-areas:
'mobile logo version'
'search search search';
grid-template-rows: $nav-height $nav-height;
grid-template-columns: 1fr 2fr 1fr;
align-items: center;
height: $nav-height;
padding-right: 0.5rem;
padding-left: 0.625rem;
color: $white;
background-color: $dark-blue;
body.is-nav-open & {
height: $nav-height * 2;
}
@media (min-width: $breakpoint-m) {
display: flex;
height: $nav-height;
padding-left: 0;
}
// -----------
// Components
// -----------
&-link {
display: inline-block;
padding: 0.5em;
color: $white;
font-weight: 500;
text-decoration: none;
opacity: 0.7;
transition: opacity 150ms linear;
&:focus,
&:hover {
opacity: 1;
}
&__desktop {
display: none;
@media (min-width: $breakpoint-m) {
display: block;
}
}
}
&-logo {
display: flex;
grid-area: logo;
justify-content: center;
padding: 0.5rem;
color: $white;
font-size: 24px;
text-decoration: none;
@media (min-width: $breakpoint-m) {
justify-content: flex-start;
padding: 0.5rem 1.25rem;
}
}
&-mobile-open {
display: flex;
grid-area: mobile;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
padding: 0;
color: $white;
font-size: 16px;
background: none;
border: none;
appearance: none;
@media (min-width: $breakpoint-m) {
display: none;
}
}
&-version {
grid-area: version;
margin-left: 0.5em;
font-size: 0.8em;
font-family: $code;
text-align: right;
@media (min-width: $breakpoint-m) {
text-align: left;
&::after {
display: inline-block;
width: 1px;
height: 1.5em;
margin-left: 0.5em;
vertical-align: -25%;
background-color: rgba($white, 0.25);
content: '';
}
}
}
}

View file

@ -0,0 +1,247 @@
@use '../var' as *;
body {
&.is-nav-open {
overflow: hidden;
}
}
// Notification
.notification {
padding: 0.5rem;
color: white;
font-weight: bold;
background-color: #b224d0;
a {
color: white;
text-decoration: underline;
}
}
// Stub
.stub {
padding: 0.5rem;
font-weight: bold;
background-color: #f0db4f;
a {
text-decoration: underline;
}
}
// Company logos
img.company-logo {
flex: 100%;
height: 56px;
border: none !important;
box-shadow: none !important;
}
.company-logos {
display: flex;
flex-wrap: wrap;
margin-top: -4px;
margin-bottom: 24px;
> a {
flex-shrink: 0;
margin: 0 4px;
padding: 10px;
color: #e74c3c;
text-decoration: none;
opacity: 0.8;
filter: grayscale(0.1);
&:hover {
font-weight: normal;
text-decoration: underline;
opacity: 1;
filter: grayscale(0);
}
}
> .add-company-button,
> .add-star-button {
display: flex;
align-items: center;
color: #555;
font-weight: normal;
opacity: 1;
filter: grayscale(0);
}
> .add-company-button {
color: #e74c3c;
border-color: #e74c3c;
}
}
// github button
.github-button {
display: none;
}
// grid list
.grid-list ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
font-size: 18px;
font-family: Overpass;
font-style: italic;
list-style: none;
}
// highlight
.highlight,
.highlight-container {
position: relative;
font-weight: bold;
}
.highlight-container {
display: inline-block;
}
.highlight-1 {
color: #2ecc71;
}
.highlight-2 {
color: #be2edd;
}
.highlight-3 {
color: #0c8cec;
}
.highlight-red {
color: #2ecc71;
}
.highlight-yellow {
color: #be2edd;
}
.highlight-green {
color: #0c8cec;
}
// Img banner
.img-banner {
display: block;
margin: -3rem -1.5rem 0;
text-align: center;
background: #f0db4f;
border-radius: 4px;
@media (min-width: $breakpoint-m) {
height: 100px;
margin: 0;
}
img {
height: 74px;
border: none;
box-shadow: none;
@media (min-width: $breakpoint-m) {
height: 100px;
}
}
}
//
.content-title {
font-family: $heading;
line-height: 1em;
letter-spacing: -0.05em;
}
h2.content-title {
font-size: 3em;
}
h3.content-title {
font-size: 2em;
}
// Search form
.search-form {
flex-grow: 1;
}
// Hidden mobile
@media (max-width: $breakpoint-m - 1) {
.hidden-mobile {
display: none !important;
}
.version-tag {
display: none;
}
}
// Frame
.frame {
position: relative;
margin: 1rem 0;
padding: 34px 17px 10px 17px;
background-color: #0a5e9d;
border-radius: 10px;
&::before {
position: absolute;
top: 5px;
display: block;
content: url(/img/guides/react/buttons.svg);
}
&::after {
position: absolute;
top: 5px;
right: 17px;
display: block;
content: url(/img/guides/react/snowpack-logo-tiny.svg);
}
}
// Diff markdown blocks
.language-diff .deleted-sign,
.language-diff .inserted-sign .inserted {
user-select: none;
}
.token.inserted {
color: #b5cea8;
}
.token.deleted {
color: #ce9178;
}
// Anchor links on hover
.content {
h2,
h3,
h4 {
.header-link {
margin-left: 0.25rem;
color: #2e5e82;
font-weight: 100;
opacity: 1;
transition: opacity 100ms ease-in-out;
@media (min-width: $breakpoint-m) {
opacity: 0;
}
}
}
h2,
h3,
h4 {
&:hover .header-link {
opacity: 1;
}
}
}

View file

@ -0,0 +1,119 @@
@use '../var' as *;
.search-form {
position: relative;
z-index: 1000;
display: flex;
flex-grow: 1;
grid-area: search;
margin: 0 6px;
> * {
flex-grow: 1;
}
@media (min-width: $breakpoint-m) {
max-width: 600px;
}
@media (max-width: $breakpoint-m - 1) {
& {
display: none;
}
body.is-nav-open & {
display: flex;
}
}
& .sr-only {
display: none;
}
&-hint {
position: absolute;
top: 0;
right: 0;
display: none;
padding: 6px 12px;
color: #c2ced9;
font-size: 16px;
pointer-events: none;
& * {
font-family: $code;
}
&::before {
display: inline-block;
width: 1px;
height: 1.5em;
margin-right: 0.5em;
vertical-align: -35%;
background-color: rgba($white, 0.25);
content: '';
}
@media (min-width: $breakpoint-m) {
display: block;
}
}
&-input {
flex-grow: 1;
box-sizing: border-box;
width: 100%;
margin: 0;
padding-top: 0.5rem;
padding-right: 1rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
overflow: visible;
color: #fff;
font-weight: 500;
font-size: 100%;
font-family: inherit;
line-height: inherit;
background-color: #446e8f;
border-color: rgba($white, 0.25);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
transition-timing-function: ease-in-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
&:focus {
color: white;
border-color: rgba($white, 0.75);
&::placeholder {
color: rgba($white, 0.8);
}
}
&::placeholder {
color: #c2ced9;
}
&__desktop {
display: none;
@media (min-width: $breakpoint-m) {
display: block;
}
}
}
}
.algolia-autocomplete .ds-dropdown-menu {
@media (max-width: $breakpoint-m - 1) {
width: 100%;
min-width: inherit;
max-width: inherit;
margin-top: 0.5rem;
}
}
.algolia-autocomplete .ds-dropdown-menu::before {
display: none !important;
}

View file

@ -0,0 +1,132 @@
@use '../var' as *;
/**
* Table of Contents (toc)
* The left-hand sidebar
*/
$top-padding: 24px;
%toc-link {
position: relative;
display: block;
color: $white;
text-decoration: none;
border: none;
transition: color 0.3s;
@media (min-width: $breakpoint-m) {
color: $grey;
}
&::before {
position: absolute;
top: -2px;
left: -19px;
font-weight: 400;
font-size: 26px;
line-height: 1;
opacity: 0;
transition: left .14s ease-out;
content: "";
}
&:hover {
text-decoration: underline;
}
&.active {
color: #0c8cec;
text-decoration: underline;
&::before {
left: -17px;
opacity: 1;
}
}
}
.snow-toc {
transition: padding 0.2s ease-out, opacity 0.2s ease-in-out;
// -----------
// Components
// -----------
&-contents {
margin: 0;
padding: 0;
line-height: 1.8;
list-style: none;
}
&-link {
@extend %toc-link;
}
&-section {
+ .snow-toc-section {
margin-top: 1.5rem;
}
&-header {
margin-top: 0;
margin-bottom: 8px;
color: rgba($white, 0.6);
font-weight: 600;
font-size: 20px;
font-family: $heading;
line-height: 1.2em;
@media (min-width: $breakpoint-m) {
color: $dark-grey;
}
}
&-items {
margin: 0;
padding: 0;
list-style: none;
}
}
// ----------
// Modifiers
// ----------
&__subnav {
position: static;
z-index: 1;
padding-top: 2rem;
.snow-toc-section-header {
color: $dark-grey;
}
hr {
display: block;
height: 1px;
margin: 1rem 0;
background-color: $light-grey;
border: none;
appearance: none;
}
ol {
margin: 0;
padding: 0;
list-style: none;
}
li {
line-height: 1.8;
}
a {
@extend %toc-link;
color: $grey;
}
}
}

View file

@ -0,0 +1,152 @@
@use '../var' as *;
/**
* Main document view
*/
$top-padding: 24px;
// Document view
.snow-view__docs {
grid-gap: 1.5rem;
grid-template-areas: 'subnav' 'main';
grid-template-columns: auto;
@media (min-width: $breakpoint-m) {
display: grid;
grid-template-areas:
'nav subnav'
'nav main';
grid-template-columns: 16rem minmax(auto, $breakpoint-m);
}
@media (min-width: $breakpoint-l) {
display: grid;
grid-template-areas: 'nav main subnav';
grid-template-columns: 16rem auto 20rem;
}
&.is-home {
margin-top: 1.5rem;
margin-bottom: 3rem;
.snow-view-nav {
padding-top: 1.5rem;
@media (min-width: $breakpoint-m) {
position: static;
max-height: inherit;
}
}
}
&.is-full {
.snow-view-main {
grid-row-start: main;
grid-row-end: main;
grid-column-start: main;
grid-column-end: subnav;
}
}
&.has-subnav {
.snow-view-main .content-title {
display: block;
@media (max-width: $breakpoint-l) {
display: none;
}
}
}
.content-body {
h2,
h3 {
margin-top: -50px;
padding-top: 80px;
margin-bottom: 20px;
}
}
// -----------
// Components
// -----------
.snow-view-nav {
position: fixed;
top: $nav-height * 2;
right: 0;
bottom: 0;
left: 0;
z-index: map-get($map: $layers, $key: 'nav-view');
display: none;
grid-area: nav;
width: 100%;
padding: 1rem 1.5rem;
overflow: auto;
color: $white;
background: $dark-blue;
body.is-nav-open & {
display: block;
}
}
.snow-view-main {
grid-area: main;
min-width: 0;
padding: $top-padding 0 $top-padding 0;
}
.snow-view-subnav {
grid-area: subnav;
padding: 90px 0 $top-padding 0;
overflow: auto;
@media (max-width: $breakpoint-l) {
padding-top: $top-padding;
}
.content-title {
display: none;
@media (max-width: $breakpoint-l) {
display: block;
}
}
}
.snow-view-nav {
@media (min-width: $breakpoint-m) {
position: sticky;
top: $nav-height;
z-index: 1;
display: block;
max-height: calc(100vh - #{$nav-height});
color: inherit;
background: none;
-webkit-overflow-scrolling: touch;
}
@media (max-width: $breakpoint-m - 1) {
padding-bottom: 2rem;
&.is-mobile-hidden {
overflow: hidden;
}
&.is-mobile-hidden .snow-toc {
padding-top: 0.5rem;
opacity: 0;
}
}
}
.snow-view-subnav {
@media (min-width: $breakpoint-l) {
position: sticky;
top: $nav-height;
z-index: 1;
display: block;
max-height: calc(100vh - #{$nav-height});
color: inherit;
background: none;
-webkit-overflow-scrolling: touch;
}
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,97 @@
.pluginPage {
&-count {
max-width: 600px;
min-height: 24px;
margin: 0.5rem 0 1rem;
color: rgba(black, 0.6);
font-weight: 300;
font-size: 1em;
font-style: italic;
text-align: center;
@media (min-width: 600px) {
font-size: 1.2em;
}
}
&-intro {
margin-top: 1rem;
margin-bottom: 1rem;
line-height: 1.5;
text-align: left;
a {
color: #2e5e82;
}
}
&-search {
display: flex;
width: 100%;
max-width: 600px;
&-input {
flex-grow: 1;
flex-shrink: 0;
box-sizing: border-box;
padding: 0.25em 0.75em;
font-size: 1em;
border-width: 1px 0 1px 1px;
border-radius: 4px 0 0 4px;
box-shadow: 0 0 0 2px rgba(#2e5e82, 0);
transition: box-shadow 150ms linear;
appearance: none;
&:focus {
border-color: #2e5e82;
outline: none;
box-shadow: 0 0 0 2px rgba(#2e5e82, 1);
+ .pluginPage-search-submit {
box-shadow: 0 0 0 2px rgba(#2e5e82, 1);
}
}
}
&-submit {
padding: 0.5em 1em;
color: white;
font-weight: 700;
font-size: 1em;
font-family: 'Overpass', sans-serif;
background-color: #2e5e82;
border: none;
border-radius: 0 4px 4px 0;
box-shadow: 0 0 0 2px rgba(#2e5e82, 0);
transition: box-shadow 150ms linear;
appearance: none;
}
}
&-subheading {
margin-top: -2.5rem;
margin-bottom: 0;
color: #2e5e82;
font-weight: 500;
font-size: 1em;
font-family: 'Overpass', sans-serif;
letter-spacing: -0.02em;
text-align: left;
@media (min-width: 600px) {
font-size: 1.5em;
}
}
&-zero-heading {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
font-weight: 700;
font-size: 1.4em;
text-align: left;
@media (min-width: 600px) {
font-size: 1.5em;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Some files were not shown because too many files have changed in this diff Show more