Issue 1:
Feature request

What is the expected behavior?

I have a plugin which creates a child compiler. And I want to apply the same optimization plugins that

webpack/lib/WebpackOptionsApply.js

Lines 293 to 456
in
a16909c

if (options.optimization.removeAvailableModules) {

const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");

new RemoveParentModulesPlugin().apply(compiler);

}

if (options.optimization.removeEmptyChunks) {

const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");

new RemoveEmptyChunksPlugin().apply(compiler);

}

if (options.optimization.mergeDuplicateChunks) {

const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");

new MergeDuplicateChunksPlugin().apply(compiler);

}

if (options.optimization.flagIncludedChunks) {

const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");

new FlagIncludedChunksPlugin().apply(compiler);

}

if (options.optimization.sideEffects) {

const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");

new SideEffectsFlagPlugin(

options.optimization.sideEffects === true

).apply(compiler);

}

if (options.optimization.providedExports) {

const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");

new FlagDependencyExportsPlugin().apply(compiler);

}

if (options.optimization.usedExports) {

const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");

new FlagDependencyUsagePlugin(

options.optimization.usedExports === "global"

).apply(compiler);

}

if (options.optimization.innerGraph) {

const InnerGraphPlugin = require("./optimize/InnerGraphPlugin");

new InnerGraphPlugin().apply(compiler);

}

if (options.optimization.mangleExports) {

const MangleExportsPlugin = require("./optimize/MangleExportsPlugin");

new MangleExportsPlugin(

options.optimization.mangleExports !== "size"

).apply(compiler);

}

if (options.optimization.concatenateModules) {

const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin");

new ModuleConcatenationPlugin().apply(compiler);

}

if (options.optimization.splitChunks) {

const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");

new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);

}

if (options.optimization.runtimeChunk) {

const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");

new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler);

}

if (!options.optimization.emitOnErrors) {

const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin");

new NoEmitOnErrorsPlugin().apply(compiler);

}

if (options.optimization.realContentHash) {

const RealContentHashPlugin = require("./optimize/RealContentHashPlugin");

new RealContentHashPlugin({

hashFunction: options.output.hashFunction,

hashDigest: options.output.hashDigest

}).apply(compiler);

}

if (options.optimization.checkWasmTypes) {

const WasmFinalizeExportsPlugin = require("./wasm-sync/WasmFinalizeExportsPlugin");

new WasmFinalizeExportsPlugin().apply(compiler);

}

const moduleIds = options.optimization.moduleIds;

if (moduleIds) {

switch (moduleIds) {

case "natural": {

const NaturalModuleIdsPlugin = require("./ids/NaturalModuleIdsPlugin");

new NaturalModuleIdsPlugin().apply(compiler);

break;

}

case "named": {

const NamedModuleIdsPlugin = require("./ids/NamedModuleIdsPlugin");

new NamedModuleIdsPlugin().apply(compiler);

break;

}

case "hashed": {

const WarnDeprecatedOptionPlugin = require("./WarnDeprecatedOptionPlugin");

const HashedModuleIdsPlugin = require("./ids/HashedModuleIdsPlugin");

new WarnDeprecatedOptionPlugin(

"optimization.moduleIds",

"hashed",

"deterministic"

).apply(compiler);

new HashedModuleIdsPlugin().apply(compiler);

break;

}

case "deterministic": {

const DeterministicModuleIdsPlugin = require("./ids/DeterministicModuleIdsPlugin");

new DeterministicModuleIdsPlugin().apply(compiler);

break;

}

case "size": {

const OccurrenceModuleIdsPlugin = require("./ids/OccurrenceModuleIdsPlugin");

new OccurrenceModuleIdsPlugin({

prioritiseInitial: true

}).apply(compiler);

break;

}

default:

throw new Error(

`webpack bug: moduleIds: ${moduleIds} is not implemented`

);

}

}

const chunkIds = options.optimization.chunkIds;

