Webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
Author: Vedees | Youtube guide (ru)
- separated configs for
devandprod typescript / javascriptfull supportsass / cssfull support- full babel & postcss setup
- 0 dependencies
- the best optimization for your production
- easy webpack and babel customization
Everybody knows that developing runs on coffee! Thanks for your support!
# Download repository:
git clone https://github.com/vedees/webpack-template webpack-template
# Go to the app:
cd webpack-template
# Install dependencies:
# npm install
# or:
yarn
# Server with hot reload at http://localhost:8084/
# npm run start
# or:
yarn start
# Output will be at dist/ folder
# npm run build
# or:
yarn buildpublic/*.html- HTML filessrc/app- core appsrc/shared- shared filessrc/shared/img- images folder (! for html calls use correct path:static/img/some.jpg)src/shared/misc- misc files (i.g. favicon, sitemap, etc.)src/index.ts- main app entity
Configs:
/babel-defines.js- config for babel/webpack/webpack-pages.js- config for html pages/webpack/webpack-defines.js- config for entire webpack
Main entry point:
src/app/index.ts- core entry point
Core webpack config from /webpack/webpack-defines.js:
const PATHS = {
// path to the src dir
src: path.join(__dirname, '../src'),
// path to the output dir
dist: path.join(__dirname, '../dist'),
// path to the public files (html files)
public: path.join(__dirname, '../public'),
// path to output sub dir (js, css, fonts, etc.)
assets: 'assets/',
// path to output sub dir (img, icons, etc.)
static: 'static/'
}Pages config from /webpack/webpack-pages.js:
const pages = [
{
// page title
title: 'Home page',
// template name `public/index.html`
template: 'index.html',
// output filename `dist/index.html`
filename: 'index.html',
// other options can be here
},
{
title: 'About page',
template: 'about.html',
filename: 'about.html',
}
]You can pass a hash of configuration options to html-webpack-plugin.
Allowed values are as follows: https://github.com/jantimon/html-webpack-plugin#options
In case if you don't want to use Pages config:
- Create another html file in
./public - Go to
./webpack/webpack.common.js - Add new page to the config:
// index page:
new HtmlWebpackPlugin({
title: 'Home page',
favicon: defines.src + '/shared/misc/favicon.ico',
template: defines.public + '/index.html', // public/index.html page
filename: 'index.html' // output file
}),
// about page:
new HtmlWebpackPlugin({
title: 'About page',
favicon: defines.src + '/shared/misc/favicon.ico',
template: defines.public + '/about.html', // public/about.html page
filename: 'about.html' // output file
}),Install it:
yarn add bootstrap react react-domImport libs to src/app/index.ts:
// React example
import React from 'react'
// Bootstrap example (with custom js imports)
import Bootstrap from 'bootstrap/dist/js/bootstrap.min.js'
import 'bootstrap/dist/js/bootstrap.min.js'Import libs to src/app/index.scss:
// sass lib import example:
@import '../../node_modules/spinners/stylesheets/spinners';
// css lib import example:
@import '../../node_modules/flickity/dist/flickity.css';Here's an example with React + i18n Provider.
Install react:
yarn add react react-domCreate div with id app in public/index.html:
<div id="app"></div>Init the app in src/app/index.ts:
import React from 'react'
import { createRoot } from 'react-dom/client'
// app styles
import './index.scss'
// local providers:
import { I18nProvider } from './providers/I18nProvider'
const container = document.getElementById('app') as HTMLElement
const root = createRoot(container)
root.render(
<React.StrictMode>
<I18nProvider>...</I18nProvider>
</React.StrictMode>
)File src/app/providers/I18nProvider.tsx:
import React, { FC, PropsWithChildren } from 'react'
export const I18nProvider: FC<PropsWithChildren> = ({ children }) => {
// ...
return <I18n locale={detectedLocale}>{children}</I18n>
}Install vue:
yarn add vueInit the app in src/app/index.ts:
// vue example (react one is above):
const app = new Vue({
el: '#app'
})Create div with id app in public/index.html:
<div id="app"></div>Create your component in src/app/components/.
HTML Usage (in *.html files):
Init component in src/app/index.ts:
Vue.component('example-component', require('./components/Example.vue').default)In any html files:
<example-component />VUE Usage (in *.vue files):
Import component:
import ExampleComponent from '@/components/Example.vue'Init component (template):
<Example />Register component (script):
components: {
Example: ExampleComponent
}Connect fonts to public/index.html:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500&display=swap" rel="stylesheet" />Change the font in src/app/styles/body.scss:
html {
font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, 'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol' !important;
}In case if you don't want to use Google Fonts:
- Download fonts
- Add fonts to the (i.g.
/src/shared/fonts/OpenSans/...).
Then add @font-face in some .scss file (i.g. /src/app/styles/font.scss):
// Open Sans example:
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: swap;
src: url('/static/fonts/OpenSans/Open-Sans.woff2') format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}The last step is to copy these fonts into the /dist folder every time you build the project.
Add another config for CopyWebpackPlugin to /webpack/webpack.common.js:
new CopyWebpackPlugin({
// ...
// `shared/fonts` to `dist/static/fonts`
{
from: `${defines.src}/shared/fonts`,
to: `${defines.dist}/${defines.static}/fonts`
},
})Change the font in src/app/styles/body.scss:
html {
font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, 'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol' !important;
}Copyright (c) 2018-present, Evgenii Vedegis