A starter Webpack boilerplate for generating single page applications (SPAs). Node.js v18+ is required. This project utilizes dot-env and cross-env to store and communicate any information prescribed to the build environment.
For the beekeepers:
- PostCSS (Transforming styles)
- TailwindCSS (Utility framework)
- LightningCSS (Transpiling and minifying)
- Import (Inlining @import rules)
- FontMagician (Generating @font-face rules)
- AdvancedVariables (Variables, conditionals and loops)
- EasingGradients (Generating eased gradients)
- PurgeCSS (Removing unused styles)
- StyleLint (Keeping things in order)
For the script kidz:
- SWC (Transpiling and compiling)
- Terser (Uglifying and compressing)
- ESLint (Keeping things in order)
- [Insert testing framework here]
To get started, clone the project and install the dependencies:
> git clone https://github.com/chuntington/webpack-boilerplate.git
> cd webpack-boilerplate/
> npm install
Create a .env
file in the root directory and specify the build environment inside:
NODE_ENV=development
// or
NODE_ENV=production
In the terminal, build the project once, or build on save:
> npm run build
> npm run watch
If you need a local web server, the following will start one and build on save:
> npm run serve
The generated bundle will be placed inside the /dist
directory.
If you need to update the Google Fonts source list, provide a valid API key to the following script:
> npm run google-fonts --apikey=YOUR_API_KEY
Note: When using styled components, the extracted CSS is likely to be invalid according to the preset StyleLint rules. You may modify these rules in stylelint.config.js
to accommodate, or disable linting completely in postcss.config.js
. In addition, it may be helpful to modify or temporarily disable some JavaScript linting rules in eslint.config.js
when utilizing any of the below frameworks.
Below is an example of a Vue.js (3.x) implementation with support for .vue
single file components.
In the terminal:
> npm install vue vue-loader vue-eslint-parser
In webpack.config.js
, import and assign the appropriate loader, plugins and alias:
const { VueLoaderPlugin } = require('vue-loader');
const Webpack = require('webpack');
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
// ...
]
},
plugins: [
// Set compile-time flags when using the esm-bundler
new Webpack.DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: DevMode,
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: DevMode
}),
new VueLoaderPlugin(),
// ...
],
// Override the alias for template interpolation
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js'
}
}
}
In postcss.config.js
, inform Purgecss of any .vue
single file components:
Purgecss({
content: ['./src/**/*.{html,js,vue}'],
// ...
})
In eslint.config.js
, assign the appropriate parser:
module.exports = {
parser: 'vue-eslint-parser',
// ...
}
In src/js/components/ExampleComponent.vue
, create an example single file component:
<template>
<h1 class="example">Example Component</h1>
</template>
<script>
export default {
data: () => ({
show: false
}),
mounted() {
this.show = true;
console.log('Example component mounted.');
}
};
</script>
<style>
.example {
color: gray;
}
</style>
In src/index.html
, declare an app container with the example component nested inside:
<body class="antialiased">
<div id="app">
<example-component></example-component>
</div>
</body>
In src/js/main.js
, import the framework and example component, and initiate a new app instance:
import ExampleComponent from './components/ExampleComponent.vue';
import { createApp } from 'vue';
const vm = createApp({ components: { ExampleComponent } });
vm.mount('#app');
Below is an example of a Vue.js (2.x)
implementation with support for .vue
single file components.
In the terminal:
> npm install vue@2 vue-loader@15 vue-template-compiler@2 vue-eslint-parser@8
In webpack.config.js
, import and assign the appropriate loader, plugin and alias:
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
// ...
]
},
plugins: [
new VueLoaderPlugin(),
// ...
],
// Override the alias for template interpolation
resolve: {
alias: {
vue: 'vue/dist/vue.esm.js'
}
}
}
In postcss.config.js
, inform Purgecss of any .vue
single file components:
Purgecss({
content: ['./src/**/*.{html,js,vue}'],
// ...
})
In eslint.config.js
, assign the appropriate parser:
module.exports = {
parser: 'vue-eslint-parser',
// ...
}
In src/js/components/ExampleComponent.vue
, create an example single file component:
<template>
<h1 class="example">Example Component</h1>
</template>
<script>
export default {
data: () => ({
show: false
}),
mounted() {
this.show = true;
console.log('Example component mounted.');
}
};
</script>
<style>
.example {
color: gray;
}
</style>
In src/index.html
, declare an app container with the example component nested inside:
<body class="antialiased">
<div id="app">
<example-component></example-component>
</div>
</body>
In src/js/main.js
, import the framework and example component, and initiate a new app instance:
import ExampleComponent from './components/ExampleComponent.vue';
import Vue from 'vue';
const vm = new Vue({ components: { ExampleComponent } });
vm.$mount('#app');
Below is an example of a Svelte.js (4.x) implementation with support for .svelte
templates.
In the terminal:
> npm install svelte svelte-loader
In webpack.config.js
, assign the appropriate loader and resolve configuration:
module.exports = {
module: {
rules: [
{
test: /\.svelte$/,
use: {
loader: 'svelte-loader',
options: {
// emitCss: true
}
}
},
{
test: /node_modules\/svelte\/.*\.mjs$/,
resolve: {
fullySpecified: false
}
},
// ...
]
},
resolve: {
alias: {
svelte: Path.resolve('node_modules', 'svelte/src/runtime')
},
conditionNames: ['svelte', 'browser', 'import'],
extensions: ['.mjs', '.js', '.svelte'],
mainFields: ['svelte', 'browser', 'module', 'main']
}
}
In postcss.config.js
, inform Purgecss of any .svelte
templates:
Purgecss({
content: ['./src/**/*.{html,js,svelte}'],
// ...
})
In src/js/components/App.svelte
, create an example styled component template:
<script>
import { onMount } from 'svelte';
export let name;
onMount(() => {
console.log(`${name} mounted.`);
});
</script>
<h1 class="example">{name}</h1>
<style>
.example {
color: gray;
}
</style>
In src/index.html
, declare the component container:
<body class="antialiased">
<div id="app"></div>
</body>
In src/js/main.js
, import the component and initiate a new instance:
import App from './components/App.svelte';
const app = new App({
target: document.getElementById('app'),
props: { name: 'Example App' }
});
window.app = app;
Below is an example of a htmx (1.x) implementation.
In the terminal:
> npm install htmx.org
In webpack.config.js
, assign the appropriate resolve configuration:
module.exports = {
resolve: {
alias: {
htmx: 'htmx.org/dist/htmx.min.js'
}
}
}
In src/index.html
, declare an app container:
<body hx-on="htmx:load: console.log('Example App mounted.')" class="antialiased">
<h1>Example App</h1>
</body>
In src/js/main.js
, import the framework:
import 'htmx';
Below is an example of a React.js (18.x) implementation.
In the terminal:
> npm install eslint-plugin-react react react-dom
In .swcrc
, enable the appropriate parser and transform options:
{
"jsc": {
"parser": {
"jsx": true,
// ...
},
"transform": {
"react": {
"runtime": "automatic"
}
}
},
// ...
}
In eslint.config.js
, enable the appropriate parser options and plugin:
module.exports = {
parserOptions: {
'ecmaFeatures': {
'jsx': true
},
// ...
},
plugins: ['react'],
// ...
}
In src/js/components/ExampleComponent.js
, create an example component template:
import React from 'react';
class ExampleComponent extends React.Component {
render() {
return <h1>Example Component</h1>;
}
componentDidMount() {
console.log('Example component mounted.');
}
}
export default ExampleComponent;
In src/index.html
, declare an app container:
<body class="antialiased">
<div id="app"></div>
</body>
In src/js/main.js
, import the framework and example component, and initiate a new app instance:
import React from 'react';
import ReactDOM from 'react-dom';
import ExampleComponent from './components/ExampleComponent.js';
class App extends React.Component {
render() {
return <ExampleComponent/>;
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
🎩 Voila!