optimize webpack config for faster build website
- switch to modern html-bundler-webpack-plugin - replace deprecated `file-loader` and `url-loader` with Webpack 5 assets module - create single webpack config instead of two configs
This commit is contained in:
parent
3732d59249
commit
818f752714
12 changed files with 1731 additions and 1293 deletions
|
|
@ -111,17 +111,14 @@
|
|||
"eslint-plugin-optimize-regex": "1.2.1",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-sonarjs": "0.20.0",
|
||||
"file-loader": "6.2.0",
|
||||
"handlebars": "4.7.8",
|
||||
"handlebars-loader": "1.7.3",
|
||||
"html-webpack-plugin": "5.5.3",
|
||||
"html-bundler-webpack-plugin": "2.10.1",
|
||||
"husky": "^8.0.1",
|
||||
"image-webpack-loader": "8.1.0",
|
||||
"is-ci-cli": "2.2.0",
|
||||
"jest": "29.6.2",
|
||||
"lint-staged": "13.2.3",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"mkdirp": "3.0.1",
|
||||
"nopt": "7.2.0",
|
||||
"postcss": "8.4.27",
|
||||
|
|
@ -134,7 +131,6 @@
|
|||
"ts-loader": "9.4.4",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "5.1.6",
|
||||
"url-loader": "4.1.1",
|
||||
"webpack": "5.88.2",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "4.15.1",
|
||||
|
|
|
|||
|
|
@ -1,28 +1,40 @@
|
|||
import path from 'path';
|
||||
|
||||
import webpack from 'webpack';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import HtmlBundlerPlugin from 'html-bundler-webpack-plugin';
|
||||
// eslint-disable-next-line import/default
|
||||
import CopyPlugin from 'copy-webpack-plugin';
|
||||
|
||||
const pages = ['index', 'demo'];
|
||||
|
||||
type Plugin = ((this: webpack.Compiler, compiler: webpack.Compiler) => void) | webpack.WebpackPluginInstance;
|
||||
|
||||
function plugins(page: string): Plugin[] {
|
||||
return [
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
hash: true,
|
||||
inject: true,
|
||||
title: `${page} page`,
|
||||
filename: `${page}.html`,
|
||||
template: `./website/templates/pages/${page}/${page}.handlebars`,
|
||||
minify: {
|
||||
const config = {
|
||||
output: {
|
||||
path: path.resolve(__dirname, './docs'),
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.jsx', '.js'],
|
||||
},
|
||||
plugins: [
|
||||
new HtmlBundlerPlugin({
|
||||
entry: {
|
||||
// define templates here
|
||||
index: './website/templates/pages/index/index.handlebars', // => docs/index.html,
|
||||
demo: './website/templates/pages/demo/demo.handlebars', // => docs/demo.html
|
||||
},
|
||||
js: {
|
||||
// output filename of compiled JavaScript, used if `inline` option is false (defaults)
|
||||
filename: '[name].[contenthash:8].js',
|
||||
//inline: true, // inlines JS into HTML
|
||||
},
|
||||
css: {
|
||||
// output filename of extracted CSS, used if `inline` option is false (defaults)
|
||||
filename: '[name].[contenthash:8].css',
|
||||
//inline: true, // inlines CSS into HTML
|
||||
},
|
||||
preprocessor: 'handlebars', // use the handlebars compiler
|
||||
preprocessorOptions: {
|
||||
knownHelpersOnly: false,
|
||||
helpers: [path.join(__dirname, 'website/templates/helpers')],
|
||||
partials: [path.join(__dirname, 'website/templates/partials'), path.join(__dirname, 'website/templates/pages')],
|
||||
},
|
||||
minify: 'auto', // minify in production mode only
|
||||
minifyOptions: {
|
||||
html5: true,
|
||||
collapseWhitespace: true,
|
||||
caseSensitive: true,
|
||||
|
|
@ -45,20 +57,7 @@ function plugins(page: string): Plugin[] {
|
|||
{ from: 'website/sitemap.xml', to: 'sitemap.xml' },
|
||||
],
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
const config: webpack.Configuration[] = pages.map(page => {
|
||||
return {
|
||||
entry: {
|
||||
[page]: `./website/templates/pages/${page}/${page}.ts`,
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, './docs'),
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.jsx', '.js'],
|
||||
},
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
|
|
@ -66,38 +65,13 @@ const config: webpack.Configuration[] = pages.map(page => {
|
|||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.(html)$/,
|
||||
use: {
|
||||
loader: 'html-loader',
|
||||
options: {
|
||||
attrs: ['img:src'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.handlebars$/,
|
||||
loader: 'handlebars-loader',
|
||||
options: {
|
||||
inlineRequires: '/images/',
|
||||
precompileOptions: {
|
||||
knownHelpersOnly: false,
|
||||
},
|
||||
helperDirs: [path.join(__dirname, 'website/templates/helpers')],
|
||||
partialDirs: [path.join(__dirname, 'website/templates')],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(gif|png|jpe?g|webp)$/i,
|
||||
type: 'asset/resource',
|
||||
generator: {
|
||||
filename: 'images/[name][ext]?[hash]',
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]?[hash]',
|
||||
outputPath: 'images',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'image-webpack-loader',
|
||||
options: {
|
||||
|
|
@ -124,28 +98,33 @@ const config: webpack.Configuration[] = pages.map(page => {
|
|||
},
|
||||
{
|
||||
test: /\.(css)$/,
|
||||
use: [MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'],
|
||||
use: [{ loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.woff(2)?(\?v=\d\.\d\.\d)?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 1000,
|
||||
mimetype: 'application/font-woff',
|
||||
type: 'asset',
|
||||
parser: {
|
||||
dataUrlCondition: {
|
||||
maxSize: 1000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|svg)(\?v=\d\.\d\.\d)?$/,
|
||||
loader: 'file-loader',
|
||||
type: 'asset/resource',
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: plugins(page),
|
||||
// enable live reload after changes
|
||||
devServer: {
|
||||
static: path.resolve(__dirname, './docs'),
|
||||
watchFiles: {
|
||||
paths: ['website/**/*.*'],
|
||||
options: {
|
||||
usePolling: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
24
website/templates/helpers/block.js
Normal file
24
website/templates/helpers/block.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const Handlebars = require('handlebars');
|
||||
|
||||
/** @typedef {import('handlebars').HelperOptions} HelperOptions */
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {HelperOptions}
|
||||
* @return {string}
|
||||
*/
|
||||
module.exports = function (name, options) {
|
||||
// eslint-disable-next-line
|
||||
const context = this;
|
||||
let partial = context._blocks[name] || options.fn;
|
||||
|
||||
if (typeof partial === 'string') {
|
||||
partial = Handlebars.compile(partial);
|
||||
context._blocks[name] = partial;
|
||||
}
|
||||
|
||||
return partial(context, { data: options.hash });
|
||||
};
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import handlebars, { HelperOptions } from 'handlebars';
|
||||
|
||||
const loadPartial = <T>(name: string): handlebars.Template<T> => {
|
||||
let partial = handlebars.partials[name];
|
||||
if (typeof partial === 'string') {
|
||||
partial = handlebars.compile(partial);
|
||||
handlebars.partials[name] = partial;
|
||||
}
|
||||
return partial;
|
||||
};
|
||||
|
||||
export default (name: string, options: HelperOptions): string => {
|
||||
const partial = loadPartial(name) || options.fn;
|
||||
return partial(this, { data: options.hash });
|
||||
};
|
||||
20
website/templates/helpers/partial.js
Normal file
20
website/templates/helpers/partial.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
/** @typedef {import('handlebars').HelperOptions} HelperOptions */
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {HelperOptions} options
|
||||
* @return {void}
|
||||
*/
|
||||
module.exports = function (name, options) {
|
||||
// don't modify `this` in code directly, because it will be compiled in `exports` as an immutable object
|
||||
// eslint-disable-next-line
|
||||
const context = this;
|
||||
|
||||
if (!context._blocks) {
|
||||
context._blocks = {};
|
||||
}
|
||||
|
||||
context._blocks[name] = options.fn;
|
||||
};
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import handlebars, { HelperOptions } from 'handlebars';
|
||||
|
||||
export default (name: string, options: HelperOptions): void => {
|
||||
handlebars.registerPartial(name, options.fn);
|
||||
};
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
{{#partial "content"}}
|
||||
{{> content}}
|
||||
{{#partial 'scripts'}}
|
||||
{{! define here page-specific source script files }}
|
||||
<script src="./demo.ts" defer="defer"></script>
|
||||
{{/partial}}
|
||||
{{> ../../template}}
|
||||
{{#partial "content"}}
|
||||
{{> demo/content}}
|
||||
{{/partial}}
|
||||
{{> template}}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { Diff2HtmlUI, defaultDiff2HtmlUIConfig, Diff2HtmlUIConfig } from '../../../../src/ui/js/diff2html-ui-slim';
|
||||
|
||||
import '../../../main.ts';
|
||||
import '../../../main';
|
||||
import '../../../main.css';
|
||||
import 'highlight.js/styles/github.css';
|
||||
import '../../../../src/ui/css/diff2html.css';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
{{#partial "content"}}
|
||||
{{> content}}
|
||||
{{#partial 'scripts'}}
|
||||
{{! define here page-specific source script files }}
|
||||
<script src="./index.ts" defer="defer"></script>
|
||||
{{/partial}}
|
||||
{{> ../../template}}
|
||||
{{#partial "content"}}
|
||||
{{> index/content}}
|
||||
{{/partial}}
|
||||
{{> template}}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import Clipboard from 'clipboard';
|
||||
|
||||
import '../../../main.ts';
|
||||
import '../../../main';
|
||||
import '../../../main.css';
|
||||
import './index.css';
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
ga('create', 'UA-78351861-2', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
|
||||
{{#block 'scripts'}}{{/block}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
Loading…
Reference in a new issue