if (chunkIds) {

switch (chunkIds) {

case "natural": {

const NaturalChunkIdsPlugin = require("./ids/NaturalChunkIdsPlugin");

new NaturalChunkIdsPlugin().apply(compiler);

break;

}

case "named": {

const NamedChunkIdsPlugin = require("./ids/NamedChunkIdsPlugin");

new NamedChunkIdsPlugin().apply(compiler);

break;

}

case "deterministic": {

const DeterministicChunkIdsPlugin = require("./ids/DeterministicChunkIdsPlugin");

new DeterministicChunkIdsPlugin().apply(compiler);

break;

}

case "size": {

const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");

new OccurrenceChunkIdsPlugin({

prioritiseInitial: true

}).apply(compiler);

break;

}

case "total-size": {

const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");

new OccurrenceChunkIdsPlugin({

prioritiseInitial: false

}).apply(compiler);

break;

}

default:

throw new Error(

`webpack bug: chunkIds: ${chunkIds} is not implemented`

);

}

}

if (options.optimization.nodeEnv) {

const DefinePlugin = require("./DefinePlugin");

new DefinePlugin({

"process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv)

}).apply(compiler);

}

if (options.optimization.minimize) {

for (const minimizer of options.optimization.minimizer) {

if (typeof minimizer === "function") {

minimizer.call(compiler, compiler);

} else if (minimizer !== "...") {

minimizer.apply(compiler);

}

}

}

is doing into my child compiler. Otherwise, I have to duplicate the whole block and then paste it into my plugin.

What is motivation or use case for adding/changing the behavior?

Same as previous.

How should this be implemented in your opinion?

Just put the whole block in a function and then expose it.

Are you willing to work on this yourself?

yes

Issue 2:
Do you want to request a feature or report a bug?

Bug

What is the current behavior?

ContextReplace seems to cause duplicate (Wasted) rebuilds in watch mode.

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?

A single build and then subsequent builds upon file change.

If this is a feature request, what is motivation or use case for changing the behavior?

Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.

Here is a log output demonstrating the secondary build at the end.

> webpack --watch --progress --display-error-details

0% compiling
Webpack is watching the files…

