require("@babel/register")({ presets: ["@babel/preset-react"] }); const path = require("path"); const fs = require("fs"); const React = require("react"); const { renderToStaticMarkup } = require("react-dom/server"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const BookIndex = require("./src/BookIndex.jsx").default; function readPages(dir) { const pageNums = fs .readdirSync(dir) .map(f => { const m = f.match(/^(\d+)\.html$/); return m ? parseInt(m[1], 10) : null; }) .filter(n => n !== null) .sort((a, b) => a - b); return pageNums.map(n => { let content = fs.readFileSync(path.join(dir, `${n}.html`), "utf8"); content = content.replace(/[ \t]*]+>\n?/g, "").trim(); return { n, content }; }); } function bookTemplateContent(title, logoText, dir) { const pages = readPages(dir); return () => "" + renderToStaticMarkup(React.createElement(BookIndex, { title, logoText, pages })); } module.exports = (env, argv) => { const isProd = argv.mode === "production"; return { entry: { sheet: "./fabula-ultima-sheet.js", // Imports the shared CSS so HtmlWebpackPlugin can inject it into the book page book: "./book.js", }, output: { filename: isProd ? "[name].[contenthash].js" : "[name].js", path: path.resolve(__dirname, "dist"), clean: true, iife: false, }, module: { rules: [ { test: /\.css$/, use: [ isProd ? MiniCssExtractPlugin.loader : "style-loader", "css-loader", ], }, ], }, plugins: [ ...(isProd ? [new MiniCssExtractPlugin({ filename: "[name].[contenthash].css" })] : []), new HtmlWebpackPlugin({ template: "./fabula-ultima-sheet.html", filename: "index.html", chunks: ["sheet"], scriptLoading: "blocking", }), new HtmlWebpackPlugin({ templateContent: bookTemplateContent( "Fabula Ultima - Core Rulebook", "Core Rules", "./books/core" ), filename: "books/core/index.html", chunks: ["book"], scriptLoading: "blocking", }), new HtmlWebpackPlugin({ templateContent: bookTemplateContent( "Fabula Ultima - Natural Fantasy Atlas", "Natural Fantasy Atlas", "./books/natural-fantasy-atlas" ), filename: "books/natural-fantasy-atlas/index.html", chunks: ["book"], scriptLoading: "blocking", }), // Copy book pages to dist/books/ (excluding index.html, managed by HtmlWebpackPlugin) new CopyWebpackPlugin({ patterns: [ { from: "books", to: "books", globOptions: { ignore: ["**/index.html"] }, }, ], }), // Copy static CSS new CopyWebpackPlugin({ patterns: [ { from: "css", to: "css", globOptions: { ignore: ["**/index.html"] }, }, ], }), ], optimization: { minimizer: ["...", new CssMinimizerPlugin()], splitChunks: { cacheGroups: { // Merge CSS from all entries into a single shared file styles: { name: "styles", type: "css/mini-extract", chunks: "all", enforce: true, }, }, }, }, devServer: { static: [ { directory: path.resolve(__dirname, "dist") }, { directory: path.resolve(__dirname, "books"), publicPath: "/books" }, { directory: path.resolve(__dirname, "css"), publicPath: "/css" }, ], port: 8080, open: true, historyApiFallback: { rewrites: [ { from: /^\/book$/, to: "/book/index.html" }, ], }, }, }; };