diff --git a/WatchHtmlPlugin.js b/WatchHtmlPlugin.js
index ddd4876..96c2fe9 100644
--- a/WatchHtmlPlugin.js
+++ b/WatchHtmlPlugin.js
@@ -1,9 +1,9 @@
-const HtmlWebpackPlugin = require('html-webpack-plugin');
-const colors = require('ansi-colors');
-const chokidar = require('chokidar');
-const spawn = require('cross-spawn');
-const path = require('path');
-const glob = require('glob');
+const HtmlWebpackPlugin = require("html-webpack-plugin");
+const colors = require("ansi-colors");
+const chokidar = require("chokidar");
+const spawn = require("cross-spawn");
+const path = require("path");
+const glob = require("glob");
module.exports = class WatchHtmlPlugin {
constructor(options) {
@@ -20,55 +20,82 @@ module.exports = class WatchHtmlPlugin {
this.addInitialHtmlPlugins(compiler);
this.browserSyncInstance = this.findBrowserSyncInstance(compiler);
- compiler.hooks.watchRun.tapAsync('WatchHtmlPlugin', (compilation, callback) => {
- if (!this.watcher) this.setupFileWatcher();
- callback();
- });
+ compiler.hooks.watchRun.tapAsync(
+ "WatchHtmlPlugin",
+ (compilation, callback) => {
+ if (!this.watcher) this.setupFileWatcher();
+ callback();
+ }
+ );
}
initializeFiles() {
- glob.sync(`${this.options.srcDir}/**/*.html`).forEach(file => this.initialFiles.add(path.resolve(file)));
+ glob
+ .sync(`${this.options.srcDir}/**/*.html`)
+ .forEach((file) => this.initialFiles.add(path.resolve(file)));
}
addInitialHtmlPlugins(compiler) {
- this.createHtmlPlugins(Array.from(this.initialFiles)).forEach(plugin => plugin.apply(compiler));
+ this.createHtmlPlugins(Array.from(this.initialFiles)).forEach((plugin) =>
+ plugin.apply(compiler)
+ );
}
createHtmlPlugins(files) {
- return files.map(filePath => new HtmlWebpackPlugin({
- ...this.options.htmlPluginOptions,
- template: filePath,
- filename: path.relative(this.options.srcDir, filePath).replace(/\\/g, '/'),
- }));
+ return files.map(
+ (filePath) =>
+ new HtmlWebpackPlugin({
+ ...this.options.htmlPluginOptions,
+ template: filePath,
+ filename: path
+ .relative(this.options.srcDir, filePath)
+ .replace(/\\/g, "/"),
+ })
+ );
}
findBrowserSyncInstance(compiler) {
- return compiler.options.plugins?.find(plugin => plugin.browserSync && typeof plugin.browserSync.exit === 'function')?.browserSync || null;
+ return (
+ compiler.options.plugins?.find(
+ (plugin) =>
+ plugin.browserSync && typeof plugin.browserSync.exit === "function"
+ )?.browserSync || null
+ );
}
setupFileWatcher() {
- this.watcher = chokidar.watch(`${this.options.srcDir}/*.html`, {ignoreInitial: true});
- this.watcher.on('add', this.debounceRestart.bind(this));
- this.watcher.on('unlink', this.debounceRestart.bind(this));
- this.watcher.on('error', error => console.error(colors.bgRed.whiteBright(`[WatchHtmlPlugin] Watcher error: ${error}`)));
+ this.watcher = chokidar.watch(`${this.options.srcDir}/*.html`, {
+ ignoreInitial: true,
+ });
+ this.watcher.on("add", this.debounceRestart.bind(this));
+ this.watcher.on("unlink", this.debounceRestart.bind(this));
+ this.watcher.on("error", (error) =>
+ console.error(
+ colors.bgRed.whiteBright(`[WatchHtmlPlugin] Watcher error: ${error}`)
+ )
+ );
}
stopBrowserSync() {
- return this.browserSyncInstance ? new Promise(resolve => {
- this.browserSyncInstance.exit();
- this.browserSyncInstance = null;
- resolve();
- }) : Promise.resolve();
+ return this.browserSyncInstance
+ ? new Promise((resolve) => {
+ this.browserSyncInstance.exit();
+ this.browserSyncInstance = null;
+ resolve();
+ })
+ : Promise.resolve();
}
stopServerProcess() {
- return this.serverProcess ? new Promise(resolve => {
- this.serverProcess.on('exit', () => {
- this.serverProcess = null;
- resolve();
- });
- this.serverProcess.kill('SIGTERM');
- }) : Promise.resolve();
+ return this.serverProcess
+ ? new Promise((resolve) => {
+ this.serverProcess.on("exit", () => {
+ this.serverProcess = null;
+ resolve();
+ });
+ this.serverProcess.kill("SIGTERM");
+ })
+ : Promise.resolve();
}
debounceRestart() {
@@ -77,9 +104,24 @@ module.exports = class WatchHtmlPlugin {
}
restartDevServer() {
- console.log(colors.bgRed.whiteBright.bold('[WatchHtmlPlugin] Restarting the development server...'));
- Promise.all([this.stopBrowserSync(), this.stopServerProcess()]).then(() => {
- this.serverProcess = spawn('npm', ['run', 'start'], {stdio: 'inherit'});
- }).catch(error => console.error(colors.bgRed.whiteBright('[WatchHtmlPlugin] Error during restart:', error)));
+ console.log(
+ colors.bgRed.whiteBright.bold(
+ "[WatchHtmlPlugin] Restarting the development server..."
+ )
+ );
+ Promise.all([this.stopBrowserSync(), this.stopServerProcess()])
+ .then(() => {
+ this.serverProcess = spawn("npm", ["run", "start"], {
+ stdio: "inherit",
+ });
+ })
+ .catch((error) =>
+ console.error(
+ colors.bgRed.whiteBright(
+ "[WatchHtmlPlugin] Error during restart:",
+ error
+ )
+ )
+ );
}
};
diff --git a/webpack.config.js b/webpack.config.js
index e703244..fad3b97 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,30 +1,30 @@
-const path = require('path');
-const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
-const ESLintPlugin = require('eslint-webpack-plugin');
-const MiniCssExtractPlugin = require('mini-css-extract-plugin');
-const StylelintPlugin = require('stylelint-webpack-plugin');
-const WatchHtmlPlugin = require('./WatchHtmlPlugin');
+const path = require("path");
+const BrowserSyncPlugin = require("browser-sync-webpack-plugin");
+const ESLintPlugin = require("eslint-webpack-plugin");
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+const StylelintPlugin = require("stylelint-webpack-plugin");
+const WatchHtmlPlugin = require("./WatchHtmlPlugin");
// Development server configuration
const devServerConfiguration = {
- host: 'localhost',
+ host: "localhost",
port: 8080,
- open: 'external',
+ open: "external",
hot: true, // Enable Hot Module Replacement (HMR)
liveReload: true, // Enable live reloading
reload: false,
watch: true,
notify: true,
reloadDelay: 0,
- watchFiles: ['src/html/**/*.html'], // Watch HTML files
- static: path.resolve(__dirname, 'dist'),
+ watchFiles: ["src/html/**/*.html"], // Watch HTML files
+ static: path.resolve(__dirname, "dist"),
client: {
overlay: true, // Display errors in the browser
},
server: {
- baseDir: ['dist'],
+ baseDir: ["dist"],
},
- files: [path.resolve(__dirname, 'src/**/*')],
+ files: [path.resolve(__dirname, "src/**/*")],
ghostMode: {
location: false,
},
@@ -34,17 +34,17 @@ const devServerConfiguration = {
module.exports = function (env, args) {
return {
- entry: './src/index.js',
+ entry: "./src/index.js",
output: {
- path: path.resolve(__dirname, 'dist'),
- filename: './js/index.bundle.js',
+ path: path.resolve(__dirname, "dist"),
+ filename: "./js/index.bundle.js",
},
resolve: {
alias: {
- src: path.resolve(__dirname, 'src'),
+ src: path.resolve(__dirname, "src"),
},
},
- devtool: 'source-map', // Generate sourcemaps for proper error messages
+ devtool: "source-map", // Generate sourcemaps for proper error messages
performance: {
hints: false, // Turn off size warnings for entry points
},
@@ -57,9 +57,9 @@ module.exports = function (env, args) {
{
test: /\.(html)$/,
use: {
- loader: 'html-srcsets-loader',
+ loader: "html-srcsets-loader",
options: {
- attrs: [':src', ':srcset'],
+ attrs: [":src", ":srcset"],
interpolate: true,
minimize: false,
removeComments: false,
@@ -73,19 +73,19 @@ module.exports = function (env, args) {
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true,
- publicPath: '../',
+ publicPath: "../",
},
},
{
- loader: 'css-loader',
+ loader: "css-loader",
options: {
importLoaders: 2,
sourceMap: true,
},
},
- 'resolve-url-loader',
+ "resolve-url-loader",
{
- loader: 'postcss-loader',
+ loader: "postcss-loader",
options: {
postcssOptions: {
plugins: {
@@ -96,7 +96,7 @@ module.exports = function (env, args) {
},
},
{
- loader: 'sass-loader',
+ loader: "sass-loader",
options: {
sourceMap: true,
},
@@ -105,34 +105,34 @@ module.exports = function (env, args) {
},
{
test: /\.(js)$/,
- loader: 'babel-loader',
+ loader: "babel-loader",
},
{
test: /\.(png|svg|jpe?g|gif)$/,
- type: 'asset/resource',
+ type: "asset/resource",
generator: {
- filename: 'images/[hash][ext]',
+ filename: "images/[hash][ext]",
},
},
{
test: /(favicon\.ico|site\.webmanifest|browserconfig\.xml|robots\.txt|humans\.txt)$/,
- loader: 'file-loader',
+ loader: "file-loader",
options: {
- name: '[name].[ext]',
+ name: "[name].[ext]",
},
},
{
test: /\.(woff(2)?|ttf|eot)(\?[a-z0-9=.]+)?$/,
- type: 'asset/resource',
+ type: "asset/resource",
generator: {
- filename: 'fonts/[name]-[hash][ext][query]',
+ filename: "fonts/[name]-[hash][ext][query]",
},
},
],
},
plugins: [
new WatchHtmlPlugin({
- srcDir: 'src/html',
+ srcDir: "src/html",
htmlPluginOptions: {
hash: true,
},
@@ -143,16 +143,16 @@ module.exports = function (env, args) {
new ESLintPlugin({
emitError: true,
emitWarning: true,
- context: path.resolve(__dirname, 'src/scripts'),
+ context: path.resolve(__dirname, "src/scripts"),
}),
new StylelintPlugin({
emitErrors: true,
emitWarning: true,
- configFile: path.resolve(__dirname, '.stylelintrc.js'),
- context: path.resolve(__dirname, 'src/assets/styles'),
+ configFile: path.resolve(__dirname, ".stylelintrc.js"),
+ context: path.resolve(__dirname, "src/assets/styles"),
}),
new MiniCssExtractPlugin({
- filename: './css/styles.css',
+ filename: "./css/styles.css",
experimentalUseImportModule: false,
}),
],