From 5b383735031b5c4296e34088766d8ab273c6e43a Mon Sep 17 00:00:00 2001 From: Mat Brown Date: Sat, 19 Nov 2016 18:38:26 -0500 Subject: [PATCH] More resilient Webpack configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make Webpack configuration less sensitive to the specific layout of `node_modules`. Extracted from https://github.com/popcodeorg/popcode/pull/561, which may need to be put on hold until yarn properly handles optional dependencies. Most usefully, changes the logic for loading stylelint rule modules—only load rules that are whitelisted, instead of loading all rules unless they’re blacklisted. Rules themselves often have external library dependencies, so this trims down the gzipped bundle size of the linter bundle from 415K to 355K. --- webpack.config.js | 76 +++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index c8ed8dfffe..0550814b6e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,9 +1,31 @@ const path = require('path'); const webpack = require('webpack'); const escapeRegExp = require('lodash/escapeRegExp'); +const startsWith = require('lodash/startsWith'); +const map = require('lodash/map'); +const includes = require('lodash/includes'); function matchModule(modulePath) { - return new RegExp(`\\/node_modules\\/${escapeRegExp(modulePath)}`); + const modulePattern = new RegExp( + `\\/node_modules\\/${escapeRegExp(modulePath)}` + ); + const moduleDependencyPattern = new RegExp( + `\\/node_modules\\/${escapeRegExp(modulePath)}\\/node_modules` + ); + + return (filePath) => + modulePattern.test(filePath) && !moduleDependencyPattern.test(filePath); +} + +function directoryContentsExcept(directory, exceptions) { + const fullExceptions = map( + exceptions, + (exception) => path.resolve(directory, exception) + ); + + return (filePath) => + startsWith(filePath, path.resolve(directory)) && + !includes(fullExceptions, filePath); } module.exports = { @@ -22,14 +44,14 @@ module.exports = { path.resolve(__dirname, 'src'), path.resolve(__dirname, 'spec'), ], - loaders: ['babel-loader', 'transform/cacheable?brfs-babel'], + loaders: ['babel-loader', 'transform-loader/cacheable?brfs-babel'], }, { test: /\.js$/, include: [ path.resolve(__dirname, 'node_modules/htmllint'), ], - loader: 'transform/cacheable?bulkify', + loader: 'transform-loader/cacheable?bulkify', }, { test: /\.js$/, @@ -37,21 +59,19 @@ module.exports = { path.resolve(__dirname, 'node_modules/PrettyCSS'), path.resolve(__dirname, 'node_modules/css'), ], - loader: 'transform/cacheable?brfs', + loader: 'transform-loader/cacheable?brfs', }, { test: /\.js$/, include: [ path.resolve(__dirname, 'node_modules/postcss/lib/previous-map'), - path.resolve(__dirname, 'node_modules/stylelint/dist/getPostcssResult'), - path.resolve(__dirname, - 'node_modules/stylelint/node_modules/sugarss/node_modules/postcss/lib/previous-map' - ), - path.resolve(__dirname, - 'node_modules/stylelint/node_modules/postcss-scss/node_modules/postcss/lib/previous-map' + path.resolve( + __dirname, + 'node_modules/stylelint/dist/getPostcssResult' ), + matchModule('postcss/lib/previous-map'), ], - loader: 'string-replace', + loader: 'string-replace-loader', query: { search: /require\(['"]fs['"]\)/, replace: '{}', @@ -65,15 +85,15 @@ module.exports = { 'node_modules/stylelint/dist/utils/isAutoprefixable' ), ], - loader: 'substitute', + loader: 'substitute-loader', query: {content: '() => false'}, }, { test: /\.js$/, include: [ - path.resolve(__dirname, 'node_modules/redux'), - path.resolve(__dirname, 'node_modules/lodash-es'), - path.resolve(__dirname, 'node_modules/github-api'), + matchModule('redux'), + matchModule('lodash-es'), + matchModule('github-api'), ], loader: 'babel-loader', }, @@ -82,7 +102,7 @@ module.exports = { include: [ path.resolve(__dirname, 'node_modules/loop-protect'), ], - loader: 'imports?define=>false', + loader: 'imports-loader?define=>false', }, { include: [ @@ -91,26 +111,30 @@ module.exports = { 'node_modules/html-inspector/html-inspector.js' ), ], - loader: 'imports?window=>{}!exports?window.HTMLInspector', + loader: + 'imports-loader?window=>{}!exports-loader?window.HTMLInspector', }, { test: /\.js$/, include: [ path.resolve(__dirname, 'node_modules/brace/worker'), - path.resolve( - __dirname, - 'node_modules/stylelint/dist/rules/no-unsupported-browser-features' - ), - path.resolve( - __dirname, - 'node_modules/stylelint/dist/rules/no-browser-hacks' - ), matchModule('autoprefixer'), matchModule('postcss-scss'), matchModule('postcss-less'), matchModule('sugarss'), ], - loader: 'null', + loader: 'null-loader', + }, + { + test: /\.js$/, + include: directoryContentsExcept( + 'node_modules/stylelint/dist/rules', + [ + 'index.js', + 'declaration-block-trailing-semicolon/index.js', + ] + ), + loader: 'null-loader', }, { test: /\.json$/,