├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── src ├── app.js ├── index.handlebars ├── partials │ ├── header.handlebars │ └── newsletter.handlebars ├── static │ └── logo.png └── styles │ └── main.scss └── webpack ├── webpack.common.js ├── webpack.dev.js └── webpack.prod.js /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Webpack Workflow 2 | 3 | This is a webpack configuration for development Websites with HTML, Handlebars, Javacript, CSS and Sass, using a live server and other features that webpack provides to other libraries and frameworks like React, Vue or Angular. 4 | 5 | A tipical website needs: 6 | - CSS or Sass styles 7 | - A template engine (like Handlebars) 8 | - Import and install Javascript files (like npm modules) 9 | - Custom Fonts 10 | 11 | ## Installation 12 | 13 | Install dependencies 14 | ``` 15 | npm install 16 | ``` 17 | 18 | To start the development server 19 | ``` 20 | npm run dev 21 | ``` 22 | 23 | To build your project for production use: 24 | ``` 25 | npm run build 26 | ``` 27 | 28 | ## Considerations 29 | - the entry of our files is inside the folder: `src` 30 | - the webpack folder is to setting webpack files for development and production 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-workflow", 3 | "version": "1.0.0", 4 | "description": "A tipical website needs: - CSS styles - A template engine - Javascript files - Custom Fonts", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "rimraf dist && webpack --config ./webpack/webpack.prod.js", 8 | "start": "webpack serve --config ./webpack/webpack.dev.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "autoprefixer": "^10.3.1", 15 | "css-loader": "^6.2.0", 16 | "file-loader": "^6.2.0", 17 | "handlebars": "^4.7.7", 18 | "handlebars-loader": "^1.7.1", 19 | "html-webpack-plugin": "^5.3.2", 20 | "image-webpack-loader": "^7.0.1", 21 | "mini-css-extract-plugin": "^2.2.0", 22 | "postcss-loader": "^6.1.1", 23 | "sass-loader": "^12.1.0", 24 | "webpack": "^5.48.0", 25 | "webpack-cli": "^4.7.2", 26 | "webpack-dev-server": "^3.11.2", 27 | "webpack-merge": "^5.8.0" 28 | }, 29 | "dependencies": { 30 | "rimraf": "^3.0.2", 31 | "sass": "^1.37.5", 32 | "toastify-js": "^1.11.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import Toastify from "toastify-js"; 2 | import "toastify-js/src/toastify.css"; 3 | 4 | import "./styles/main.scss"; 5 | import "./static/logo.png"; 6 | 7 | const newsletterForm = document.querySelector("#newsletter"); 8 | const newsletterInput = document.querySelector("#newsletter-input"); 9 | 10 | newsletterForm.addEventListener("submit", (event) => { 11 | event.preventDefault(); 12 | 13 | console.log(newsletterInput.value); 14 | 15 | Toastify({ 16 | text: `Gracias ${newsletterInput.value} por registrarte!`, 17 | className: "info", 18 | }).showToast(); 19 | }); 20 | -------------------------------------------------------------------------------- /src/index.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{htmlWebpackPlugin.options.title}} 8 | 9 | 10 | 11 | 12 |

Webpack, Sass & A Template Engine

13 | 14 | 15 | {{> partials/header title=htmlWebpackPlugin.options.title}} 16 | {{> partials/newsletter}} 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/partials/header.handlebars: -------------------------------------------------------------------------------- 1 |
2 | 5 |
-------------------------------------------------------------------------------- /src/partials/newsletter.handlebars: -------------------------------------------------------------------------------- 1 |
2 |

Newsletter