10% building modules 0/2 modules 2 active ...ate\entries\coreEntryInstanceAdmin.js
10% building modules 2/2 modules 0 active
10% building modules 2/3 modules 1 active ...apps\instance\coreAppInstanceAdmin.js
10% building modules 2/4 modules 2 active ...e\apps\instance\coreAppInstanceWww.js
10% building modules 4/4 modules 0 active
10% building modules 4/6 modules 2 active ...Project\core\private\lib\coreMixin.js
10% building modules 4/8 modules 4 active ...e\private\apps\base\coreAppBaseWww.js
10% building modules 8/8 modules 0 active
10% building modules 8/10 modules 2 active ...scss\themes\instance\admin\theme.scss
11% building modules 10/11 modules 1 active ...core\private\apps\base\coreAppBase.js
11% building modules 10/12 modules 2 active ...scss\themes\instance\admin\theme.scss
11% building modules 10/19 modules 9 active ...core\private\modules\coreApi\index.js
11% building modules 11/19 modules 8 active ...core\private\modules\coreApi\index.js
11% building modules 11/21 modules 10 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
11% building modules 13/21 modules 8 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
11% building modules 14/21 modules 7 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
11% building modules 15/21 modules 6 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
11% building modules 16/21 modules 5 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
12% building modules 17/21 modules 4 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
12% building modules 17/22 modules 5 active ...vestergaard-company\js-mixin\index.js
12% building modules 18/25 modules 7 active ...roject\core\private\lib\coreLoader.js
12% building modules 18/27 modules 9 active ...hahnamaProject\core\lib\coreShared.js
12% building modules 19/27 modules 8 active ...hahnamaProject\core\lib\coreShared.js
12% building modules 22/27 modules 5 active ...hahnamaProject\core\lib\coreShared.js
12% building modules 22/29 modules 7 active ...t\core\private\templates\coreMenu.pug
12% building modules 23/29 modules 6 active ...t\core\private\templates\coreMenu.pug
12% building modules 24/29 modules 5 active ...t\core\private\templates\coreMenu.pug
12% building modules 24/30 modules 6 active ...t\core\private\lib\coreReadyTarget.js
13% building modules 25/36 modules 11 active ...rd-company\js-mixin\src\Utils\wrap.js
13% building modules 28/37 modules 9 active ...ect\node_modules\pug-runtime\index.js
13% building modules 30/37 modules 7 active ...ect\node_modules\pug-runtime\index.js
13% building modules 33/39 modules 6 active ...node_modules\bootstrap\dist\js\npm.js
14% building modules 35/41 modules 6 active ...mixins\shared\coreMixinSharedMenu.pug
14% building modules 37/43 modules 6 active ...generic\coreLoaderGenericListItems.js
14% building modules 37/45 modules 8 active ...oreComponentFormInputSelect\loader.js
14% building modules 37/46 modules 9 active ...oaders\coreLoaderFeatureTestWicked.js
14% building modules 38/46 modules 8 active ...oaders\coreLoaderFeatureTestWicked.js
14% building modules 39/46 modules 7 active ...oaders\coreLoaderFeatureTestWicked.js
14% building modules 40/46 modules 6 active ...oaders\coreLoaderFeatureTestWicked.js
14% building modules 40/47 modules 7 active ...ct\node_modules\jquery\dist\jquery.js
14% building modules 41/47 modules 6 active ...oaders\coreLoaderFeatureTestWicked.js
15% building modules 42/49 modules 7 active ...ct\node_modules\jquery\dist\jquery.js
15% building modules 42/51 modules 9 active ...ct\node_modules\bootstrap\js\alert.js
15% building modules 42/61 modules 19 active ...ct\node_modules\bootstrap\js\affix.js
15% building modules 43/61 modules 18 active ...ct\node_modules\bootstrap\js\affix.js
15% building modules 46/62 modules 16 active ...oject\node_modules\debug\src\debug.js
15% building modules 46/63 modules 17 active ...oject\node_modules\process\browser.js
15% building modules 49/63 modules 14 active ...oject\node_modules\process\browser.js
16% building modules 50/63 modules 13 active ...oject\node_modules\process\browser.js
16% building modules 51/63 modules 12 active ...oject\node_modules\process\browser.js
16% building modules 52/63 modules 11 active ...oject\node_modules\process\browser.js
16% building modules 53/63 modules 10 active ...oject\node_modules\process\browser.js
16% building modules 54/63 modules 9 active ...oject\node_modules\process\browser.js
16% building modules 55/63 modules 8 active ...oject\node_modules\process\browser.js
16% building modules 56/63 modules 7 active ...oject\node_modules\process\browser.js
16% building modules 57/63 modules 6 active ...oject\node_modules\process\browser.js
16% building modules 58/63 modules 5 active ...oject\node_modules\process\browser.js
17% building modules 60/63 modules 3 active ...oject\node_modules\process\browser.js
17% building modules 62/65 modules 3 active ...ode_modules\webpack\buildin\global.js
17% building modules 64/68 modules 4 active ...eComponentFormInputSelect\styles.scss
17% building modules 64/70 modules 6 active ...reComponentFormInputSelect\mixins.pug
18% building modules 67/71 modules 4 active ...hnamaProject\node_modules\ms\index.js
18% building modules 67/73 modules 6 active ...re\templates\mixins\coreMixinForm.pug
18% building modules 71/76 modules 5 active ..._modules\select2\dist\css\select2.css
18% building modules 72/76 modules 4 active ..._modules\select2\dist\css\select2.css
18% building modules 73/76 modules 3 active ..._modules\select2\dist\css\select2.css
18% building modules 74/76 modules 2 active ...e\scss\themes\instance\www\theme.scss
19% building modules 75/76 modules 1 active ...scss\themes\instance\admin\theme.scss
19% building modules 76/77 modules 1 active ..._modules\css-loader\lib\url\escape.js
19% building modules 77/77 modules 0 active
19% building modules 77/83 modules 6 active ...fonts\fontawesome-webfont.ttf?v=4.7.0
19% building modules 78/83 modules 5 active ...fonts\fontawesome-webfont.ttf?v=4.7.0
19% building modules 79/83 modules 4 active ...fonts\fontawesome-webfont.ttf?v=4.7.0
19% building modules 80/83 modules 3 active ...fonts\fontawesome-webfont.ttf?v=4.7.0
19% building modules 82/83 modules 1 active ...fonts\fontawesome-webfont.svg?v=4.7.0
71% sealing
74% module optimization
75% advanced module optimization
76% basic chunk optimization pass 2
19% building modules 83/84 modules 1 active ...e\scss\themes\instance\www\theme.scss
19% building modules 83/85 modules 2 active ...scss\themes\instance\admin\theme.scss
20% building modules 84/85 modules 1 active ...e\scss\themes\instance\www\theme.scss
85% chunk reviving
87% chunk id optimization
90% chunk assets processing
95% emittingHash: 4c1f5b159f459c5c35b4

