Svelte PWA Now starter ============= A simple Svelte starter template with:
implement-ts
branch)Make sure Node.js is installed. Clone the repo and
npm install
Start by
npm run dev
and go to localhost:5000.
Build for production using
npm run build
and serve the dist
folder.
Find out more about Tailwind CSS here. To extend Tailwind classes, go to tailwind.config.js
and put in your customizations as an object under extend
.
module.exports = {
theme: {
extend: {
colors: {
backgroundColor: "#f6f5f5",
primaryColor: "#5bd1d7",
secondaryColor: "#248ea9",
accentColor: "#556fb5"
}
}
},
variants: {},
plugins: []
};
For example, the template comes with custom colors which can then be used in html like <div class="backgroundColor"></div>
.
Be sure to indicate postcss
to your style tags like this
<style type="text/postcss"></style>
to see proper syntax highlighting and parsing in VS code.
More details can be found here.
The template includes optional integration with the Now hosting service. The easiest way to get started is to link your Github repo to Now, which allows all pushes to be built and served automatically. The included now.json
tells Now to automatically run the rollup build command (via package.json
) and serve the dist
folder.
If applicable, be sure to include your custom web domain under alias
to tell Now to automatically alias your output to your domain.
{
"version": 2,
"alias": "https://ADD-DOMAIN-NAME-HERE",
"builds": [
{
"src": "package.json",
"use": "@now/static-build"
}
],
"routes": [
{
"src": "/(.*)",
"headers": { "cache-control": "max-age=0,must-revalidate" },
"dest": "dist/$1"
}
]
}
There is also a .nowignore
file which tells Now to ignore specified files, similar to .gitignore
.
More info on Now integration with Github can be found here.
If you do not need Now integration, feel free to remove now.json
and .nowignore
.
Cypress is included in the template. Simply use npm run test
to start cypress integration testing. More info about writing cypress tests can be found at cypress.io.
By default, Rollup does not copy static folders to dist
when building. If you have folders with static assets like data files or images, put the folder path in rollup.config.js
like so.
...
import copy from "rollup-plugin-copy-assets";
const production = !process.env.ROLLUP_WATCH;
export default {
...
plugins: [
...
copy({
assets: ["src/assets", "src/MORE-STATIC-FOLDERS"]
}),
...
]
...
};
The commonly required icons are at src/assets
. Be sure to use the same filenames as they are referred to in the metadata at dist/index.html
. Tip: Use Real Favicon Generator which automatically creates all the required icon sizes, and simply unzip the generated asset bundle into src/assets
.
The icons are all utilized in the <meta></meta>
tags for Facebook, Twitter and Google indexing among others. Be sure to customize your app title and descriptions in all the tags.
This template includes a basic service worker at dist/service-worker.js
which simply checks against the currently held cache and loads from network if required. Feel free to further customize it for your needs.
Customize dist/manifest.json
with your PWA's info for installation. Note that the manifest requires a 512x512 icon which is not generated by Real Favicon Generator. You have to manually create that one on your own using something like https://onlinepngtools.com/resize-png.
A very basic router is included as a renderless component at src/components/Router.svelte
. It simply uses the browser History API to manage the browser history stack and updating the browser url. To use, you must manually do something like
window.history.pushState(
{
state1: newValue1,
state2: newValue2
},
null,
"?state1=" + newValue1 + "&state2=" + newValue2
);
in the component where the state was updated, which will then change your browser window url to show the new state for your SPA.
The router also takes care of parsing incoming url parameters, which you must then manually pass to your state store (in this case src/store/store.js
).
window.onload = function() {
if (window.location.search.length > 0) {
const params = window.location.search.substr(1);
params.split("&").forEach(param => {
const key = param.split("=")[0];
const value = parseFloat(param.split("=")[1]);
console.log(`Parameter of ${key} is ${value}`);
});
//UPDATE STATE WITH THESE PARAMS
updateState();
}
};
This article probably explains it much better.
MIT