Skip to content

Add various methods to configure default plugins #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,90 @@ const publicApi = {
return this;
},

/**
* Allows you to configure the options passed to the DefinePlugin.
* A list of available options can be found at https://webpack.js.org/plugins/define-plugin/
*
* For example:
*
* Encore.configureDefinePlugin((options) => {
* options.VERSION = JSON.stringify('1.0.0');
* })
*
* @param {function} definePluginOptionsCallback
* @returns {exports}
*/
configureDefinePlugin(definePluginOptionsCallback = () => {}) {
webpackConfig.configureDefinePlugin(definePluginOptionsCallback);

return this;
},

/**
* Allows you to configure the options passed to the extract-text-webpack-plugin.
* A list of available options can be found at https://github.com/webpack-contrib/extract-text-webpack-plugin
*
* For example:
*
* Encore.configureExtractTextPlugin((options) => {
* options.ignoreOrder = true;
* })
*
* @param {function} extractTextPluginOptionsCallback
* @returns {exports}
*/
configureExtractTextPlugin(extractTextPluginOptionsCallback = () => {}) {
webpackConfig.configureExtractTextPlugin(extractTextPluginOptionsCallback);

return this;
},

/**
* Allows you to configure the options passed to the friendly-errors-webpack-plugin.
* A list of available options can be found at https://github.com/geowarin/friendly-errors-webpack-plugin
*
* For example:
*
* Encore.configureFriendlyErrorsPlugin((options) => {
* options.clearConsole = true;
* })
*
* @param {function} friendlyErrorsPluginOptionsCallback
* @returns {exports}
*/
configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) {
webpackConfig.configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback);

return this;
},

/**
* Allows you to configure the options passed to the LoaderOptionsPlugins.
* A list of available options can be found at https://webpack.js.org/plugins/loader-options-plugin/
*
* For example:
*
* Encore.configureLoaderOptionsPlugin((options) => {
* options.minimize = true;
* })
*
* @param {function} loaderOptionsPluginOptionsCallback
* @returns {exports}
*/
configureLoaderOptionsPlugin(loaderOptionsPluginOptionsCallback = () => {}) {
webpackConfig.configureLoaderOptionsPlugin(loaderOptionsPluginOptionsCallback);

return this;
},

/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks beautiful

