|
9 | 9 |
|
10 | 10 | 'use strict';
|
11 | 11 |
|
12 |
| -const webpack = require('webpack'); |
13 |
| -const ExtractTextPlugin = require('extract-text-webpack-plugin'); |
14 | 12 | const extractText = require('./loaders/extract-text');
|
15 |
| -const ManifestPlugin = require('./webpack/webpack-manifest-plugin'); |
16 |
| -const DeleteUnusedEntriesJSPlugin = require('./webpack/delete-unused-entries-js-plugin'); |
17 |
| -const AssetOutputDisplayPlugin = require('./friendly-errors/asset-output-display-plugin'); |
18 |
| -const CleanWebpackPlugin = require('clean-webpack-plugin'); |
19 |
| -const WebpackChunkHash = require('webpack-chunk-hash'); |
20 |
| -const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); |
21 |
| -const missingLoaderTransformer = require('./friendly-errors/transformers/missing-loader'); |
22 |
| -const missingLoaderFormatter = require('./friendly-errors/formatters/missing-loader'); |
23 |
| -const missingPostCssConfigTransformer = require('./friendly-errors/transformers/missing-postcss-config'); |
24 |
| -const missingPostCssConfigFormatter = require('./friendly-errors/formatters/missing-postcss-config'); |
25 |
| -const vueUnactivatedLoaderTransformer = require('./friendly-errors/transformers/vue-unactivated-loader-error'); |
26 |
| -const vueUnactivatedLoaderFormatter = require('./friendly-errors/formatters/vue-unactivated-loader-error'); |
27 | 13 | const pathUtil = require('./config/path-util');
|
| 14 | +// loaders utils |
28 | 15 | const cssLoaderUtil = require('./loaders/css');
|
29 | 16 | const sassLoaderUtil = require('./loaders/sass');
|
30 | 17 | const lessLoaderUtil = require('./loaders/less');
|
31 | 18 | const babelLoaderUtil = require('./loaders/babel');
|
32 | 19 | const tsLoaderUtil = require('./loaders/typescript');
|
33 | 20 | const vueLoaderUtil = require('./loaders/vue');
|
| 21 | +// plugins utils |
| 22 | +const extractTextPluginUtil = require('./plugins/extract-text'); |
| 23 | +const deleteUnusedEntriesPluginUtil = require('./plugins/delete-unused-entries'); |
| 24 | +const manifestPluginUtil = require('./plugins/manifest'); |
| 25 | +const loaderOptionsPluginUtil = require('./plugins/loader-options'); |
| 26 | +const versioningPluginUtil = require('./plugins/versioning'); |
| 27 | +const variableProviderPluginUtil = require('./plugins/variable-provider'); |
| 28 | +const cleanPluginUtil = require('./plugins/clean'); |
| 29 | +const commonChunksPluginUtil = require('./plugins/common-chunks'); |
| 30 | +const definePluginUtil = require('./plugins/define'); |
| 31 | +const uglifyPluginUtil = require('./plugins/uglify'); |
| 32 | +const friendlyErrorPluginUtil = require('./plugins/friendly-errors'); |
| 33 | +const assetOutputDisplay = require('./plugins/asset-output-display'); |
34 | 34 |
|
35 | 35 | class ConfigGenerator {
|
36 | 36 | /**
|
@@ -180,173 +180,32 @@ class ConfigGenerator {
|
180 | 180 | buildPluginsConfig() {
|
181 | 181 | let plugins = [];
|
182 | 182 |
|
183 |
| - /* |
184 |
| - * All CSS/SCSS content (due to the loaders above) will be |
185 |
| - * extracted into an [entrypointname].css files. The result |
186 |
| - * is that NO css will be inlined, *except* CSS that is required |
187 |
| - * in an async way (e.g. via require.ensure()). |
188 |
| - * |
189 |
| - * This may not be ideal in some cases, but it's at least |
190 |
| - * predictable. It means that you must manually add a |
191 |
| - * link tag for an entry point's CSS (unless no CSS file |
192 |
| - * was imported - in which case no CSS file will be dumped). |
193 |
| - */ |
194 |
| - plugins.push(new ExtractTextPlugin({ |
195 |
| - filename: this.webpackConfig.useVersioning ? '[name].[contenthash].css' : '[name].css', |
196 |
| - // if true, async CSS (e.g. loaded via require.ensure()) |
197 |
| - // is extracted to the entry point CSS. If false, it's |
198 |
| - // inlined in the AJAX-loaded .js file. |
199 |
| - allChunks: false |
200 |
| - })); |
| 183 | + extractTextPluginUtil(plugins, this.webpackConfig); |
201 | 184 |
|
202 | 185 | // register the pure-style entries that should be deleted
|
203 |
| - plugins.push(new DeleteUnusedEntriesJSPlugin( |
204 |
| - // transform into an Array |
205 |
| - [... this.webpackConfig.styleEntries.keys()] |
206 |
| - )); |
207 |
| - |
208 |
| - /* |
209 |
| - * Dump the manifest.json file |
210 |
| - */ |
211 |
| - let manifestPrefix = this.webpackConfig.manifestKeyPrefix; |
212 |
| - if (null === manifestPrefix) { |
213 |
| - // by convention, we remove the opening slash on the manifest keys |
214 |
| - manifestPrefix = this.webpackConfig.publicPath.replace(/^\//,''); |
215 |
| - } |
216 |
| - plugins.push(new ManifestPlugin({ |
217 |
| - basePath: manifestPrefix, |
218 |
| - // guarantee the value uses the public path (or CDN public path) |
219 |
| - publicPath: this.webpackConfig.getRealPublicPath(), |
220 |
| - // always write a manifest.json file, even with webpack-dev-server |
221 |
| - writeToFileEmit: true, |
222 |
| - })); |
223 |
| - |
224 |
| - /* |
225 |
| - * This section is a bit mysterious. The "minimize" |
226 |
| - * true is read and used to minify the CSS. |
227 |
| - * But as soon as this plugin is included |
228 |
| - * at all, SASS begins to have errors, until the context |
229 |
| - * and output options are specified. At this time, I'm |
230 |
| - * not totally sure what's going on here |
231 |
| - * https://github.com/jtangelder/sass-loader/issues/285 |
232 |
| - */ |
233 |
| - plugins.push(new webpack.LoaderOptionsPlugin({ |
234 |
| - debug: !this.webpackConfig.isProduction(), |
235 |
| - options: { |
236 |
| - context: this.webpackConfig.getContext(), |
237 |
| - output: { path: this.webpackConfig.outputPath } |
238 |
| - } |
239 |
| - })); |
240 |
| - |
241 |
| - /* |
242 |
| - * With versioning, the "chunkhash" used in the filenames and |
243 |
| - * the module ids (i.e. the internal names of modules that |
244 |
| - * are required) become important. Specifically: |
245 |
| - * |
246 |
| - * 1) If the contents of a module don't change, then you don't want its |
247 |
| - * internal module id to change. Otherwise, whatever file holds the |
248 |
| - * webpack "manifest" will change because the module id will change. |
249 |
| - * Solved by HashedModuleIdsPlugin or NamedModulesPlugin |
250 |
| - * |
251 |
| - * 2) Similarly, if the final contents of a file don't change, |
252 |
| - * then we also don't want that file to have a new filename. |
253 |
| - * The WebpackChunkHash() handles this, by making sure that |
254 |
| - * the chunkhash is based off of the file contents. |
255 |
| - * |
256 |
| - * Even in the webpack community, the ideal setup seems to be |
257 |
| - * a bit of a mystery: |
258 |
| - * * https://github.com/webpack/webpack/issues/1315 |
259 |
| - * * https://github.com/webpack/webpack.js.org/issues/652#issuecomment-273324529 |
260 |
| - * * https://webpack.js.org/guides/caching/#deterministic-hashes |
261 |
| - */ |
262 |
| - if (this.webpackConfig.isProduction()) { |
263 |
| - // shorter, and obfuscated module ids (versus NamedModulesPlugin) |
264 |
| - // makes the final assets *slightly* larger, but prevents contents |
265 |
| - // from sometimes changing when nothing really changed |
266 |
| - plugins.push(new webpack.HashedModuleIdsPlugin()); |
267 |
| - } else { |
268 |
| - // human-readable module names, helps debug in HMR |
269 |
| - // enable always when not in production for consistency |
270 |
| - plugins.push(new webpack.NamedModulesPlugin()); |
271 |
| - } |
| 186 | + deleteUnusedEntriesPluginUtil(plugins, this.webpackConfig); |
272 | 187 |
|
273 |
| - if (this.webpackConfig.useVersioning) { |
274 |
| - // enables the [chunkhash] ability |
275 |
| - plugins.push(new WebpackChunkHash()); |
276 |
| - } |
| 188 | + // Dump the manifest.json file |
| 189 | + manifestPluginUtil(plugins, this.webpackConfig); |
277 | 190 |
|
278 |
| - if (Object.keys(this.webpackConfig.providedVariables).length > 0) { |
279 |
| - plugins = plugins.concat([ |
280 |
| - new webpack.ProvidePlugin(this.webpackConfig.providedVariables) |
281 |
| - ]); |
282 |
| - } |
| 191 | + loaderOptionsPluginUtil(plugins, this.webpackConfig); |
283 | 192 |
|
284 |
| - if (this.webpackConfig.cleanupOutput) { |
285 |
| - plugins.push( |
286 |
| - new CleanWebpackPlugin(['**/*'], { |
287 |
| - root: this.webpackConfig.outputPath, |
288 |
| - verbose: false, |
289 |
| - }) |
290 |
| - ); |
291 |
| - } |
| 193 | + versioningPluginUtil(plugins, this.webpackConfig); |
292 | 194 |
|
293 |
| - // if we're extracting a vendor chunk, set it up! |
294 |
| - if (this.webpackConfig.sharedCommonsEntryName) { |
295 |
| - plugins = plugins.concat([ |
296 |
| - new webpack.optimize.CommonsChunkPlugin({ |
297 |
| - name: [ |
298 |
| - this.webpackConfig.sharedCommonsEntryName, |
299 |
| - /* |
300 |
| - * Always dump a 2nd file - manifest.json that |
301 |
| - * will contain the webpack manifest information. |
302 |
| - * This changes frequently, and without this line, |
303 |
| - * it would be packaged inside the "shared commons entry" |
304 |
| - * file - e.g. vendor.js, which would prevent long-term caching. |
305 |
| - */ |
306 |
| - 'manifest' |
307 |
| - ], |
308 |
| - minChunks: Infinity, |
309 |
| - }), |
310 |
| - ]); |
311 |
| - } |
| 195 | + variableProviderPluginUtil(plugins, this.webpackConfig); |
312 | 196 |
|
313 |
| - if (this.webpackConfig.isProduction()) { |
314 |
| - plugins = plugins.concat([ |
315 |
| - new webpack.DefinePlugin({ |
316 |
| - 'process.env': { |
317 |
| - NODE_ENV: '"production"' |
318 |
| - } |
319 |
| - }), |
320 |
| - |
321 |
| - // todo - options here should be configurable |
322 |
| - new webpack.optimize.UglifyJsPlugin({ |
323 |
| - sourceMap: this.webpackConfig.useSourceMaps |
324 |
| - }) |
325 |
| - ]); |
326 |
| - } |
| 197 | + cleanPluginUtil(plugins, this.webpackConfig, ['**/*']); |
327 | 198 |
|
328 |
| - const friendlyErrorsPlugin = new FriendlyErrorsWebpackPlugin({ |
329 |
| - clearConsole: false, |
330 |
| - additionalTransformers: [ |
331 |
| - missingLoaderTransformer, |
332 |
| - missingPostCssConfigTransformer, |
333 |
| - vueUnactivatedLoaderTransformer |
334 |
| - ], |
335 |
| - additionalFormatters: [ |
336 |
| - missingLoaderFormatter, |
337 |
| - missingPostCssConfigFormatter, |
338 |
| - vueUnactivatedLoaderFormatter |
339 |
| - ], |
340 |
| - compilationSuccessInfo: { |
341 |
| - messages: [] |
342 |
| - } |
343 |
| - }); |
344 |
| - plugins.push(friendlyErrorsPlugin); |
| 199 | + commonChunksPluginUtil(plugins, this.webpackConfig); |
345 | 200 |
|
346 |
| - if (!this.webpackConfig.useDevServer()) { |
347 |
| - const outputPath = pathUtil.getRelativeOutputPath(this.webpackConfig); |
348 |
| - plugins.push(new AssetOutputDisplayPlugin(outputPath, friendlyErrorsPlugin)); |
349 |
| - } |
| 201 | + // todo - options here should be configurable |
| 202 | + definePluginUtil(plugins, this.webpackConfig); |
| 203 | + uglifyPluginUtil(plugins, this.webpackConfig); |
| 204 | + |
| 205 | + let friendlyErrorPlugin = friendlyErrorPluginUtil(); |
| 206 | + plugins.push(friendlyErrorPlugin); |
| 207 | + |
| 208 | + assetOutputDisplay(plugins, this.webpackConfig, friendlyErrorPlugin); |
350 | 209 |
|
351 | 210 | this.webpackConfig.plugins.forEach(function(plugin) {
|
352 | 211 | plugins.push(plugin);
|
|
0 commit comments