Webpack4 html partials with parameters - html

Creating a static application with webpack4 I'm searching a way to transmit variable to the partials.
here is my webpack config
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Require html-webpack-plugin plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var path = require("path");
module.exports = {
entry: __dirname + "/src/app/index.js", // webpack entry point. Module to start building dependency graph
output: {
path: __dirname + '/dist', // Folder to store generated bundle
filename: 'bundle.js', // Name of generated bundle after build
publicPath: '/' // public URL of the output directory when referenced in a browser
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader"
}
},
{
test : /\.(scss|css)$/,
resolve: {extensions: [".scss", ".css"],},
use : [
'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'resolve-url-loader?sourceMap',
'sass-loader?sourceMap',
]
},
{ test: /\.(html)$/,
include: path.join(__dirname, 'src/public'),
use: {
loader: 'html-loader',
options: {
interpolate: true
}
}
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: [
'file-loader?name=[name].[ext]&outputPath=./images/',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: false,
quality: 10
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
},
],
},
{
test: /\.ejs$/,
use: 'ejs-compiled-loader'
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: `styles/[name].css`
}),
new HtmlWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'src/app/views/index.ejs',
filename: 'index.html',
include:'body',
title: 'Home',
chunks: ['index']
}),
new HtmlWebpackPlugin({
filename: 'about.html',
title: 'Praxis',
template: 'src/public/about.html'
}),
new HtmlWebpackPlugin({
filename: 'appointments.html',
template: 'src/public/appointments.html'
}),
new HtmlWebpackPlugin({
filename: 'directions.html',
template: 'src/public/directions.html'
}),
new HtmlWebpackPlugin({
filename: 'privacy.html',
template: 'src/public/privacy.html'
}),
new HtmlWebpackPlugin({
filename: 'services.html',
template: 'src/public/services.html'
})
],
devServer: { // configuration for webpack-dev-server
contentBase: './src/public', //source of static assets
port: 7700, // port to run dev-server
}
};
Having the following example
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
${require('./partials/header.html')}
${require('./partials/footer.html')}
</body>
I would like to be able to add some parameter like
${require('./partials/header.html')({title: 'Home')}
Is there any workaround for this case?

Related

Webpack does not remove boilerplate from HtmlWebpackPLugin under development

I own the following pages:
about
contact
home
portfolio
And these pages are "templates", where nothing more, nothing less, I inject the head with index.js and index.scss in them, along with title, goals etc that are the same for all.
But in development mode, it still leaves the <%= htmlWebpackPlugin.tags.headTags %>
HTML TEMPLATE PAGE EXAMPLE:
<html lang="en">
<head>
<%= htmlWebpackPlugin.tags.headTags %>
</head>
<body>
X
</body>
</html>
WEBPACK CONFIG:
const path = require('path');
const AutoPrefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const HTML_WEBPACK_PLUGIN = {
minify: true,
cache: true,
favicon: '',
meta: {
viewport: 'width=device-width, initial-scale=1',
},
};
module.exports = {
entry: './src/index.js',
mode: 'production',
plugins: [
new HtmlWebpackPlugin({ ...HTML_WEBPACK_PLUGIN, title: 'HOME PAGE', filename: 'index.html', template: 'src/pages/home.html' }),
new HtmlWebpackPlugin({ ...HTML_WEBPACK_PLUGIN, title: 'ABOUT PAGE', filename: 'about.html', template: 'src/pages/about.html' }),
new HtmlWebpackPlugin({
...HTML_WEBPACK_PLUGIN,
title: 'PORTFOLIO PAGE',
filename: 'portfolio.html',
template: 'src/pages/portfolio.html',
}),
new HtmlWebpackPlugin({
...HTML_WEBPACK_PLUGIN,
title: 'CONTACT PAGE',
filename: 'contact.html',
template: 'src/pages/contact.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css',
}),
],
devServer: {
static: path.resolve(__dirname, 'dist'),
port: 8080,
hot: false,
liveReload: true,
},
optimization: {
runtimeChunk: 'single',
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.cleanCssMinify,
parallel: true,
}),
new TerserPlugin({
test: /\.js(\?.*)?$/i,
parallel: true,
minify: TerserPlugin.uglifyJsMinify,
}),
],
},
output: {
clean: true,
filename: '[name].[contenthash].js',
chunkFilename: '[id].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: true,
presets: ['#babel/preset-env'],
plugins: ['#babel/plugin-transform-runtime'],
},
},
},
{
test: /\.html$/i,
loader: 'html-loader',
},
{
mimetype: 'image/svg+xml',
scheme: 'data',
type: 'asset/resource',
generator: {
filename: 'icons/[hash].svg',
},
},
{
test: /\.(sa|sc|c)ss$/, // SASS AND CSS
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: () => [AutoPrefixer()],
},
},
},
{
loader: 'sass-loader',
},
],
},
],
},
};