* Allows you to configure the options passed to webpack-manifest-plugin.
* A list of available options can be found at https://github.com/danethurber/webpack-manifest-plugin
*
* For example:
*
* Encore.configureManifestPlugin(function(options){
* options.fileName: '../../var/assets/manifest.json'
* Encore.configureManifestPlugin((options) => {
* options.fileName = '../../var/assets/manifest.json';
* })
*
* @param {function} manifestPluginOptionsCallback
Expand All @@ -121,6 +197,26 @@ const publicApi = {
return this;
},

/**
* Allows you to configure the options passed to the uglifyjs-webpack-plugin.
* A list of available options can be found at https://github.com/webpack-contrib/uglifyjs-webpack-plugin/tree/v0.4.6
*
* For example:
*
* Encore.configureUglifyJsPlugin((options) => {
* options.compress = false;
* options.beautify = true;
* })
*
* @param {function} uglifyJsPluginOptionsCallback
* @returns {exports}
*/
configureUglifyJsPlugin(uglifyJsPluginOptionsCallback = () => {}) {
webpackConfig.configureUglifyJsPlugin(uglifyJsPluginOptionsCallback);

return this;
},

/**
* Adds a JavaScript file that should be webpacked:
*
Expand Down Expand Up @@ -519,13 +615,22 @@ const publicApi = {
},

/**
* If enabled, the output directory is emptied between
* each build (to remove old files).
* If enabled, the output directory is emptied between each build (to remove old files).
*
* A list of available options can be found at https://github.com/johnagan/clean-webpack-plugin
*
* For example:
*
* Encore.cleanupOutputBeforeBuild(['*.js'], (options) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should show the default ['**/*'] as the first option. The issue is that, if I only want to specify some options for the plugin... I need to know what this first value is by default, so I can repeat it. That kind of sucks... but I can't think of a good way around it (so showing the default here might make sense)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to but '**/*' breaks the multi-line comment :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha! What a crazy edge case :p

* options.dry = true;
* })
*
* @param {Array} paths Paths that should be cleaned, relative to the "root" option
* @param {function} cleanWebpackPluginOptionsCallback
* @returns {exports}
*/
cleanupOutputBeforeBuild() {
webpackConfig.cleanupOutputBeforeBuild();
cleanupOutputBeforeBuild(paths = ['**/*'], cleanWebpackPluginOptionsCallback = () => {}) {
webpackConfig.cleanupOutputBeforeBuild(paths, cleanWebpackPluginOptionsCallback);

return this;
},
Expand Down
114 changes: 92 additions & 22 deletions lib/WebpackConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,40 +30,60 @@ function validateRuntimeConfig(runtimeConfig) {
class WebpackConfig {
constructor(runtimeConfig) {
validateRuntimeConfig(runtimeConfig);

this.runtimeConfig = runtimeConfig;
this.outputPath = null;
this.publicPath = null;
this.manifestKeyPrefix = null;
this.entries = new Map();
this.styleEntries = new Map();
this.plugins = [];
this.loaders = [];

// Global settings
this.outputPath = null;
this.publicPath = null;
this.manifestKeyPrefix = null;
this.sharedCommonsEntryName = null;
this.providedVariables = {};
this.configuredFilenames = {};

// Features/Loaders flags
this.useVersioning = false;
this.useSourceMaps = false;
this.cleanupOutput = false;
this.useImagesLoader = true;
this.useFontsLoader = true;
this.usePostCssLoader = false;
this.postCssLoaderOptionsCallback = function() {};
this.useSassLoader = false;
this.sassLoaderOptionsCallback = function() {};
this.sassOptions = {
resolve_url_loader: true
};
this.useLessLoader = false;
this.lessLoaderOptionsCallback = function() {};
this.cleanupOutput = false;
this.sharedCommonsEntryName = null;
this.providedVariables = {};
this.babelConfigurationCallback = function() {};
this.useSassLoader = false;
this.useReact = false;
this.useVueLoader = false;
this.vueLoaderOptionsCallback = () => {};
this.loaders = [];
this.useTypeScriptLoader = false;
this.tsConfigurationCallback = function() {};
this.useForkedTypeScriptTypeChecking = false;

// Features/Loaders options
this.sassOptions = {
resolve_url_loader: true
};

// Features/Loaders options callbacks
this.postCssLoaderOptionsCallback = () => {};
this.sassLoaderOptionsCallback = () => {};
this.lessLoaderOptionsCallback = () => {};
this.babelConfigurationCallback = () => {};
this.vueLoaderOptionsCallback = () => {};
this.tsConfigurationCallback = () => {};

// Plugins options
this.cleanWebpackPluginPaths = ['**/*'];

// Plugins callbacks
this.cleanWebpackPluginOptionsCallback = () => {};
this.definePluginOptionsCallback = () => {};
this.extractTextPluginOptionsCallback = () => {};
this.forkedTypeScriptTypesCheckOptionsCallback = () => {};
this.useImagesLoader = true;
this.useFontsLoader = true;
this.configuredFilenames = {};
this.manifestPluginOptionsCallback = function() {};
this.friendlyErrorsPluginOptionsCallback = () => {};
this.loaderOptionsPluginOptionsCallback = () => {};
this.manifestPluginOptionsCallback = () => {};
this.uglifyJsPluginOptionsCallback = () => {};
}

getContext() {
Expand Down Expand Up @@ -118,6 +138,38 @@ class WebpackConfig {
this.manifestKeyPrefix = manifestKeyPrefix;
}

configureDefinePlugin(definePluginOptionsCallback = () => {}) {
if (typeof definePluginOptionsCallback !== 'function') {
throw new Error('Argument 1 to configureDefinePlugin() must be a callback function');
}

this.definePluginOptionsCallback = definePluginOptionsCallback;
}

configureExtractTextPlugin(extractTextPluginOptionsCallback = () => {}) {
if (typeof extractTextPluginOptionsCallback !== 'function') {
throw new Error('Argument 1 to configureExtractTextPlugin() must be a callback function');
}

this.extractTextPluginOptionsCallback = extractTextPluginOptionsCallback;
}

configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) {
if (typeof friendlyErrorsPluginOptionsCallback !== 'function') {
throw new Error('Argument 1 to configureFriendlyErrorsPlugin() must be a callback function');
}

this.friendlyErrorsPluginOptionsCallback = friendlyErrorsPluginOptionsCallback;
}

configureLoaderOptionsPlugin(loaderOptionsPluginOptionsCallback = () => {}) {
if (typeof loaderOptionsPluginOptionsCallback !== 'function') {
throw new Error('Argument 1 to configureLoaderOptionsPlugin() must be a callback function');
}

this.loaderOptionsPluginOptionsCallback = loaderOptionsPluginOptionsCallback;
}

configureManifestPlugin(manifestPluginOptionsCallback = () => {}) {
if (typeof manifestPluginOptionsCallback !== 'function') {
throw new Error('Argument 1 to configureManifestPlugin() must be a callback function');
Expand All @@ -126,6 +178,14 @@ class WebpackConfig {
this.manifestPluginOptionsCallback = manifestPluginOptionsCallback;
}

configureUglifyJsPlugin(uglifyJsPluginOptionsCallback = () => {}) {
if (typeof uglifyJsPluginOptionsCallback !== 'function') {
throw new Error('Argument 1 to configureUglifyJsPlugin() must be a callback function');
}

this.uglifyJsPluginOptionsCallback = uglifyJsPluginOptionsCallback;
}

/**
* Returns the value that should be used as the publicPath,
* which can be overridden by enabling the webpackDevServer
Expand Down Expand Up @@ -311,8 +371,18 @@ class WebpackConfig {
this.configuredFilenames = configuredFilenames;
}

cleanupOutputBeforeBuild() {
cleanupOutputBeforeBuild(paths = ['**/*'], cleanWebpackPluginOptionsCallback = () => {}) {
if (!Array.isArray(paths)) {
throw new Error('Argument 1 to cleanupOutputBeforeBuild() must be an Array of paths - e.g. [\'**/*\']');
}

if (typeof cleanWebpackPluginOptionsCallback !== 'function') {
throw new Error('Argument 2 to cleanupOutputBeforeBuild() must be a callback function');
}

this.cleanupOutput = true;
this.cleanWebpackPluginPaths = paths;
this.cleanWebpackPluginOptionsCallback = cleanWebpackPluginOptionsCallback;
}

autoProvideVariables(variables) {
Expand Down
10 changes: 5 additions & 5 deletions lib/config-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const loaderOptionsPluginUtil = require('./plugins/loader-options');
const versioningPluginUtil = require('./plugins/versioning');
const variableProviderPluginUtil = require('./plugins/variable-provider');
const cleanPluginUtil = require('./plugins/clean');
const commonChunksPluginUtil = require('./plugins/common-chunks');
const commonsChunksPluginUtil = require('./plugins/commons-chunks');
const definePluginUtil = require('./plugins/define');
const uglifyPluginUtil = require('./plugins/uglify');
const friendlyErrorPluginUtil = require('./plugins/friendly-errors');
Expand Down Expand Up @@ -218,15 +218,15 @@ class ConfigGenerator {

variableProviderPluginUtil(plugins, this.webpackConfig);

cleanPluginUtil(plugins, this.webpackConfig, ['**/*']);
cleanPluginUtil(plugins, this.webpackConfig);

commonChunksPluginUtil(plugins, this.webpackConfig);
commonsChunksPluginUtil(plugins, this.webpackConfig);

// todo - options here should be configurable
definePluginUtil(plugins, this.webpackConfig);

uglifyPluginUtil(plugins, this.webpackConfig);

let friendlyErrorPlugin = friendlyErrorPluginUtil();
const friendlyErrorPlugin = friendlyErrorPluginUtil(this.webpackConfig);
plugins.push(friendlyErrorPlugin);

assetOutputDisplay(plugins, this.webpackConfig, friendlyErrorPlugin);
Expand Down
18 changes: 12 additions & 6 deletions lib/plugins/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,26 @@ const CleanWebpackPlugin = require('clean-webpack-plugin');
*
* @param {Array} plugins to push to
* @param {WebpackConfig} webpackConfig read only variable
* @param {Array} paths to clean
* @param {Object} cleanUpOptions
* @return {void}
*/
module.exports = function(plugins, webpackConfig, paths, cleanUpOptions = {}) {
module.exports = function(plugins, webpackConfig) {

if (!webpackConfig.cleanupOutput) {
return;
}

let config = Object.assign({}, cleanUpOptions, {
const cleanWebpackPluginOptions = {
root: webpackConfig.outputPath,
verbose: false,
});
};

plugins.push(new CleanWebpackPlugin(paths, config));
webpackConfig.cleanWebpackPluginOptionsCallback.apply(
cleanWebpackPluginOptions,
[cleanWebpackPluginOptions]
);

plugins.push(new CleanWebpackPlugin(
webpackConfig.cleanWebpackPluginPaths,
cleanWebpackPluginOptions
));
};
File renamed without changes.
15 changes: 9 additions & 6 deletions lib/plugins/define.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,24 @@ const webpack = require('webpack');
/**
* @param {Array} plugins
* @param {WebpackConfig} webpackConfig
* @param {Object} defineOptions
* @return {void}
*/
module.exports = function(plugins, webpackConfig, defineOptions = {}) {
module.exports = function(plugins, webpackConfig) {

if (!webpackConfig.isProduction()) {
return;
}

let defineConfig = Object.assign({}, defineOptions, {
const definePluginOptions = {
'process.env': {
NODE_ENV: '"production"'
}
});
let define = new webpack.DefinePlugin(defineConfig);
};

plugins.push(define);
webpackConfig.definePluginOptionsCallback.apply(
definePluginOptions,
[definePluginOptions]
);

plugins.push(new webpack.DefinePlugin(definePluginOptions));
};
Loading