Я пытаюсь создать страницы c html с помощью веб-пакета 4. Я использую html -webpack-plugin . Я хочу определить заголовок . html и нижний колонтитул. html и импортировать их позже на все html страницы. Но я также хочу, чтобы мои выходные файлы js и css автоматически вводились в этот верхний и нижний колонтитулы. Примерно так:
header. html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Some Title</title>
<% for(var i=0; i < htmlWebpackPlugin.files.css.length; i++) {%>
<link type="text/css" rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[i] %>">
<% } %>
</head>
<body>
нижний колонтитул. html:
<% for(var i=0; i < htmlWebpackPlugin.files.js.length; i++) {%>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[i] %>"></script>
<% } %>
</body>
</html>
index.hbs (или index. html):
<%= _.template(require('./../includes/header.html'))() %>
<div class="content">
<img src="img/bg/desktop/bg-index-03.jpg" width="500" height="500"/>
<div class="imgtest"></div>
</div> <!-- .content -->
<%= _.template(require('./../includes/footer.html'))() %>
Но я получаю в dist / index. html некоторую ошибку. Эти строки все те же и не загружают верхний / нижний колонтитул в индекс. html:
<%= _.template(require('./../includes/header.html'))() %>
...
<%= _.template(require('./../includes/footer.html'))() %>
По некоторым причинам loda sh не работает ...
UPD :
Я изменил src/html/views/index.hbs
на src/html/views/index.html
(и в плагине)
new HtmlWebpackPlugin({
template: './src/html/views/index.html',
...
Добавить include
строку здесь:
{
test: /\.html$/,
include: path.resolve(__dirname, 'src/html/includes'),
use: ['html-loader']
},
В верхнем / нижнем колонтитуле Я удалил loda sh код <% ... %>
, оставив только чистый html - так оно и работает! Верхний / нижний колонтитул импортирован в index. html, но без css / js.
Если я верну loda sh обратно в нижний колонтитул. html (или header. html)
<% for(var i=0; i < htmlWebpackPlugin.files.js.length; i++) {%>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[i] %>"></script>
<% } %>
Я получаю ошибку:
ERROR in Template execution failed: ReferenceError: htmlWebpackPlugin is not defined
ERROR in ReferenceError: htmlWebpackPlugin is not defined
- lodash.templateSources[2]:10 eval
lodash.templateSources[2]:10:19
- index.html:102
D:/.../src/html/views/index.html:102:110
- index.html:104 ./node_modules/html-webpack-plugin/lib/loader.js!./src/html/views/index.html.module.exports
D:/.../src/html/views/index.html:104:3
- index.js:393
[project]/[html-webpack-plugin]/index.js:393:16
- runMicrotasks
- task_queues.js:93 processTicksAndRejections
internal/process/task_queues.js:93:5
- async Promise.all
Почему это происходит? Что не так? Как заставить loda sh работать в верхнем / нижнем колонтитуле?
Или каков наилучший способ создания html шаблонов?
дерево файлов:
dist
│ index.html
├───css
│ main.css
│ main.css.map
├───fonts
├───img
├───js
│ main.js
│ main.js.map
│ vendors~main.js
│ vendors~main.js.map
src
├───favicon
├───fonts
├───html
│ ├───includes
│ │ footer.html
│ │ header.html
│ └───views
│ index.hbs
├───img
├───js
│ index.js
├───scss
│ fonts.scss
│ icomoon.scss
│ style.scss
package.json
package-lock.json
webpack.config.js
webpack.config. js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const isDev = process.env.NODE_ENV === 'development';
const isProd = !isDev;
const optimization = () => {
const config = {
splitChunks: {
chunks: 'all'
}
}
if (isProd) {
config.minimizer = [
new OptimizeCssAssetWebpackPlugin(),
new TerserWebpackPlugin()
]
}
return config
}
const filename = ext => isDev ? `[name].${ext}` : `[name].[hash].${ext}`;
const cssLoaders = extra => {
const loaders = [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: isDev,
reloadAll: true
},
},
{
loader: 'css-loader',
options: {
url: false
}
}
];
if (extra) {
loaders.push(extra)
}
return loaders
}
const babelOptions = preset => {
const opts = {
presets: [
'@babel/preset-env'
],
plugins: [
'@babel/plugin-proposal-class-properties'
]
}
if (preset) {
opts.presets.push(preset)
}
return opts
}
module.exports = {
mode: 'development',
entry: [
'@babel/polyfill',
'./src/js/index.js'
],
output: {
filename: 'js/' + filename('js'),
path: path.resolve(__dirname, 'dist')
},
devServer: {
port: 4250,
hot: isDev
},
devtool: isDev ? 'source-map' : '',
resolve: {
//extensions: ['.js', '.json', '.png'],
alias: {
'@views': path.resolve(__dirname, 'src/html/views'),
'@includes': path.resolve(__dirname, 'src/html/includes'),
'@scss': path.resolve(__dirname, 'src/scss'),
'@': path.resolve(__dirname, 'src'),
}
},
optimization: optimization(),
module: {
rules: [
{
test: /\.html$/,
//include: path.resolve(__dirname, 'src/html/includes'),
use: ['html-loader']
},
{
test: /\.hbs$/,
loader: 'handlebars-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: {
loader: 'babel-loader',
options: babelOptions()
}
},
{
test: /\.css$/,
use: cssLoaders()
},
{
test: /\.s[ac]ss$/,
use: cssLoaders('sass-loader')
},
{
test: /\.(png|jpg|svg|gif)$/,
exclude: path.resolve(__dirname, 'src/fonts'),
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: path.resolve(__dirname, 'dist/img')
}
}
]
},
{
test: /\.(ttf|otf|svg|woff|woff2|eot)$/,
exclude: path.resolve(__dirname, 'src/img'),
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: path.resolve(__dirname, 'dist/fonts')
}
}
]
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/html/views/index.hbs',
minify: {
collapseWhitespace: isProd
},
inject: false
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'css/' + filename('css'),
}),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'src/favicon'),
to: path.resolve(__dirname, 'dist')
},
{
from: path.resolve(__dirname, 'src/fonts'),
to: path.resolve(__dirname, 'dist/fonts')
},
{
from: path.resolve(__dirname, 'src/img'),
to: path.resolve(__dirname, 'dist/img')
}
])
]
};
пакет. json:
{
"name": "Name",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"dev": "cross-env NODE_ENV=development webpack --mode development",
"build": "cross-env NODE_ENV=production webpack --mode production",
"watch": "cross-env NODE_ENV=development webpack --mode development --watch",
"start": "cross-env NODE_ENV=development webpack-dev-server --mode development --open"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/preset-env": "^7.9.5",
"babel-loader": "^8.1.0",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.1.1",
"cross-env": "^7.0.2",
"css-loader": "^3.5.2",
"file-loader": "^6.0.0",
"html-loader": "^1.1.0",
"html-webpack-plugin": "^4.2.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"raw-loader": "^4.0.1",
"resolve-url-loader": "^3.1.1",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.4",
"terser-webpack-plugin": "^2.3.5",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"
},
"browserslist": "defaults",
"dependencies": {
"@babel/polyfill": "^7.8.7",
"bootstrap": "^4.4.1",
"handlebars": "^4.7.6",
"handlebars-loader": "^1.7.1",
"jquery": "^3.5.0",
"popper.js": "^1.16.1"
}
}