svind
is a very simple boilerplate that bundles svelte
, tailwind
, now
and a few extras.
I tried to keep the project as simple as possible but with enough to be able to write code right away without having to think about the boring things.
For the rest of this README
, I'll assume that you're using yarn
, if not change the commands accordingly.
git clone https://github.com/gawlk/svind.git
cd svind
yarn install
Here are the available scripts of this boilerplate.
yarn dev Runs the server in development mode
yarn build Builds your static files
yarn start Starts the server
yarn prod Shortcut for build+start
yarn now Starts a deployment
yarn now:dev Runs now in development mode
yarn now:prod Starts a production deployment
yarn gulp Runs Gulp
yarn test Runs all tests
yarn test:unit Runs Jest tests
yarn test:unit:watch Runs Jest tests in watch mode
yarn test:unit:coverage Runs Jest coverage calculator
yarn test:lint Checks your code with ESLint
yarn test:size Runs a size-limit test
yarn test:ui Runs Cypress tests
yarn test:audit Runs Lighthouse tests
If you prefer to build your project yourself, here's a very detailed guide with all the steps.
First you'll have to download the official Svelte template:
npx degit sveltejs/template PROJECT_NAME
bash PROJECT_NAME
Then install the packages with: yarn install
You might want to have aliases in your project just like in Vue
. For example being able to do src/components/X.svelte
instead of ../../../../../../components/X.svelte
when you're in a deep component.
If so, you can run the following command in your terminal to install a rollup
package that let you do just that: yarn add -D @rollup/plugin-alias
Then add this code in your rollup.config.js
file in the plugins
array before svelte({...})
:
alias({
entries: {
'src': `${__dirname}/src`
},
resolve: [
''
],
}),
Here we just create a shortcut to the root of our source folder.
process.env
variables (optionnal)process.env
variables are very common in webpack
projects. You probably used them in Vue
, React
or even Angular
but here, they don't exist in rollup
.
But ! There is a way to add them. All you have to do is run this command in your terminal:
yarn add -D @rollup/plugin-replace
Then add these code in your rollup.config.js
file in the plugins
array before svelte({...})
:
replace({
'process.browser': true,
'process.env.NODE_ENV': JSON.stringify(mode),
}),
and finally add the following line in the same file just after const production = ! process.env.ROLLUP_WATCH;
:
const mode = production ? 'production' : 'development';
Now, you'll be able to call process.env.NODE_ENV
just like you did with your webpack
projects !
The installation of Tailwind
is a bit harder than those of other CSS libraries but the benefits definitely outweigh the long installation process.
First run this in your terminal to install the packages:
yarn add -D tailwindcss @tailwindcss/ui postcss autoprefixer cssnano postcss-import @fullhuman/postcss-purgecss
Then create a main.css
file in src/
with the following code:
/* purgecss start ignore */
@import "tailwindcss/base";
@import "tailwindcss/components";
/* purgecss end ignore */
@import "tailwindcss/utilities";
Then create a tailwind.config.js
file with the following code:
const defaultTheme = require('tailwindcss/defaultTheme');
const tailwindUI = require('@tailwindcss/ui');
module.exports = {
theme: {
extend: {
fontFamily: {
sans: [
'Inter var',
...defaultTheme.fontFamily.sans,
],
},
},
},
plugins: [
tailwindUI()
]
};
Then you have to create a postcss.config.js
file with the following code:
const production = ! process.env.ROLLUP_WATCH;
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const postcssimport = require('postcss-import');
const purgecss = require('@fullhuman/postcss-purgecss');
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: [
postcssimport(),
tailwindcss,
autoprefixer,
production && purgecss({
content: [
'./public/**/*.html',
'./src/**/*.html',
'./src/**/*.svelte'
],
defaultExtractor: (content) => {
const matches = content.match(/[\w-/.:]+(?<!:)/g) || [];
// Special Svelte case when binding a class
return matches.map(match => match.startsWith('class:') ? match.substr(6) : match);
}
}),
production && cssnano({
preset: 'default',
})
]
};
Finally you'll need to add in your rollup.config.js
file this line: import postcss from 'rollup-plugin-postcss';
And in the same file add the following block of code in the plugins
array before svelte({...})
:
postcss({
extract: 'public/build/bundle.tailwind.css'
}),
Here's a more complete configuration which add support for browser dark and light theme, adds a new Z index and adds two variants, not first child and not last child:
const defaultTheme = require('tailwindcss/defaultTheme');
const tailwindUI = require('@tailwindcss/ui');
module.exports = {
theme: {
extend: {
fontFamily: {
sans: [
'Inter var',
...defaultTheme.fontFamily.sans,
],
},
screens: {
dark: {
raw: '(prefers-color-scheme: dark)',
},
light: {
raw: '(prefers-color-scheme: light)',
},
},
zIndex: {
'-10': '-10',
}
},
},
variants: {
margin: [ 'not-first', 'responsive' ],
},
plugins: [
tailwindUI({
// layout: 'sidebar',
}),
function({ addVariant, e }) {
const variants = [
{
name: 'not-first',
css: 'not(:first-child)',
},
{
name: 'not-last',
css: 'not(:last-child)',
},
];
variants.forEach((variant) => {
addVariant(variant.name, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`${variant.name}${separator}${className}`)}:${variant.css}`
})
})
});
}
]
};
Run yarn add -D now
to add now
to your project. You might want to create to api
folder right away, that's where your serverless functions will be located.
Don't forget to add .now
to your .gitignore
file, that's where now
keeps important and secret data.
Here's a little example of a serverless function
export default (req, res) => {
res.status(200).json(new Date());
};
If you put these code in a file called date.js
in your api
folder, after deploying via now
you'll be able to go to YOUR_ADDRESS/api/date
and get the result of this function. (Here's a live example)
You might want to add a sitemap.xml
to your website but having to maintain can be painful really fast but you could create a function that generates and returns a sitemap each time. Such function could be very useful for website such as blogs for example.
Here's an example, for this to work you'll need to change YOUR_ADDRESS
by your actual address and to launch yarn add -D sitemap
in your terminal.
import {
SitemapStream,
streamToPromise,
} from 'sitemap';
const urls = [
{
url: '/',
},
{
url: '/date',
},
];
export default (req, res) => {
res.setHeader('Content-Type', 'application/xml');
const sitemap = new SitemapStream({
hostname: YOUR_ADDRESS,
});
urls.forEach((url) => {
sitemap.write(url);
});
sitemap.end();
streamToPromise(sitemap)
.then((result) => {
res.status(200).send(result);
})
.catch((error) => {
console.error(error);
res.status(500).end();
});
};
You can see here, that if you want to add a new route from your website to your sitemap you would just need to add an object to the urls
list.
Finally, if you want now
's servers to redirect /sitemap.xml
to /api/sitemap
you need to create a now.json
file if you didn't already and add this:
{
"routes": [
{
"src": "/sitemap.xml",
"dest": "/api/sitemap"
}
]
}
First you'll have to create .github/workflows/nodejs.yml
with the following code
name: Node CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x]
env:
CI: true
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install
run: yarn install
- name: Build
run: yarn build
To add lighthouse to your CI run the following
yarn add -D @lhci/cli
Then add these line to your list of scripts in your package.json
"test:audit": "lhci autorun",
If you made the test
script earlier you might want to add test:audit
to it
Finally add the following to your CI file
- name: Lighthouse audit
run: yarn test:audit