Version: webpack 3.10.0
Time: 4648ms
Asset Size Chunks Chunk Names
js/loader2.chunk.js 81 bytes 2 [emitted] loader2
fonts/fontawesome-webfont.674f50d287a8c48dc19ba404d20fe713.eot 166 kB [emitted]
fonts/fontawesome-webfont.fee66e712a8a08eef5805a46892932ad.woff 98 kB [emitted]
fonts/fontawesome-webfont.b06871f281fee6b241d60582ae9369b9.ttf 166 kB [emitted]
fonts/fontawesome-webfont.912ec66d7572ff821749319396470bde.svg 444 kB [emitted] [big]
js/loader1.chunk.js 181 kB 0 [emitted] loader1
js/loader3.chunk.js 2.05 kB 1 [emitted] loader3
fonts/fontawesome-webfont.af7ae505a9eed503f8b8e6982036873e.woff2 77.2 kB [emitted]
js/loader0.chunk.js 743 bytes 3 [emitted] loader0
js/instance.admin.bundle.js 2.53 kB 4 [emitted] instance.admin
js/instance.www.bundle.js 1.69 kB 5 [emitted] instance.www
js/vendor.bundle.js 482 kB 6 [emitted] [big] vendor.bundle
css/instance.www.bundle.css 466 kB 5 [emitted] [big] instance.www
css/instance.admin.bundle.css 466 kB 4 [emitted] [big] instance.admin
[4] ./lib/coreMixin.js 258 bytes {6} [built]
[10] ./apps/base/coreAppBaseWww.js 861 bytes {6} [built]
[14] ./templates/coreMenu.pug 8.96 kB {6} [built]
[15] ./apps/instance/coreAppInstance.js 283 bytes {6} [built]
[19] ./entries/coreEntryInstanceWww.js 213 bytes {5} [built]
[20] ./scss/themes/instance/www/theme.scss 41 bytes {5} [built]
[22] ./apps/instance/coreAppInstanceWww.js 358 bytes {5} [built]
[27] ./apps/base/coreAppBase.js 3.67 kB {6} [built]
[51] ./modules/coreForm/index.js 9.73 kB {6} [built]
[53] ./entries/coreEntryInstanceAdmin.js 217 bytes {4} [built]
[54] ./scss/themes/instance/admin/theme.scss 41 bytes {4} [built]
[55] ./apps/instance/coreAppInstanceAdmin.js 368 bytes {4} [built]
[56] ./apps/base/coreAppBaseAdmin.js 384 bytes {4} [built]
[81] D:/dev/projects/nodejs/shahnamaProject/node_modules/css-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/resolve-url-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/sass-loader/lib/loader.js?&precision=10!./scss/themes/instance/www/theme.scss 496 kB [built]
[82] D:/dev/projects/nodejs/shahnamaProject/node_modules/css-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/resolve-url-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/sass-loader/lib/loader.js?&precision=10!./scss/themes/instance/admin/theme.scss 496 kB [built]
+ 68 hidden modules
Child extract-text-webpack-plugin ../../node_modules/extract-text-webpack-plugin/dist ../../node_modules/css-loader/index.js!../../node_modules/resolve-url-loader/index.js!../../node_modules/sass-loader/lib/loader.js?&precision=10!scss/themes/instance/admin/theme.scss:
5 assets
[0] D:/dev/projects/nodejs/shahnamaProject/node_modules/css-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/resolve-url-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/sass-loader/lib/loader.js?&precision=10!./scss/themes/instance/admin/theme.scss 496 kB {0} [built]
+ 8 hidden modules
Child extract-text-webpack-plugin ../../node_modules/extract-text-webpack-plugin/dist ../../node_modules/css-loader/index.js!../../node_modules/resolve-url-loader/index.js!../../node_modules/sass-loader/lib/loader.js?&precision=10!scss/themes/instance/www/theme.scss:
5 assets
[0] D:/dev/projects/nodejs/shahnamaProject/node_modules/css-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/resolve-url-loader!D:/dev/projects/nodejs/shahnamaProject/node_modules/sass-loader/lib/loader.js?&precision=10!./scss/themes/instance/www/theme.scss 496 kB {0} [built]
+ 8 hidden modules
10% building modules 0/1 modules 1 active ...\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/
10% building modules 1/2 modules 1 active ...ComponentFormInputReference\loader.js
86% chunk order optimization
87% chunk id optimization
88% hashing
95% emitting
Hash: 54257b4d40c1dff4ccc9
Version: webpack 3.10.0
Time: 21889ms
Asset Size Chunks Chunk Names
js/loader1.chunk.js 197 kB 0 [emitted] loader1
js/vendor.bundle.js 465 kB 6 [emitted] [big] vendor.bundle
css/instance.www.bundle.css 466 kB 5 [emitted] [big] instance.www
css/instance.admin.bundle.css 466 kB 4 [emitted] [big] instance.admin
+ 5 hidden assets
[34] D:/dev/projects/nodejs/shahnamaProject lazy [\/\\](core|instance)[\/\\](?:(?:components|features[\/\\].*[\/\\]components)[\/\\].*\1Component[a-zA-Z0-9]*[\/\\]loader\.js$|(?:private|features[\/\\][a-zA-Z0-9-_]*)[\/\\](?:[a-zA-Z0-9-_]*[\/\\])*loaders[\/\\](?:[a-zA-Z0-9-_]*[\/\\])*\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$) 160 bytes {6} [built]
+ 70 hidden modules

