tmpl-cli
api
docs
env
git
hbs
hbs init
html
husky
jest
lintstaged
lisp
node
prettier
python
react
readme
schema
style
util
vue
web

$ tmpl hbs init

Inits new hbs project.

Files

project
└─src
└──partials
└───headMeta.hbs
└───header.hbs
└──styles
└───__import.css
└───main.css
└───reset.css
└──index.hbs
└──index.js
└─.babelrc
└─package.json
└─webpack.config.js

headMeta.hbs

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{{#if htmlWebpackPlugin.options.isNoIndex}}
<meta name="robots" content="noindex">
{{/if}}
<title>Project</title>
</head>

header.hbs

<h1>Header</h1>

__import.css

@import "./reset.css";
@import "./main.css";

main.css

reset.css

html {
box-sizing: border-box;
font-size: 16px;
color: #212121;
font-family: Arial, Helvetica, sans-serif;
font-weight: normal;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
ol,
ul {
margin: 0;
padding: 0;
}
ol,
ul {
list-style: none;
}
img {
max-width: 100%;
height: auto;
}
input {
padding: 0.5rem
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
button {
cursor: pointer;
}

index.hbs

{{> headMeta}}
<body>
{{> header/header}}
{{htmlWebpackPlugin.options.message}}
</body>
</html>

index.js

import "./styles/__import.css";
console.log("Web Project Working");

.babelrc

{
"presets": ["@babel/preset-env"]
}

package.json

{
"name": "project",
"version": "0.0.0",
"description": "",
"browserslist": [
"last 2 versions",
"IE 11"
],
"scripts": {
"build": "webpack",
"start": "webpack-dev-server"
},
"keywords": [],
"author": "developer<developer@developer.dev>",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"@babel/core": "^7.12.13",
"@babel/preset-env": "^7.12.13",
"autoprefixer": "^10.2.4",
"babel-core": "^7.0.0-bridge.0",
"babel-loader": "^8.2.2",
"css-loader": "^5.0.1",
"cssnano": "^4.1.10",
"handlebars": "^4.7.6",
"handlebars-loader": "^1.7.1",
"html-webpack-plugin": "^5.0.0",
"mini-css-extract-plugin": "^1.3.5",
"postcss-import": "^14.0.0",
"postcss-loader": "^5.0.0",
"postcss-preset-env": "^6.7.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack": "^4.44.2"
}
}

webpack.config.js

// Tools
const path = require("path");
// Plugins
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// Variables - Directory Target
const dir = path.resolve(__dirname);
const srcDir = path.join(dir, "src");
const distDir = path.join(dir, "dist");
const nodeModulesDir = path.join(dir, "node_modules");
// Variables - File Targets
const srcIndex = "index.js";
const srcTemplate = "index.hbs";
const distHtml = "index.html";
// Variables - Environment
const webpackMode = process.env.NODE_ENV === "production" ? "production" : "development";
const isProduction = webpackMode === "production";
// Variables - Other
const devPort = process.env.DEV_SERVER_PORT || 8080;
// Main Webpack Config
module.exports = {
target: "web",
mode: webpackMode,
entry: path.join(srcDir, srcIndex),
devServer: {
compress: true,
port: devPort,
open: true,
openPage: distHtml
},
output: {
path: path.resolve(distDir),
filename: "[name].[contenthash].js"
},
resolve: {
alias: [],
extensions: [".js", ".json"],
mainFields: ["browser", "main", "module"],
plugins: []
},
module: {
rules: [
{
test: /.hbs$/,
loader: "handlebars-loader",
query: {
partialDirs: [path.join(srcDir, "partials")]
}
},
{
test: /.(js|jsx)$/,
use: "babel-loader",
exclude: /node_modules/
},
{
test: /.(sa|sc|c)ss$/,
include: dir,
enforce: "pre",
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: { importLoaders: 1, sourceMap: !isProduction, url: false }
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
ident: "postcss",
plugins: () => [
require("autoprefixer")(),
require("postcss-import")(),
require("postcss-preset-env")({ stage: 3 }),
isProduction
? require("cssnano")({
preset: [
"default",
{
discardComments: { removeAll: true }
}
]
})
: () => {}
]
}
}
}
]
},
{
test: /.(png|jp(e*)g|svg|ico)$/,
use: [
{
loader: "url-loader",
options: {
limit: 512,
name: "images/[hash]-[name].[ext]"
}
}
],
exclude: nodeModulesDir
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: distHtml,
template: path.join(srcDir, srcTemplate),
// minify: { collapseWhitespace: true },
isNoIndex: "true",
message: "HBS Working"
}),
new MiniCssExtractPlugin({
filename: "main.[contenthash].css",
chunkFilename: "[name].[contenthash].css"
})
]
};