-
Notifications
You must be signed in to change notification settings - Fork 0
/
browserProductionConfiguration.js
198 lines (195 loc) · 6.83 KB
/
browserProductionConfiguration.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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
const { provider } = require('jimple');
const ConfigurationFile = require('../../abstracts/configurationFile');
const { ProjextWebpackRuntimeDefinitions } = require('../../plugins');
/**
* Creates the specifics of a Webpack configuration for a browser target production build.
* @extends {ConfigurationFile}
*/
class WebpackBrowserProductionConfiguration extends ConfigurationFile {
/**
* Class constructor.
* @param {Events} events To reduce the configuration.
* @param {PathUtils} pathUtils Required by `ConfigurationFile`
* in order to build the path to the
* overwrite file.
* @param {TargetsHTML} targetsHTML The service in charge of generating
* a default HTML file in case the
* target doesn't have one.
* @param {WebpackBaseConfiguration} webpackBaseConfiguration The configuration this one will
* extend.
*/
constructor(
events,
pathUtils,
targetsHTML,
webpackBaseConfiguration
) {
super(
pathUtils,
[
'config/webpack/browser.production.config.js',
'config/webpack/browser.config.js',
],
true,
webpackBaseConfiguration
);
/**
* A local reference for the `events` service.
* @type {Events}
*/
this.events = events;
/**
* A local reference for the `targetsHTML` service.
* @type {TargetsHTML}
*/
this.targetsHTML = targetsHTML;
}
/**
* Create the configuration with the `entry`, the `output` and the plugins specifics for a
* browser target production build.
* This method uses the reducer events `webpack-browser-production-configuration` and
* `webpack-browser-configuration`. It sends the configuration, the received `params` and
* expects a configuration on return.
* @param {WebpackConfigurationParams} params A dictionary generated by the top service building
* the configuration and that includes things like the
* target information, its entry settings, output
* paths, etc.
* @return {object}
*/
createConfig(params) {
const {
definitions,
copy,
entry,
target,
output,
additionalWatch,
} = params;
// Define the basic stuff: entry, output and mode.
const config = {
entry,
output: {
path: `./${target.folders.build}`,
filename: output.js,
chunkFilename: output.jsChunks,
publicPath: '/',
},
mode: 'production',
};
// If the target has source maps enabled...
if (target.sourceMap.production) {
config.devtool = 'source-map';
}
// Enable or not uglification for the target bundle.
if (target.uglifyOnProduction) {
config.optimization = {
minimizer: [
new TerserPlugin({
sourceMap: !!target.sourceMap.production,
}),
],
};
} else {
config.optimization = {
minimize: false,
};
}
// Setup the plugins.
config.plugins = [
// If the target is a library, it doesn't need HTML on production.
...(
target.library ?
[] :
[
// To automatically inject the `script` tag on the target `html` file.
new HtmlWebpackPlugin(Object.assign({}, target.html, {
template: this.targetsHTML.getFilepath(target),
inject: 'body',
})),
// To add the `async` attribute to the `script` tag.
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'async',
}),
]
),
// To add the _'browser env variables'_.
new ProjextWebpackRuntimeDefinitions(
Object.keys(entry).reduce(
(current, key) => [...current, ...entry[key].filter((file) => path.isAbsolute(file))],
[]
),
definitions
),
// To optimize the SCSS and remove repeated declarations.
new OptimizeCssAssetsPlugin(),
// To compress the emitted assets using gzip, if the target is not a library.
...(!target.library || target.libraryOptions.compress ? [new CompressionPlugin()] : []),
// Copy the files the target specified on its settings.
new CopyWebpackPlugin(copy),
/**
* If the target doesn't inject the styles on runtime, add the plugin to push them all on
* a single file.
*/
...(
target.css.inject ?
[] :
[new MiniCssExtractPlugin({
filename: output.css,
})]
),
// If there are additionals files to watch, add the plugin for it.
...(
additionalWatch.length ?
[new ExtraWatchWebpackPlugin({ files: additionalWatch })] :
[]
),
];
// Enable the watch mode if required...
if (target.watch.production) {
config.watch = true;
}
// Reduce the configuration
return this.events.reduce(
[
'webpack-browser-production-configuration',
'webpack-browser-configuration',
],
config,
params
);
}
}
/**
* The service provider that once registered on the app container will set an instance of
* `WebpackBrowserProductionConfiguration` as the `webpackBrowserProductionConfiguration` service.
* @example
* // Register it on the container
* container.register(webpackBrowserProductionConfiguration);
* // Getting access to the service instance
* const webpackBrowserProdConfig = container.get('webpackBrowserProductionConfiguration');
* @type {Provider}
*/
const webpackBrowserProductionConfiguration = provider((app) => {
app.set(
'webpackBrowserProductionConfiguration',
() => new WebpackBrowserProductionConfiguration(
app.get('events'),
app.get('pathUtils'),
app.get('targetsHTML'),
app.get('webpackBaseConfiguration')
)
);
});
module.exports = {
WebpackBrowserProductionConfiguration,
webpackBrowserProductionConfiguration,
};