I don't know if this is related to the webpack watcher triggering on files it generates? I have been trying for a few days now to resolve this issue but need some help.

config

'use strict';

//module imports
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const MinifyPlugin = require("babel-minify-webpack-plugin");

//custom plugin imports
const IncludeExcludePlugin = require('./webpack/plugins/IncludeExcludePlugin.js');
const WatchOffsetPlugin = require('./webpack/plugins/WatchOffsetPlugin.js');
const CoreProtocolPlugin = require('./webpack/plugins/CoreProtocolPlugin.js');

//local imports
const apps = require('./core/coreApps');

//constants
const development = process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'development';
const sassPrecision = 10;//this is important! precision fix detailed here: https://github.com/twbs/bootstrap-sass/issues/409

//build flags
const buildMaps = false;
const buildMonkeyApps = false;
const buildBabel = false;
const buildFonts = true;
const buildImages = true;
const buildLoaders = true;

//regexp patterns
const monkeyPattern = /external[\\\/]monkey[\\\/]([a-z0-9_-]+)[\\\/]app[\\\/]main.js$/i;
const monkeyDataPattern = /external[\\\/]monkey[\\\/]([a-z0-9_-]+)[\\\/]app[\\\/]data([a-z0-9-_@\\\/]*)[\\\/]([a-z0-9-_@]+\.(?:png|jpg|jpeg|gif|svg|txt|ttf|json))$/i;