How open image with tag a?

To create my page i use webpack. In page i want show multiple image. On internet i found library "lightbox2". This library is used for click image and popup. The library have simple example like this:
<a
class="example-image-link"
href="../image/bed-small.jpg" -- not work
href="./469cccac29babd05add3a0b2d23abf0d.jpg" -- work
data-lightbox="example-1"
><img class="example-image" src="../image/bed-small.jpg" alt="image-1" --here work
/></a>
Img src work great and i see picture on my page. When i click on image popup work but image never loaded. I used dev-tools and i see that my image is download with that name '469cccac29babd05add3a0b2d23abf0d.jpg'. So i copy and i see my image. My question is how generate that file name dynamic in my html file ? Below i add my webpack.conf
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
},
entry: {
main: './js/index.js',
fontAwesome: './js/fontAwe.js',
fontSolid: './js/fontSolid.js',
fontRegular: './js/fontRegular.js',
galery: './js/galery.js',
},
plugins: [
new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
new HtmlWebpackPlugin({
title: 'none',
template: './index.html',
inject: true,
chunks: ['main', 'fontAwesome', 'fontSolid', 'fontRegular'],
filename: 'index.html',
}),
new HtmlWebpackPlugin({
title: 'none',
template: './pages/galeria.html',
inject: true,
chunks: ['galery'],
filename: 'galeria.html',
}),
],
output: {
publicPath: '/',
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
},
},
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
// Prefer `dart-sass`
implementation: require('sass'),
},
},
],
},
{
test: /\.html$/i,
loader: 'html-loader',
},
{
//IMAGE LOADER
test: /\.(jpe?g|png|gif|svg)$/i,
loader: 'file-loader',
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
},
},
],
},
],
},
};
My dev-tool
No longer current. I found solution. Import image to js file and changed href ;)
change name of photo and use:<div class=""><a src="></a>

Inline all html tags with appropriate style from a stylesheet using html-inline-css-webpack-plugin

In order to send email from an application I develop, due to smtp client restrictions,
I would like to inline every style class from my CSS in each tags in my final html template using Webpack. In my case I can inline all the stylesheet in the one div but my aim is to get every tag of the style to be filled with the appropriate style.
Here is my webpack.config :
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HTMLInlineCSSWebpackPlugin = require("html-inline-css-webpack-plugin").default;
module.exports = {
mode: 'development',
entry: [
'./src/main.js',
],
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].css',
}),
new HtmlWebpackPlugin({
filename: 'review.html',
template: './src/templates/models/review.pug',
}),
new HtmlWebpackPlugin({
filename: 'access_request.html',
template: './src/templates/models/domain_access_request.pug',
}),
new HtmlWebpackPlugin({
filename: 'analytics_alert.html',
template: './src/templates/models/analytics_alert.pug',
}),
new HtmlWebpackPlugin({
filename: 'battery_pb.html',
template: './src/templates/models/battery_pb.pug',
}),
new HtmlWebpackPlugin({
filename: 'deco_module_cloud.html',
template: './src/templates/models/deco_module_cloud.pug',
}),
new HtmlWebpackPlugin({
filename: 'stock_pb.html',
template: './src/templates/models/stock_pb.pug',
}),
new HTMLInlineCSSWebpackPlugin({
replace: {
target: 'tbody',
removeTarget:true
}
}),
],
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.scss$/i,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'sass-loader'
}
],
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
minimize: true,
includePaths: [
path.resolve(__dirname, './src/templates/assets/scss')
]
}
},
],
},
{
test: /\.pug$/,
use: [
'pug-loader'
],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader',
],
},
],
},
};
Hope you understood my issue.

How to automatically add css imports in all generated html files?