3 |
4 | 12 | 13 |
14 |
-------------------------------------------------------------------------------- /src/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FaztWeb/webpack-simple-workflow/eab582b6ca478a8f4bc0fd55d860a3ffcc4c1b22/src/static/logo.png -------------------------------------------------------------------------------- /src/styles/main.scss: -------------------------------------------------------------------------------- 1 | $bg-dark: #0f0f0f; 2 | $bg-light: #f5f6fa; 3 | 4 | $text-color: $bg-dark; 5 | 6 | body { 7 | padding: 10rem; 8 | text-align: center; 9 | background: $bg-light; 10 | color: $text-color; 11 | font-family: "Roboto", sans-serif; 12 | } 13 | 14 | .bg-white { 15 | background: #ffffff; 16 | color: #0f0f0f; 17 | padding: 40px; 18 | } 19 | 20 | .newsletter-input { 21 | padding: 0.5rem; 22 | font-size: 1.2rem; 23 | } 24 | 25 | .newsletter-btn { 26 | padding: 0.5rem; 27 | font-size: 1.2rem; 28 | background: beige; 29 | border: 1px solid #ccc; 30 | } 31 | -------------------------------------------------------------------------------- /webpack/webpack.common.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 3 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 4 | const autoprefixer = require("autoprefixer"); 5 | 6 | module.exports = { 7 | entry: "./src/app.js", 8 | output: { 9 | path: path.resolve(__dirname, "../dist"), 10 | filename: "js/bundle.js", 11 | }, 12 | devtool: "source-map", 13 | devServer: { 14 | port: 4000, 15 | open: true, 16 | }, 17 | module: { 18 | rules: [ 19 | { 20 | test: /\.handlebars$/, 21 | loader: "handlebars-loader", 22 | }, 23 | { 24 | test: /\.(sa|sc|c)ss$/, 25 | use: [ 26 | MiniCssExtractPlugin.loader, 27 | "css-loader", 28 | { 29 | loader: "postcss-loader", 30 | options: { 31 | postcssOptions: { 32 | plugins: [ 33 | [ 34 | autoprefixer, 35 | { 36 | browsers: "last 2 versions", 37 | }, 38 | ], 39 | ], 40 | }, 41 | }, 42 | }, 43 | "sass-loader", 44 | ], 45 | }, 46 | { 47 | test: /\.(jpg|png|gif)$/, 48 | use: [ 49 | { 50 | loader: "file-loader", 51 | options: { 52 | name: "[name].[ext]", 53 | outputPath: "static/", 54 | useRelativePath: true, 55 | }, 56 | }, 57 | { 58 | loader: "image-webpack-loader", 59 | options: { 60 | mozjpeg: { 61 | progressive: true, 62 | quality: 65, 63 | }, 64 | // optipng.enabled: false will disable optipng 65 | optipng: { 66 | enabled: false, 67 | }, 68 | pngquant: { 69 | quality: [0.65, 0.9], 70 | speed: 4, 71 | }, 72 | gifsicle: { 73 | interlaced: false, 74 | }, 75 | // the webp option will enable WEBP 76 | webp: { 77 | quality: 75, 78 | }, 79 | }, 80 | }, 81 | ], 82 | }, 83 | ], 84 | }, 85 | plugins: [ 86 | new HtmlWebpackPlugin({ 87 | title: "My Cool Website", 88 | template: "./src/index.handlebars", 89 | minify: { 90 | html5: true, 91 | collapseWhitespace: true, 92 | caseSensitive: true, 93 | removeComments: true, 94 | removeEmptyElements: true, 95 | }, 96 | }), 97 | new MiniCssExtractPlugin({ 98 | filename: "css/[name]-styles.css", 99 | chunkFilename: "[id].css", 100 | }), 101 | ], 102 | }; 103 | -------------------------------------------------------------------------------- /webpack/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require("webpack-merge"); 2 | const common = require("./webpack.common"); 3 | 4 | module.exports = merge(common, { 5 | mode: "development", 6 | }); 7 | -------------------------------------------------------------------------------- /webpack/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require("webpack-merge"); 2 | const common = require("./webpack.common"); 3 | 4 | module.exports = merge(common, { 5 | mode: "production", 6 | }); 7 | --------------------------------------------------------------------------------