-
Notifications
You must be signed in to change notification settings - Fork 0
/
config-overrides.js
177 lines (156 loc) · 5.5 KB
/
config-overrides.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
const paths = require("react-scripts/config/paths");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ManifestPlugin = require("webpack-manifest-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const prebuildScript = require("./prebuild-script");
const postbuildScript = require("./postbuild-script");
const rewiredEsbuild = require("react-app-rewired-esbuild");
const customOverrideDevServer = (configFunction) => {
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost);
config.writeToDisk = true;
config.inline = false;
config.hot = false;
return config;
};
};
const customOverrideWebpack = (config, env) => {
const isEnvProduction = env === "production";
// Adding entries
config.entry = {
popup: paths.appSrc + "/popup",
options: paths.appSrc + "/options",
serviceworker: paths.appSrc + "/extension-service-worker",
};
// Change output filename template to get rid of hash there
config.output.filename = "static/js/[name].js";
// Disable built-in SplitChunksPlugin
config.optimization.splitChunks = {
cacheGroups: { default: false },
};
// Disable runtime chunk addition for each entry point
config.optimization.runtimeChunk = false;
// Shared minify options to be used in HtmlWebpackPlugin constructor
const minifyOpts = {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
};
// Custom HtmlWebpackPlugin instance for index (popup) page
const indexHtmlPlugin = new HtmlWebpackPlugin({
inject: true,
chunks: ["popup"],
template: paths.appPublic + "/popup.html",
filename: "popup.html",
minify: isEnvProduction && minifyOpts,
});
// Replace original HtmlWebpackPlugin instance in config.plugins with the above one
config.plugins = replacePlugin(
config.plugins,
(name) => /HtmlWebpackPlugin/i.test(name),
indexHtmlPlugin
);
// Extra HtmlWebpackPlugin instance for options page
const optionsHtmlPlugin = new HtmlWebpackPlugin({
inject: true,
chunks: ["options"],
template: paths.appHtml,
filename: "index.html",
minify: isEnvProduction && minifyOpts,
});
// Add the above HtmlWebpackPlugin instance into config.plugins
// Note: you may remove/comment the next line if you don't need an options page
config.plugins.push(optionsHtmlPlugin);
// Custom ManifestPlugin instance to cast asset-manifest.json back to old plain format
const manifestPlugin = new ManifestPlugin({
fileName: "asset-manifest.json",
});
// Replace original ManifestPlugin instance in config.plugins with the above one
config.plugins = replacePlugin(
config.plugins,
(name) => /ManifestPlugin/i.test(name),
manifestPlugin
);
// Custom MiniCssExtractPlugin instance to get rid of hash in filename template
const miniCssExtractPlugin = new MiniCssExtractPlugin({
filename: "static/css/[name].css",
});
// Replace original MiniCssExtractPlugin instance in config.plugins with the above one
config.plugins = replacePlugin(
config.plugins,
(name) => /MiniCssExtractPlugin/i.test(name),
miniCssExtractPlugin
);
// Remove GenerateSW plugin from config.plugins to disable service worker generation
config.plugins = replacePlugin(config.plugins, (name) =>
/GenerateSW/i.test(name)
);
// Remove HMR plugin from config.plugins to disable the Hot Module
config.plugins = replacePlugin(config.plugins, (name) =>
/HotModuleReplacementPlugin/i.test(name)
);
// Remove fast refresh plugin
config.plugins = replacePlugin(config.plugins, (name) =>
/ReactRefreshPlugin/i.test(name)
);
// Add prebuild and postbuild script
config.plugins.push({
apply: (compiler) => {
let preBuildCompleted = false;
let postBuildCompleted = false;
compiler.hooks.afterEnvironment.tap("PreBuildScript", (compilation) => {
// Prevent second run
if (preBuildCompleted) return;
try {
prebuildScript(isEnvProduction);
process.stdout.write("Success running pre-build script\n");
process.stdout.write("Continue building...\n");
} catch (error) {
process.stderr.write(`Error running pre-build script: ${error}\n`);
}
preBuildCompleted = true;
});
compiler.hooks.done.tap("PostBuildScript", (compilation) => {
// Prevent second run
if (postBuildCompleted) return;
try {
postbuildScript(isEnvProduction);
process.stdout.write("Success running post-build script\n");
} catch (error) {
process.stderr.write(`Error running post-build script: ${error}\n`);
}
postBuildCompleted = true;
});
},
});
// use es-build for faster build time
config = rewiredEsbuild()(config, env);
return config;
};
module.exports = {
webpack: customOverrideWebpack,
devServer: customOverrideDevServer,
};
// Utility function to replace/remove specific plugin in a webpack config
function replacePlugin(plugins, nameMatcher, newPlugin) {
const i = plugins.findIndex((plugin) => {
return (
plugin.constructor &&
plugin.constructor.name &&
nameMatcher(plugin.constructor.name)
);
});
return i > -1
? plugins
.slice(0, i)
.concat(newPlugin || [])
.concat(plugins.slice(i + 1))
: plugins;
}