UNPKG

4.91 kBJavaScriptView Raw
1'use strict'
2
3const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
4const CopyWebpackPlugin = require('copy-webpack-plugin')
5const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin')
6const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
7const HtmlWebpackPlugin = require('html-webpack-plugin')
8const MiniCssExtractPlugin = require('mini-css-extract-plugin')
9const ProgressBarPlugin = require('progress-bar-webpack-plugin')
10const SVGSymbolSprite = require('svg-symbol-sprite-loader')
11const chalk = require('chalk')
12const { CleanWebpackPlugin } = require('clean-webpack-plugin')
13const {
14 EnvironmentPlugin,
15 HotModuleReplacementPlugin,
16 NamedModulesPlugin,
17} = require('webpack')
18
19/**
20 * Returns the set of plugins for the passed opts including:
21 * clean, copy, duplicatePackageChecker, environment, friendlyErrors,
22 * hotModuleReplacement, html, miniCSSExtract, namedModules, progressBar,
23 * svgSymbolSprite
24 */
25module.exports = ({ chunkHash, devServer, envVars, flags, publicPath, paths }) => ({
26 // --------------------------------------------------------
27 // ✅ Path validation
28 // Ensure that import paths are case sensitive to ensure Linux/MacOS compatability
29 caseSensitivePathsPlugin: new CaseSensitivePathsPlugin(),
30
31 // --- đŸ“Ļ Build Prep
32 // Wipe output folder before the build
33 cleanPlugin: new CleanWebpackPlugin(),
34
35 // --- 🖨 File copying
36 // Copy public directory to build directory, this is an escape hatch for assets
37 // needed that are not imported into build
38 copyPlugin: new CopyWebpackPlugin([paths.static]),
39
40 // --- ✅ Validations + Optimizations
41 // Check for duplicate versions of the same package, ie React 15 && React 16
42 // in the same build
43 duplicatePackageCheckerPlugin: new DuplicatePackageCheckerPlugin({
44 verbose: true, // Show module that is requiring each duplicate package
45 }),
46
47 // --- 💉 Variable injections
48 // Define environment variables in build.
49 // ℹī¸ Values passed to EnvironmentPlugin are defaults
50 environmentPlugin: new EnvironmentPlugin({
51 DEBUG: false,
52 PUBLIC_PATH: publicPath, // useful for routing and media from /public dir
53 ...envVars,
54 }),
55
56 // --- ℹī¸ Logging
57 // Shows and clears errors in a easier to read format
58 friendlyErrorsPlugin: new FriendlyErrorsWebpackPlugin({
59 compilationSuccessInfo: {
60 messages: [
61 ` 🎉 ${chalk.green.bold('BINGO')} 🎉`,
62 ` Application running at ${chalk.blue.underline(
63 `http://${devServer.host || 'localhost'}:${devServer.port || 3000}`,
64 )}`,
65 ],
66 notes: [
67 `webpack output is served from ${publicPath}`,
68 `Content not from webpack is served from ${paths.static}`,
69 `404s will fallback to /index.html`,
70 ],
71 },
72 }),
73
74 // --- đŸ”Ĩ Hot Module Replacement
75 // See: https://webpack.js.org/concepts/hot-module-replacement/
76 hotModuleReplacementPlugin: new HotModuleReplacementPlugin(),
77
78 // --- đŸ“Ļ HTML index generator
79 // Generates index.html with injected script/style resources paths
80 htmlPlugin: new HtmlWebpackPlugin({
81 favicon: `${paths.static}/favicon.ico`,
82 inject: !flags.electron,
83 minify: false,
84 template: paths.htmlTemplate,
85 }),
86
87 // --- 😍 Styles extractions
88 miniCSSExtractPlugin: new MiniCssExtractPlugin({
89 filename: `static/css/[name]${chunkHash}.css`,
90 }),
91
92 // --- đŸ›Ŗ Modules
93 // Uses the relative path of a module for the module id instead of the module
94 // index. This produces more consistent module ids across builds b/c the path
95 // changes much less frequently than the index. Apparently consistent module ids
96 // is a good thing in webpack land.
97 // ℹī¸ We use NamedModulesPlugin b/c the paths gzip better than the hashes
98 // produced by the HashedModuleIdsPlugin!
99 namedModulesPlugin: new NamedModulesPlugin(),
100
101 // --- đŸ”ĸ Stats
102 // Visual compile indicator with progress bar
103 progressBarPlugin: new ProgressBarPlugin({
104 /* eslint-disable no-console */
105 callback: () => console.log(`\n 🎉 ${chalk.bold('BINGO')} 🎉\n`),
106 /* eslint-enable no-console */
107 clear: false, // Don't clear the bar on completion
108 format: ` Hacking time... [:bar] ${chalk.green.bold(
109 ':percent',
110 )} (:elapsed seconds) :msg`,
111 }),
112
113 // --- đŸ“Ļ Asset extractions
114 // Plugin for SVG symbol sprite extracts imported SVGs into a file
115 // ⚠ī¸ Order is important, this plugin must be included after HTML plugin so that
116 // HTML plugin hooks are pre-registered!
117 svgSymbolSpritePlugin: new SVGSymbolSprite.Plugin({
118 filename: `static/media/icon-sprite${chunkHash}.svg`,
119 // Don't inject the sprite id in electron and storybook targets because the
120 // HTML plugin might be different (Storybook) or the app will just always
121 // fetch it (both)
122 injectSpriteId: !(flags.electron || flags.storybook),
123 }),
124})