I'm generating multiples *.html files in the dist folder of my project (copied with file-loader). The import of styles.css (generated from scss files from my src folder) is present in the generated index.html but not in the other generated html files which are located in my src/pages (and also generated in the dist folder).
How can I add the styles.css import in all generated html files or even better in all targeted html files?
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin'); // to minify JS
module.exports = {
entry: ['#babel/polyfill', './src/js/index.js'],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/bundle.js'
},
devServer: {
contentBase: './dist'
},
optimization: {
//https://webpack.js.org/plugins/mini-css-extract-plugin/
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
output: {
comments: /#license/i,
},
},
extractComments: false,
}),
new OptimizeCSSAssetsPlugin({})
], // utilisés pour minifier le css généré en Production
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.s[ac]ss$/i,
chunks: 'all',
enforce: true,
},
},
},
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: false
}
}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new CopyPlugin([
{ from: './src/assets/images', to: 'assets/images' },
//{ from: 'other', to: 'public' },
]),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.(html)$/i,
loader: 'html-loader',
options: {
attributes: false,
interpolate: true,
},
},
{
test: /\.s[ac]ss$/i,
use: [
{loader: MiniCssExtractPlugin.loader},
//'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader',
'sass-loader',
],
},
{
test: /\.svg/,
use: {
loader: 'svg-url-loader',
options: {}
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/images',
esModule: false,
}
}
]
},
{
test: /\.html$/,
loader: 'file-loader',
options: {
name: '[name].[ext]'
},
exclude: [
path.resolve(__dirname, 'src/index.html'),
path.resolve(__dirname, 'src/fragments')
]
},
]
}
};
Thank in advance for your help.

webpack load some html file into index.html (like web component)

i want to separate my project file to multi files.
with sass and JavaScript import, i can do that just for styles and scripts.
but i want to separate HTML files too.
i dont use any frameworks just webpack.
according to webpack documentation, we can do that with interpolation
https://webpack.js.org/loaders/html-loader/#interpolation
require("html-loader?interpolate!./file.html");
<div>${require('./components/gallery.html')}</div>
but i got error:
Cannot find module 'html-loader?interpolate!./file.html'
my webpack config:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const webpack = require('webpack');
require("html-loader?interpolate!./file.html");
module.exports = {
devtool: 'source-map', // to see source map of scss and ts
entry: [ // root files to load
'./node_modules/material-design-lite/material.min.js',
'./src/scripts/main.ts',
'./src/index.html',
'./src/styles/main.scss',
],
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
transpileOnly: false
}
},
{ // to auto refresh index.html and other html
test: /\.html$/,
loader: "raw-loader",
exclude: /node_modules/,
},
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
}],
},
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader", options: {
sourceMap: true
}
}, {
loader: "sass-loader", options: {
sourceMap: true
}
}]
},
{ // for images and fonts in scss file
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
}
]
},
resolve: {
extensions: ['.ts', '.js', '.json'],
plugins: [
// to get access of custom typescript paths. (e.g. _app/XXX/XX or #app/XXX/XX)
new TsconfigPathsPlugin({ configFile: __dirname + "/tsconfig.json" })
]
},
output: {
filename: "./bundle.js",
path: path.resolve(__dirname, './build'),
},
plugins: [
// use for html pre complier like jade
// new HtmlWebpackPlugin({
// filename: 'index.html',
// path: path.resolve(__dirname, './build'),
// template: './src/index.jade',
// inject: 'body',
// }),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// copy assets folder to access file from html or as http request
new CopyWebpackPlugin([{
from: './src/assets',
to: path.resolve(__dirname, './build/assets')
}]),
// to use hot, inline (auto refresh) in config file. with out this we have to set as command of webpack-dev-server
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: path.resolve(__dirname, './build'),
hot: true, // for auto refresh
inline: true, // for auto refresh
port: 3000,
overlay: true // for show error on html
}
}
HTML
<!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">
<title>Zoom.FM</title>
</head>
<body>
<div class="side-nav mdl-list">
<div>${require('./myfile.html')}</div>
</body>
</html>
how can i do that or how interpolation work?
I found answer :)
remove require("html-loader?interpolate!./file.html")
enable interpolate in webpack config
webpack config
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
options: {
interpolate: true
}
}],
},