Skip to content

Commit 2a65613

Browse files
committed
feature #152 Add various methods to configure default plugins (Lyrkan)
This PR was squashed before being merged into the master branch (closes #152). Discussion ---------- Add various methods to configure default plugins This PR adds some methods to configure default plugins (closes #148, closes #87 and closes #15): * `Encore.configureDefinePlugin(callback)` * `Encore.configureExtractTextPlugin(callback)` * `Encore.configureFriendlyErrorsPlugin(callback)` * `Encore.configureLoaderOptionsPlugin(callback)` * `Encore.configureUglifyJsPlugin(callback)` Other changes: * Allows the `clean-webpack-plugin` to be configured using `Encore.cleanupOutputBeforeBuild(paths, callback)` * Fixed a small mistake in the `Encore.configureManifestPlugin()` jsdoc * Reorganized flags/callbacks in the constructor of `webpack.config.js` since it was starting to be a bit hard to read. I'm not sure about the way I splitted things though, let me know what you think about it. * Renamed `common-chunks.js` to `commons-chunks.js` since the name of the plugin is `CommonsChunkPlugin` @weaverryan: Not directly related but while doing all of that I noticed that `sassOptions` uses snake-case whereas I used camel-case in #144 for `enablePreactPreset()` and in #115 for `configureRuntimeEnvironment()`, should we do something about that? ***Edit 1:** Added `Encore.configureCleanWebpackPlugin()`* ***Edit 2:** Removed `Encore.configureCleanWebpackPlugin()` to use `Encore.cleanupOutputBeforeBuild(paths, callback)` arguments instead* Commits ------- 286787a Minor text changes f72614b Remove configureCleanWebpackPlugin and use cleanupOutputBeforeBuild arguments instead 90c8565 Add various methods to configure default plugins
2 parents 0d3a91b + 286787a commit 2a65613

19 files changed

+888
-65
lines changed

index.js

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,90 @@ const publicApi = {
102102
return this;
103103
},
104104

105+
/**
106+
* Allows you to configure the options passed to the DefinePlugin.
107+
* A list of available options can be found at https://webpack.js.org/plugins/define-plugin/
108+
*
109+
* For example:
110+
*
111+
* Encore.configureDefinePlugin((options) => {
112+
* options.VERSION = JSON.stringify('1.0.0');
113+
* })
114+
*
115+
* @param {function} definePluginOptionsCallback
116+
* @returns {exports}
117+
*/
118+
configureDefinePlugin(definePluginOptionsCallback = () => {}) {
119+
webpackConfig.configureDefinePlugin(definePluginOptionsCallback);
120+
121+
return this;
122+
},
123+
124+
/**
125+
* Allows you to configure the options passed to the extract-text-webpack-plugin.
126+
* A list of available options can be found at https://github.com/webpack-contrib/extract-text-webpack-plugin
127+
*
128+
* For example:
129+
*
130+
* Encore.configureExtractTextPlugin((options) => {
131+
* options.ignoreOrder = true;
132+
* })
133+
*
134+
* @param {function} extractTextPluginOptionsCallback
135+
* @returns {exports}
136+
*/
137+
configureExtractTextPlugin(extractTextPluginOptionsCallback = () => {}) {
138+
webpackConfig.configureExtractTextPlugin(extractTextPluginOptionsCallback);
139+
140+
return this;
141+
},
142+
143+
/**
144+
* Allows you to configure the options passed to the friendly-errors-webpack-plugin.
145+
* A list of available options can be found at https://github.com/geowarin/friendly-errors-webpack-plugin
146+
*
147+
* For example:
148+
*
149+
* Encore.configureFriendlyErrorsPlugin((options) => {
150+
* options.clearConsole = true;
151+
* })
152+
*
153+
* @param {function} friendlyErrorsPluginOptionsCallback
154+
* @returns {exports}
155+
*/
156+
configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) {
157+
webpackConfig.configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback);
158+
159+
return this;
160+
},
161+
162+
/**
163+
* Allows you to configure the options passed to the LoaderOptionsPlugins.
164+
* A list of available options can be found at https://webpack.js.org/plugins/loader-options-plugin/
165+
*
166+
* For example:
167+
*
168+
* Encore.configureLoaderOptionsPlugin((options) => {
169+
* options.minimize = true;
170+
* })
171+
*
172+
* @param {function} loaderOptionsPluginOptionsCallback
173+
* @returns {exports}
174+
*/
175+
configureLoaderOptionsPlugin(loaderOptionsPluginOptionsCallback = () => {}) {
176+
webpackConfig.configureLoaderOptionsPlugin(loaderOptionsPluginOptionsCallback);
177+
178+
return this;
179+
},
180+
105181
/**
106182
* Allows you to configure the options passed to webpack-manifest-plugin.
107183
* A list of available options can be found at https://github.com/danethurber/webpack-manifest-plugin
108184
*
109185
* For example:
110186
*
111-
* Encore.configureManifestPlugin(function(options){
112-
* options.fileName: '../../var/assets/manifest.json'
187+
* Encore.configureManifestPlugin((options) => {
188+
* options.fileName = '../../var/assets/manifest.json';
113189
* })
114190
*
115191
* @param {function} manifestPluginOptionsCallback
@@ -121,6 +197,26 @@ const publicApi = {
121197
return this;
122198
},
123199

200+
/**
201+
* Allows you to configure the options passed to the uglifyjs-webpack-plugin.
202+
* A list of available options can be found at https://github.com/webpack-contrib/uglifyjs-webpack-plugin/tree/v0.4.6
203+
*
204+
* For example:
205+
*
206+
* Encore.configureUglifyJsPlugin((options) => {
207+
* options.compress = false;
208+
* options.beautify = true;
209+
* })
210+
*
211+
* @param {function} uglifyJsPluginOptionsCallback
212+
* @returns {exports}
213+
*/
214+
configureUglifyJsPlugin(uglifyJsPluginOptionsCallback = () => {}) {
215+
webpackConfig.configureUglifyJsPlugin(uglifyJsPluginOptionsCallback);
216+
217+
return this;
218+
},
219+
124220
/**
125221
* Adds a JavaScript file that should be webpacked:
126222
*
@@ -539,13 +635,22 @@ const publicApi = {
539635
},
540636

541637
/**
542-
* If enabled, the output directory is emptied between
543-
* each build (to remove old files).
638+
* If enabled, the output directory is emptied between each build (to remove old files).
639+
*
640+
* A list of available options can be found at https://github.com/johnagan/clean-webpack-plugin
641+
*
642+
* For example:
643+
*
644+
* Encore.cleanupOutputBeforeBuild(['*.js'], (options) => {
645+
* options.dry = true;
646+
* })
544647
*
648+
* @param {Array} paths Paths that should be cleaned, relative to the "root" option
649+
* @param {function} cleanWebpackPluginOptionsCallback
545650
* @returns {exports}
546651
*/
547-
cleanupOutputBeforeBuild() {
548-
webpackConfig.cleanupOutputBeforeBuild();
652+
cleanupOutputBeforeBuild(paths = ['**/*'], cleanWebpackPluginOptionsCallback = () => {}) {
653+
webpackConfig.cleanupOutputBeforeBuild(paths, cleanWebpackPluginOptionsCallback);
549654

550655
return this;
551656
},

lib/WebpackConfig.js

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,44 +31,64 @@ function validateRuntimeConfig(runtimeConfig) {
3131
class WebpackConfig {
3232
constructor(runtimeConfig) {
3333
validateRuntimeConfig(runtimeConfig);
34+
3435
this.runtimeConfig = runtimeConfig;
35-
this.outputPath = null;
36-
this.publicPath = null;
37-
this.manifestKeyPrefix = null;
3836
this.entries = new Map();
3937
this.styleEntries = new Map();
4038
this.plugins = [];
39+
this.loaders = [];
40+
41+
// Global settings
42+
this.outputPath = null;
43+
this.publicPath = null;
44+
this.manifestKeyPrefix = null;
45+
this.sharedCommonsEntryName = null;
46+
this.providedVariables = {};
47+
this.configuredFilenames = {};
48+
49+
// Features/Loaders flags
4150
this.useVersioning = false;
4251
this.useSourceMaps = false;
52+
this.cleanupOutput = false;
53+
this.useImagesLoader = true;
54+
this.useFontsLoader = true;
4355
this.usePostCssLoader = false;
44-
this.postCssLoaderOptionsCallback = function() {};
45-
this.useSassLoader = false;
46-
this.sassLoaderOptionsCallback = function() {};
47-
this.sassOptions = {
48-
resolve_url_loader: true
49-
};
5056
this.useLessLoader = false;
51-
this.lessLoaderOptionsCallback = function() {};
52-
this.cleanupOutput = false;
53-
this.sharedCommonsEntryName = null;
54-
this.providedVariables = {};
55-
this.babelConfigurationCallback = function() {};
57+
this.useSassLoader = false;
5658
this.useReact = false;
5759
this.usePreact = false;
5860
this.preactOptions = {
5961
preactCompat: false
6062
};
6163
this.useVueLoader = false;
62-
this.vueLoaderOptionsCallback = () => {};
63-
this.loaders = [];
6464
this.useTypeScriptLoader = false;
65-
this.tsConfigurationCallback = function() {};
6665
this.useForkedTypeScriptTypeChecking = false;
66+
67+
// Features/Loaders options
68+
this.sassOptions = {
69+
resolve_url_loader: true
70+
};
71+
72+
// Features/Loaders options callbacks
73+
this.postCssLoaderOptionsCallback = () => {};
74+
this.sassLoaderOptionsCallback = () => {};
75+
this.lessLoaderOptionsCallback = () => {};
76+
this.babelConfigurationCallback = () => {};
77+
this.vueLoaderOptionsCallback = () => {};
78+
this.tsConfigurationCallback = () => {};
79+
80+
// Plugins options
81+
this.cleanWebpackPluginPaths = ['**/*'];
82+
83+
// Plugins callbacks
84+
this.cleanWebpackPluginOptionsCallback = () => {};
85+
this.definePluginOptionsCallback = () => {};
86+
this.extractTextPluginOptionsCallback = () => {};
6787
this.forkedTypeScriptTypesCheckOptionsCallback = () => {};
68-
this.useImagesLoader = true;
69-
this.useFontsLoader = true;
70-
this.configuredFilenames = {};
71-
this.manifestPluginOptionsCallback = function() {};
88+
this.friendlyErrorsPluginOptionsCallback = () => {};
89+
this.loaderOptionsPluginOptionsCallback = () => {};
90+
this.manifestPluginOptionsCallback = () => {};
91+
this.uglifyJsPluginOptionsCallback = () => {};
7292
}
7393

7494
getContext() {
@@ -135,6 +155,38 @@ class WebpackConfig {
135155
this.manifestKeyPrefix = manifestKeyPrefix;
136156
}
137157

158+
configureDefinePlugin(definePluginOptionsCallback = () => {}) {
159+
if (typeof definePluginOptionsCallback !== 'function') {
160+
throw new Error('Argument 1 to configureDefinePlugin() must be a callback function');
161+
}
162+
163+
this.definePluginOptionsCallback = definePluginOptionsCallback;
164+
}
165+
166+
configureExtractTextPlugin(extractTextPluginOptionsCallback = () => {}) {
167+
if (typeof extractTextPluginOptionsCallback !== 'function') {
168+
throw new Error('Argument 1 to configureExtractTextPlugin() must be a callback function');
169+
}
170+
171+
this.extractTextPluginOptionsCallback = extractTextPluginOptionsCallback;
172+
}
173+
174+
configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) {
175+
if (typeof friendlyErrorsPluginOptionsCallback !== 'function') {
176+
throw new Error('Argument 1 to configureFriendlyErrorsPlugin() must be a callback function');
177+
}
178+
179+
this.friendlyErrorsPluginOptionsCallback = friendlyErrorsPluginOptionsCallback;
180+
}
181+
182+
configureLoaderOptionsPlugin(loaderOptionsPluginOptionsCallback = () => {}) {
183+
if (typeof loaderOptionsPluginOptionsCallback !== 'function') {
184+
throw new Error('Argument 1 to configureLoaderOptionsPlugin() must be a callback function');
185+
}
186+
187+
this.loaderOptionsPluginOptionsCallback = loaderOptionsPluginOptionsCallback;
188+
}
189+
138190
configureManifestPlugin(manifestPluginOptionsCallback = () => {}) {
139191
if (typeof manifestPluginOptionsCallback !== 'function') {
140192
throw new Error('Argument 1 to configureManifestPlugin() must be a callback function');
@@ -143,6 +195,14 @@ class WebpackConfig {
143195
this.manifestPluginOptionsCallback = manifestPluginOptionsCallback;
144196
}
145197

198+
configureUglifyJsPlugin(uglifyJsPluginOptionsCallback = () => {}) {
199+
if (typeof uglifyJsPluginOptionsCallback !== 'function') {
200+
throw new Error('Argument 1 to configureUglifyJsPlugin() must be a callback function');
201+
}
202+
203+
this.uglifyJsPluginOptionsCallback = uglifyJsPluginOptionsCallback;
204+
}
205+
146206
/**
147207
* Returns the value that should be used as the publicPath,
148208
* which can be overridden by enabling the webpackDevServer
@@ -340,8 +400,18 @@ class WebpackConfig {
340400
this.configuredFilenames = configuredFilenames;
341401
}
342402

343-
cleanupOutputBeforeBuild() {
403+
cleanupOutputBeforeBuild(paths = ['**/*'], cleanWebpackPluginOptionsCallback = () => {}) {
404+
if (!Array.isArray(paths)) {
405+
throw new Error('Argument 1 to cleanupOutputBeforeBuild() must be an Array of paths - e.g. [\'**/*\']');
406+
}
407+
408+
if (typeof cleanWebpackPluginOptionsCallback !== 'function') {
409+
throw new Error('Argument 2 to cleanupOutputBeforeBuild() must be a callback function');
410+
}
411+
344412
this.cleanupOutput = true;
413+
this.cleanWebpackPluginPaths = paths;
414+
this.cleanWebpackPluginOptionsCallback = cleanWebpackPluginOptionsCallback;
345415
}
346416

347417
autoProvideVariables(variables) {

lib/config-generator.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const loaderOptionsPluginUtil = require('./plugins/loader-options');
2626
const versioningPluginUtil = require('./plugins/versioning');
2727
const variableProviderPluginUtil = require('./plugins/variable-provider');
2828
const cleanPluginUtil = require('./plugins/clean');
29-
const commonChunksPluginUtil = require('./plugins/common-chunks');
29+
const commonsChunksPluginUtil = require('./plugins/commons-chunks');
3030
const definePluginUtil = require('./plugins/define');
3131
const uglifyPluginUtil = require('./plugins/uglify');
3232
const friendlyErrorPluginUtil = require('./plugins/friendly-errors');
@@ -223,15 +223,15 @@ class ConfigGenerator {
223223

224224
variableProviderPluginUtil(plugins, this.webpackConfig);
225225

226-
cleanPluginUtil(plugins, this.webpackConfig, ['**/*']);
226+
cleanPluginUtil(plugins, this.webpackConfig);
227227

228-
commonChunksPluginUtil(plugins, this.webpackConfig);
228+
commonsChunksPluginUtil(plugins, this.webpackConfig);
229229

230-
// todo - options here should be configurable
231230
definePluginUtil(plugins, this.webpackConfig);
231+
232232
uglifyPluginUtil(plugins, this.webpackConfig);
233233

234-
let friendlyErrorPlugin = friendlyErrorPluginUtil();
234+
const friendlyErrorPlugin = friendlyErrorPluginUtil(this.webpackConfig);
235235
plugins.push(friendlyErrorPlugin);
236236

237237
assetOutputDisplay(plugins, this.webpackConfig, friendlyErrorPlugin);

lib/plugins/clean.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,26 @@ const CleanWebpackPlugin = require('clean-webpack-plugin');
1616
*
1717
* @param {Array} plugins to push to
1818
* @param {WebpackConfig} webpackConfig read only variable
19-
* @param {Array} paths to clean
20-
* @param {Object} cleanUpOptions
2119
* @return {void}
2220
*/
23-
module.exports = function(plugins, webpackConfig, paths, cleanUpOptions = {}) {
21+
module.exports = function(plugins, webpackConfig) {
2422

2523
if (!webpackConfig.cleanupOutput) {
2624
return;
2725
}
2826

29-
let config = Object.assign({}, cleanUpOptions, {
27+
const cleanWebpackPluginOptions = {
3028
root: webpackConfig.outputPath,
3129
verbose: false,
32-
});
30+
};
3331

34-
plugins.push(new CleanWebpackPlugin(paths, config));
32+
webpackConfig.cleanWebpackPluginOptionsCallback.apply(
33+
cleanWebpackPluginOptions,
34+
[cleanWebpackPluginOptions]
35+
);
36+
37+
plugins.push(new CleanWebpackPlugin(
38+
webpackConfig.cleanWebpackPluginPaths,
39+
cleanWebpackPluginOptions
40+
));
3541
};
File renamed without changes.

lib/plugins/define.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,24 @@ const webpack = require('webpack');
1414
/**
1515
* @param {Array} plugins
1616
* @param {WebpackConfig} webpackConfig
17-
* @param {Object} defineOptions
1817
* @return {void}
1918
*/
20-
module.exports = function(plugins, webpackConfig, defineOptions = {}) {
19+
module.exports = function(plugins, webpackConfig) {
2120

2221
if (!webpackConfig.isProduction()) {
2322
return;
2423
}
2524

26-
let defineConfig = Object.assign({}, defineOptions, {
25+
const definePluginOptions = {
2726
'process.env': {
2827
NODE_ENV: '"production"'
2928
}
30-
});
31-
let define = new webpack.DefinePlugin(defineConfig);
29+
};
3230

33-
plugins.push(define);
31+
webpackConfig.definePluginOptionsCallback.apply(
32+
definePluginOptions,
33+
[definePluginOptions]
34+
);
35+
36+
plugins.push(new webpack.DefinePlugin(definePluginOptions));
3437
};

0 commit comments

Comments
 (0)