Webpack frontend web app starter.
Includes: Hosting(gh-pages), Testing(Jest), CICD(Husky, GitHub Actions, Docker), Docs (.adoc), asset handling(Images, Videos, Audios, Fonts...), TypeScript, Sass, TailwindCSS, Web Components(lit), Component Library(shoelace).
The goal is to keep the bundle size as small as possible but still have a decent developer experience.
You could also put them inside of public/static and import them with /<asset_name>, but if you do so, caching might cause you headaches.
(if in public/lib/assets the assets are given a unique hash at build time, if in public/static they are just copied to the root of the build folder)
Shoelace comes with a lot of icons: https://shoelace.style/components/icon.
Reusable elements (components) should be written in TypeScript for type safety.
They are then imported into the <page_name>.html file as follows:
<script type="module" src="bundle.<component-name>.js" defer></script>
<component-name></component-name>If you don't want to use shoelace, you can delete the shoelace folder, delete the following in your webpack.config.js file to reduce the bundle size:
module.exports = {
...
plugins: [
...
new CopyPlugin({
patterns: [
{
from: path.resolve(
__dirname,
'node_modules/@shoelace-style/shoelace/dist/assets',
),
to: path.resolve(__dirname, 'dist/shoelace/assets'),
},
],
}),
...
]
...
}// ShoelaceUI
import '@shoelace-style/shoelace/dist/themes/light.css';
import '@shoelace-style/shoelace/dist/themes/dark.css';
import '@shoelace-style/shoelace/dist/components/<component_name>/<component_name>.js';
import {setBasePath} from '@shoelace-style/shoelace/dist/utilities/base-path.js';
setBasePath('/dist/shoelace');<sl-<component_name>></sl-<component_name>>Page-specific scripts in public/lib/script/pages.
module.exports = {
// INFO: include the script in the build
...
entry: {
...
<page_name>: './public/lib/script/pages/<page_name>.js',
...
},
...
// INFO: import the `script/pages` script in its html template
plugins: [
...
new HtmlWebpackPlugin({
filename: '<page_name>.html',
template: 'public/routes/<page_name>.html',
chunks: ['<page_name>'], // only include the '<page_name>' chunk
}),
...
]
...
}Tailwind extensions in main.css.
Suggestion: Custom CSS in SCSS syntax and BEM.
General custom CSS: style.scss
Component Specific/Custom Class: <component/custom_class>.scss
This is where you put your HTML templates.
Pure HTML only, no JS, and no CSS (except for TailwindCSS classes).
These are moved to the root of the dist folder.
You can write them in AsciiDoc format.
They are automatically converted to HTML and moved to the root of the dist/docs folder.
Don't forget to install the dependencies with --save-dev or -D if they are only used for development.
Production dependencies should be as slim as possible, because that is the goal of using webpack and not some large framework.
(Currently only Express as the NodeJS server and Cors for setting Cors headers for the backend is installed as a production dependency.)
The workflow is defined in .github/workflows/cicd.yml.
It is triggered on every push to the main branch.
jobs:
test-and-build-frontend,push-frontend-to-docker-hub(don't forget to setDOCKERHUB_USERNAMEandDOCKERHUB_TOKENas secrets
in the repo settings AND change the image name in the workflow file to your own (example: <username/app_name:latest>).),publish-frontend-to-github-pages
A pre-commit hook is defined in .husky/pre-commit (formats code).
A pre-push hook is defined in .husky/pre-push (lints code).
You can disable them by adding --no-verify to your commit/push command or by deleting
the .husky folder or you could simply update the file to your liking.
You can find the build config in webpack.config.js.
You can find the Jest config in jest.config.js.
You can write the Jest tests in public/lib/script/__tests__.
Start Webpack development server:
npm devBuild/bundle for production:
npm buildPreview the bundle:
npm preview