//functions
function JavascriptEntryPoints() {
const entries = {};

//only include entry points enabled in teh config
if (apps.instance.www.enabled) {
entries['instance.www'] = './entries/coreEntryInstanceWww.js';
}

if (apps.instance.admin.enabled) {
entries['instance.admin'] = './entries/coreEntryInstanceAdmin.js';
}

if (apps.instance.embed.enabled) {
entries['instance.embed'] = './entries/coreEntryInstanceEmbed.js';
}

if (apps.control.www.enabled) {
entries['control.www'] = './entries/coreEntryControlWww.js';
}

if (apps.owner.enabled) {
entries['owner.www'] = './entries/coreEntryOwnerWww.js';
}

if (apps.owner.admin.enabled) {
entries['owner.admin'] = './entries/coreEntryOwnerAdmin.js';
}

if (apps.owner.embed.enabled) {
entries['owner.embed'] = './entries/coreEntryOwnerEmbed.js';
}

if (Object.keys(entries).length === 0) {
console.error(`no entries defined, check you have at least 1 app enabled in instanceApps.js`);
}

return entries;
}

//the config
module.exports = {
watch: false,
watchOptions: {
poll: true,
ignored: [
/(^|[\\/])public($|[\\/])/,
/(^|[\\/])norepo($|[\\/])/,
/(^|[\\/])node_modules($|[\\/])/,
/node_modules/,
/public[\\/].*js/,
/public[\\/].*css/,
],
},

context: path.resolve(__dirname, 'core/private'),//root directory for finding entry points (the core entry points import from the instance entry points)

entry: JavascriptEntryPoints(),

output: {
path: path.resolve(__dirname, 'public'),
filename: 'js/[name].bundle.js',
sourceMapFilename: 'js/[file].map',
chunkFilename: 'js/[name].chunk.js',
publicPath: '/',
},

resolve: {
modules: ['node_modules'],
plugins: [new CoreProtocolPlugin()],
alias: Object.assign({}, ...[{
//module fixes!
moment$: 'moment/moment.js',//fixes: https://github.com/moment/moment/issues/2979
'TweenMax': 'gsap',
},

//filter undefined to allow optional build!
].filter(alias => !!alias)),
},

externals: {
settings: 'settings',//the server request output from core!
},

module: {
rules: [
//node_module fixes
{
test: /node_modules[\\/]typed\.js[\\/].*\.js$/,
use: [
{
loader: 'babel-loader',
options: {
plugins: [require('babel-plugin-transform-object-rest-spread')],
},
},
],
},

//pug
{
test: /\.pug$/,
use: [
{
loader: 'pug-loader',
query: {
//root: path.resolve(__dirname, './core/private/empty.scss'),
},
},
],
},

//css imports
{
test: /\.scss|\.css$/,
use: ExtractTextPlugin.extract({
fallback: ['style-loader'],
use: [
{
loader: 'css-loader'
},
{
loader: 'resolve-url-loader'
},
{
loader: 'sass-loader',
query: (sassPrecision?'&precision='+sassPrecision:'')+(!buildMaps?'':'&sourceMap'),
}
],
allChunks: true,
}),
},

//monkey apps
{
test: monkeyPattern,
use: [
!buildMonkeyApps?{loader:'ignore-loader'}:{
loader: 'exports-loader',
query: 'BBMonkeyGame',
},
],
},

//monkey data
//this imports all monkey apps into public/monkey/[appFolderName]/data/*
//we then need to setup static express routes to route the data per page e.g.
//app.use('/admin/app/data', express.static(path.join(__dirname, './public/monkey/appPreview/data')));
{
test: monkeyDataPattern,
use: [
!buildMonkeyApps?{loader:'ignore-loader'}:{
loader: 'file-loader',
query: {
regExp: monkeyDataPattern,
name: 'monkey/[1]/app/data/[2]/[name].[ext]',
},
},
],
},

//fonts (copy to /public/fonts)
//as we want .svgs to be treated as "images" we need to manually specify any inclusions here
!buildFonts?undefined:{
test: /(fontawesome.*\.svg|\.(ttf|otf|eot|woff(2)?))(\?[a-z0-9]+)?$/,
exclude: [
monkeyDataPattern,
],
use: [
{
loader: 'file-loader',
query: {
name: 'fonts/[name].[hash].[ext]',
},
},
],
},

//images (copy to /public/images)
!buildImages?undefined:{
test: /\.(jpe?g|gif|png|svg)$/,
exclude: [
//make sure to exclude any manually defined font .svgs here
/fontawesome.*\.svg(\?[a-z0-9]+)?$/,
],
use: [
{
loader: 'file-loader',
query: {
emitFile: true,
name: 'images/[name].[hash].[ext]',
},
},
],
},

//babel conversion
!buildBabel?undefined:{
test: /\.js$/,
exclude: [
/(node_modules)/,
monkeyPattern,
],
use: [
{
loader: 'babel-loader',
},
],
},

//expose globals to modules!
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
query: 'jQuery',
},
{
loader: 'expose-loader',
query: '$',
},
],

},
/*
{
test: require.resolve('gsap'),
use: [
{
loader: 'expose-loader',
query: 'TweenMax',
},
{
loader: 'expose-loader',
query: 'TimelineMax',
},
],
},
*/

