234 lines
6.3 KiB
JavaScript
234 lines
6.3 KiB
JavaScript
const TerserPlugin = require("terser-webpack-plugin");
|
|
const path = require("path");
|
|
const CompressionPlugin = require("compression-webpack-plugin");
|
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
const sass = require("sass");
|
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
const fs = require("fs");
|
|
|
|
module.exports = (env, argv) => {
|
|
const mode =
|
|
argv?.mode !== undefined
|
|
? argv.mode
|
|
: process.env["WEBPACK_MODE"] !== undefined
|
|
? process.env["WEBPACK_MODE"]
|
|
: "production";
|
|
|
|
const production = mode === "production";
|
|
|
|
const inDocker = process.env["MD_DEV_ENV"] === "docker";
|
|
|
|
const dist = path.resolve(__dirname, "dist");
|
|
const src = path.resolve(__dirname, "src");
|
|
const assets = path.resolve(__dirname, "assets");
|
|
|
|
const version = process.env["MD_VERSION"];
|
|
const metadataFilename = `${src}/elm/MassiveDecks/Version.elm`;
|
|
class InjectMetadataPlugin {
|
|
apply(compiler) {
|
|
if (version !== undefined) {
|
|
const logger = compiler.getInfrastructureLogger("InjectMetadataPlugin");
|
|
compiler.hooks.beforeRun.tap("InjectMetadataPlugin", () => {
|
|
const original = this.before(logger);
|
|
const hook = () => {
|
|
this.after(logger, original);
|
|
};
|
|
compiler.hooks.done.tap("InjectMetadataPlugin", hook);
|
|
compiler.hooks.failed.tap("InjectMetadataPlugin", hook);
|
|
});
|
|
}
|
|
}
|
|
|
|
before(logger) {
|
|
logger.info("Metadata Injected");
|
|
const original = fs.readFileSync(metadataFilename, "utf8");
|
|
const updated = original
|
|
.toString()
|
|
.replace(/^(version\s*=\s*")(.*?)(")/m, `$1${version}$3`);
|
|
fs.writeFileSync(metadataFilename, updated);
|
|
return original;
|
|
}
|
|
|
|
after(logger, original) {
|
|
logger.info("Metadata Reverted");
|
|
fs.writeFileSync(metadataFilename, original);
|
|
}
|
|
}
|
|
|
|
return {
|
|
mode,
|
|
context: path.resolve(__dirname),
|
|
entry: {
|
|
// Main entry point.
|
|
index: path.join(src, "ts", "index.ts"),
|
|
// Chromecast entry point.
|
|
cast: path.join(src, "ts", "cast.ts"),
|
|
},
|
|
output: {
|
|
path: dist,
|
|
publicPath: "/",
|
|
filename: "assets/scripts/[name].[contenthash].js",
|
|
clean: true,
|
|
},
|
|
module: {
|
|
rules: [
|
|
// Elm scripts.
|
|
{
|
|
test: /\.elm$/,
|
|
exclude: [/elm-stuff/, /node_modules/],
|
|
use: [
|
|
{
|
|
loader: "elm-webpack-loader",
|
|
options: {
|
|
optimize: production,
|
|
debug: !production,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
// Typescript scripts.
|
|
{
|
|
test: /\.ts$/,
|
|
exclude: [/elm-stuff/, /node_modules/],
|
|
use: "ts-loader",
|
|
include: src,
|
|
},
|
|
// Styles.
|
|
{
|
|
test: /\.s?css$/,
|
|
exclude: [/elm-stuff/, /node_modules/],
|
|
use: [
|
|
production
|
|
? {
|
|
loader: MiniCssExtractPlugin.loader,
|
|
}
|
|
: { loader: "style-loader" },
|
|
// Load CSS to inline styles.
|
|
{
|
|
loader: "css-loader",
|
|
options: { sourceMap: !production },
|
|
},
|
|
// Transform CSS for compatibility.
|
|
{
|
|
loader: "postcss-loader",
|
|
options: {
|
|
sourceMap: !production,
|
|
},
|
|
},
|
|
// Allow relative URLs.
|
|
{
|
|
loader: "resolve-url-loader",
|
|
options: { sourceMap: !production },
|
|
},
|
|
// Load SASS to CSS.
|
|
{
|
|
loader: "sass-loader",
|
|
options: {
|
|
implementation: sass,
|
|
sourceMap: true,
|
|
sassOptions: {
|
|
includePaths: ["node_modules"],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
// Image assets.
|
|
{
|
|
test: /\.(jpg|png|svg)$/,
|
|
type: "asset/resource",
|
|
generator: {
|
|
filename: "assets/images/[name].[hash][ext]",
|
|
},
|
|
},
|
|
// Font assets.
|
|
{
|
|
test: /\.(woff2)$/,
|
|
type: "asset/resource",
|
|
generator: {
|
|
filename: "assets/fonts/[name].[hash][ext]",
|
|
},
|
|
},
|
|
// App manifest.
|
|
{
|
|
test: /\.webmanifest$/,
|
|
exclude: [/elm-stuff/, /node_modules/, /dist/],
|
|
type: "asset/resource",
|
|
generator: {
|
|
filename: "assets/[name].[hash][ext]",
|
|
},
|
|
use: [
|
|
{
|
|
loader: "app-manifest-loader",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
resolve: {
|
|
extensions: [".js", ".ts", ".elm", ".scss"],
|
|
modules: ["node_modules"],
|
|
},
|
|
plugins: [
|
|
new InjectMetadataPlugin(),
|
|
new MiniCssExtractPlugin({
|
|
filename: "assets/styles/[name].[contenthash].css",
|
|
}),
|
|
new HtmlWebpackPlugin({
|
|
template: path.join(src, "html", "index.html"),
|
|
filename: "index.html",
|
|
inject: "body",
|
|
excludeChunks: ["cast"],
|
|
}),
|
|
new HtmlWebpackPlugin({
|
|
template: path.join(src, "html", "cast.html"),
|
|
filename: "cast.html",
|
|
inject: "body",
|
|
excludeChunks: ["index"],
|
|
}),
|
|
...(production
|
|
? [
|
|
new CompressionPlugin({
|
|
test: /\.(js|css|html|webmanifest|svg)$/,
|
|
}),
|
|
]
|
|
: []),
|
|
],
|
|
optimization: {
|
|
minimizer: [
|
|
new TerserPlugin({
|
|
test: /assets\/scripts\/.*\.js$/,
|
|
parallel: true,
|
|
terserOptions: {
|
|
output: {
|
|
comments: false,
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
devtool: !production ? "eval-source-map" : undefined,
|
|
devServer: {
|
|
static: [{ directory: dist }],
|
|
hot: true,
|
|
host: inDocker ? "0.0.0.0" : "localhost",
|
|
allowedHosts: ["localhost"],
|
|
proxy: {
|
|
// Forward to the server.
|
|
"/api/**": {
|
|
target: inDocker ? "http://server:8081" : "http://localhost:8081",
|
|
ws: true,
|
|
},
|
|
// As we are an SPA, this lets us route all requests to the index.
|
|
"**": {
|
|
target: "http://localhost:8080",
|
|
pathRewrite: {
|
|
cast: "cast.html",
|
|
".*": "",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
};
|