webpack.config.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { dirname, join } from "path";
  2. import { exec } from "child_process";
  3. import { fileURLToPath } from "url";
  4. import dotenv from "dotenv";
  5. import MiniCssExtractPlugin from "mini-css-extract-plugin";
  6. import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
  7. dotenv.config();
  8. /** Set to true to suppress all webpack output but errors */
  9. const silent = true;
  10. const defaultMode = ["development", "production"].includes(process.env.NODE_ENV) ? String(process.env.NODE_ENV) : "development";
  11. const outFileSuffix = process.env.OUTFILE_SUFFIX ?? "";
  12. /** Webpack configuration for the output file */
  13. const output = {
  14. filename: `BetterYTM${outFileSuffix}.user.js`,
  15. path: join(dirname(fileURLToPath(import.meta.url)), "/dist"),
  16. clean: true,
  17. module: true,
  18. };
  19. /** @param {import("./src/types").WebpackEnv} env */
  20. const getConfig = (env) => {
  21. const mode = env.mode ?? defaultMode;
  22. /** @type {import("webpack").Configuration} */
  23. const cfg = {
  24. entry: "./src/index.ts",
  25. output,
  26. mode,
  27. resolve: {
  28. extensions: [
  29. ".ts",
  30. ".js",
  31. ".css",
  32. ".md",
  33. ],
  34. },
  35. experiments: {
  36. // userscripts are automatically wrapped in an IIFE by the browser extension,
  37. // also all modern browsers support ESM so this can safely be enabled:
  38. outputModule: true,
  39. },
  40. optimization: {
  41. moduleIds: "named",
  42. // since sites like greasyfork don't allow minified userscripts:
  43. minimize: false,
  44. minimizer: [
  45. `...`,
  46. new CssMinimizerPlugin(),
  47. ],
  48. },
  49. // enable sourcemaps if NODE_ENV === "development"
  50. ...(mode === "development" ? { devtool: "source-map" } : {}),
  51. ...(silent ? { stats: "errors-only", } : {}),
  52. module: {
  53. rules: [
  54. {
  55. test: /\.tsx?$/,
  56. use: "ts-loader",
  57. exclude: /node_modules/,
  58. },
  59. {
  60. test: /\.(html|svg)$/i,
  61. loader: "html-loader",
  62. },
  63. {
  64. test: /\.md$/,
  65. use: [
  66. {
  67. loader: "html-loader",
  68. },
  69. {
  70. loader: "markdown-loader",
  71. },
  72. ],
  73. },
  74. {
  75. test: /.css$/,
  76. use: [MiniCssExtractPlugin.loader, "css-loader" /*, "sass-loader"*/],
  77. },
  78. ],
  79. },
  80. plugins: [
  81. new MiniCssExtractPlugin({
  82. filename: "global.css",
  83. }),
  84. {
  85. apply: (compiler) => {
  86. console.log("Running post-build script...\n");
  87. compiler.hooks.afterEmit.tap("AfterEmitPlugin", () => {
  88. exec(`npm run --silent post-build -- mode=${mode}`, (_err, stdout, stderr) => {
  89. stdout && process.stdout.write(stdout);
  90. stderr && process.stderr.write(stderr);
  91. });
  92. });
  93. },
  94. },
  95. ],
  96. };
  97. return cfg;
  98. };
  99. export default getConfig;
  100. export { output };