//filter undefined rules
].filter(rule => !!rule),
},

plugins: [
//custom webpack plugins to fix sheeeet
new IncludeExcludePlugin(),
new WatchOffsetPlugin(),

//allow import of css in js
new ExtractTextPlugin({
//convert bundle [name] (js/blah.bundle.js) into css/blah.bundle.css
filename: getPath => 'css/'+path.basename(getPath('[name]'), '.js')+'.bundle.css',
allChunks: false,//allows for imported chunks to add scss to bundle
}),

//setup .map file generation
!buildMaps?undefined:new webpack.SourceMapDevToolPlugin({
filename: '[file].map',
exclude: ['vendor.bundle.js', /\.css$/, /\.scss$/],
}),

//auto load modules (really we should never be doing this!)
new webpack.ProvidePlugin({
//jQuery: 'jquery',
//$: 'jquery',
//moment: 'moment',
}),

//limit moment locales
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en/),

//allow dynamic import using custom @loader syntax.
//we are allowing the @loader syntax complete access to the root (of the app) file system.
//we limit what is processed in the private/coreAppBase import comment tags.
//we limit what files are included via the ContextReplacementPlugin regexp below!

//help: https://iamakulov.com/notes/webpack-contextreplacementplugin/

new webpack.IgnorePlugin(/^@loader/, /node_modules/),

!buildLoaders?new webpack.IgnorePlugin(/^@loader/):new webpack.ContextReplacementPlugin(
/^@loader/,
path.resolve(__dirname, './'),
true,
/[/\\](core|instance)[/\\](?:(?:components|features[/\\].*[/\\]components)[/\\].*\1Component[a-zA-Z0-9]*[/\\]loader\.js$|(?:private|features[/\\][a-zA-Z0-9-_]*)[/\\](?:[a-zA-Z0-9-_]*[/\\])*loaders[/\\](?:[a-zA-Z0-9-_]*[/\\])*\1Loader[A-Z0-9][a-zA-Z0-9-_]*\.js$)/,
),

//generate vendor
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor.bundle',
filename: 'js/vendor.bundle.js',
}),

//force common dependencies (for lazy load) into chunk
new webpack.optimize.CommonsChunkPlugin({
name: Object.keys(JavascriptEntryPoints()),
children: true,
minChunks: 4,
async: 'common',
}),

//plugins based on environment mode
].concat(development?[
//development
]:[
//production
new MinifyPlugin({
mangle: {
//need these to protect our this.constructor.name code!
keepClassName: true,
keepFnName: true,
},
}, {}),

//filter null plugins (allows inline conditional plugins)
]).filter(plugin => !!plugin),
};