import * as HtmlWebpackPlugin from "html-webpack-plugin"; import * as MiniCssExtractPlugin from "mini-css-extract-plugin"; import * as webpack from "webpack"; const resolve = require("resolve"); import * as ManifestPlugin from "webpack-manifest-plugin"; import { paths } from "../../config/paths"; const ForkTsCheckerWebpackPlugin = require("react-dev-utils/ForkTsCheckerWebpackPlugin"); const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin"); const InlineChunkHtmlPlugin = require("react-dev-utils/InlineChunkHtmlPlugin"); const ModuleNotFoundPlugin = require("react-dev-utils/ModuleNotFoundPlugin"); const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin"); const WatchMissingNodeModulesPlugin = require("react-dev-utils/WatchMissingNodeModulesPlugin"); const WorkboxWebpackPlugin = require("workbox-webpack-plugin"); const typescriptFormatter = require("react-dev-utils/typescriptFormatter"); export const plugins = { ForkTsCheckerWebpackPlugin: ({ isEnvDevelopment, isEnvProduction, }: { isEnvDevelopment: boolean; isEnvProduction: boolean; }): webpack.Plugin => new ForkTsCheckerWebpackPlugin({ typescript: resolve.sync("typescript", { basedir: paths.appNodeModules, }), async: isEnvDevelopment, useTypescriptIncrementalApi: true, checkSyntacticErrors: true, tsconfig: paths.appTsConfig, reportFiles: ["**", "!**/*.json", "!**/__tests__/**", "!**/?(*.)(spec|test).*", "!**/src/setupProxy.*", "!**/src/setupTests.*"], watch: paths.appSrc, silent: true, // The formatter is invoked directly in WebpackDevServerUtils during development formatter: isEnvProduction ? typescriptFormatter : undefined, }), // https://github.com/jantimon/html-webpack-plugin/issues/218 HtmlWebpackPlugin: ({ isEnvProduction }: { isEnvProduction: boolean }): webpack.Plugin => new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, ...(isEnvProduction ? { minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, } : undefined), }), MiniCssExtractPlugin: (): webpack.Plugin => new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional filename: "static/css/[name].[contenthash:8].css", chunkFilename: "static/css/[name].[contenthash:8].chunk.css", }), ModuleNotFoundPlugin: ({ appPath }: { appPath: string }) => new ModuleNotFoundPlugin(appPath), InlineChunkHtmlPlugin: () => new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]), InterpolateHtmlPlugin: (env: { raw: any }) => new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw), DefinePlugin: (env: { stringified: any }) => new webpack.DefinePlugin(env.stringified), HotModuleReplacementPlugin: () => new webpack.HotModuleReplacementPlugin(), WatchMissingNodeModulesPlugin: () => new WatchMissingNodeModulesPlugin(), CaseSensitivePathsPlugin: () => new CaseSensitivePathsPlugin(), ManifestPlugin: ({ publicPath }: { publicPath: string }) => new ManifestPlugin({ fileName: "asset-manifest.json", publicPath, }), IgnorePlugin: () => new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), WorkboxWebpackPlugin: ({ publicUrl }: { publicUrl: string }) => new WorkboxWebpackPlugin.GenerateSW({ clientsClaim: true, exclude: [/\.map$/, /asset-manifest\.json$/], importWorkboxFrom: "cdn", navigateFallback: publicUrl + "/index.html", navigateFallbackBlacklist: [ // Exclude URLs starting with /_, as they're likely an API call new RegExp("^/_"), // Exclude URLs containing a dot, as they're likely a resource in // public/ and not a SPA route new RegExp("/[^/]+\\.[^/]+$"), ], }), };