Repository: styleguidist/react-styleguidist
Pull request #569 (2017-08-09 23:01:42)

Using devtools with react-stylegudist #456
The `devtool` setting in your webpack config will now get passed through for non-production environments, e.g., running the hot-reloading server.

It will still get ignored for production builds.

Docs updated, and added a test.

codecov-io: # [Codecov](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=h1) Report
> Merging [#569](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=desc) into [master](https://codecov.io/gh/styleguidist/react-styleguidist/commit/df1a321e4b83aac2409796b2d4ade003dea38546?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569/graphs/tree.svg?src=pr&width=650&token=Z1XExpSVLu&height=150)](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #569      +/-   ##
==========================================
+ Coverage   96.04%   96.04%   +<.01%     
==========================================
  Files          99       99              
  Lines        1314     1316       +2     
  Branches      271      272       +1     
==========================================
+ Hits         1262     1264       +2     
  Misses         51       51              
  Partials        1        1
```


| [Impacted Files](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [scripts/utils/mergeWebpackConfig.js](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=tree#diff-c2NyaXB0cy91dGlscy9tZXJnZVdlYnBhY2tDb25maWcuanM=) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=footer). Last update [df1a321...0a52cf3](https://codecov.io/gh/styleguidist/react-styleguidist/pull/569?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/docs/Configuration.md b/docs/Configuration.md
index cbcc231d..18fcb882 100644
--- a/docs/Configuration.md
+++ b/docs/Configuration.md
@@ -443,7 +443,7 @@ module.exports = {
 
 > **Warning:** This option disables config load from `webpack.config.js`, load your config [manually](Webpack.md#reusing-your-projects-webpack-config).
 
-> **Note:** `entry`, `externals`, `output`, `watch`, `stats` and `devtool` options will be ignored.
+> **Note:** `entry`, `externals`, `output`, `watch`, and `stats` options will be ignored. For production builds, `devtool` will also be ignored.
 
 > **Note:** `CommonsChunkPlugins`, `HtmlWebpackPlugin`, `UglifyJsPlugin`, `HotModuleReplacementPlugin` plugins will be ignored because Styleguidist already includes them or they may break Styleguidist.
 
diff --git a/docs/Webpack.md b/docs/Webpack.md
index 965babb6..7340597c 100644
--- a/docs/Webpack.md
+++ b/docs/Webpack.md
@@ -31,7 +31,7 @@ module.exports = {
 };
 ```
 
-> **Note:** `entry`, `externals`, `output`, `watch`, `stats` and `devtool` options will be ignored.
+> **Note:** `entry`, `externals`, `output`, `watch`, and `stats` options will be ignored. For production builds, `devtool` will also be ignored.
 
 > **Note:** `CommonsChunkPlugins`, `HtmlWebpackPlugin`, `UglifyJsPlugin`, `HotModuleReplacementPlugin` plugins will be ignored because Styleguidist already includes them or they may break Styleguidist.
 
@@ -69,7 +69,7 @@ module.exports = {
 
 > **Warning:** This option disables config load from `webpack.config.js`, see above how to load your config manually.
 
-> **Note:** `entry`, `externals`, `output`, `watch`, `stats` and `devtool` options will be ignored.
+> **Note:** `entry`, `externals`, `output`, `watch`, and `stats` options will be ignored. For production builds, `devtool` will also be ignored.
 
 > **Note:** `CommonsChunkPlugins`, `HtmlWebpackPlugin`, `UglifyJsPlugin`, `HotModuleReplacementPlugin` plugins will be ignored because Styleguidist already includes them or they may break Styleguidist.
 
diff --git a/scripts/utils/mergeWebpackConfig.js b/scripts/utils/mergeWebpackConfig.js
index 6a3c4a6d..ea729dbe 100644
--- a/scripts/utils/mergeWebpackConfig.js
+++ b/scripts/utils/mergeWebpackConfig.js
@@ -4,15 +4,13 @@ const isFunction = require('lodash/isFunction');
 const omit = require('lodash/omit');
 const mergeBase = require('webpack-merge');
 
-const IGNORE_SECTIONS = [
-	'entry',
-	'externals',
-	'output',
-	'watch',
-	'stats',
-	'devtool',
-	'styleguidist',
-];
+const IGNORE_SECTIONS = ['entry', 'externals', 'output', 'watch', 'stats', 'styleguidist'];
+const IGNORE_SECTIONS_ENV = {
+	development: [],
+	// For production builds, we'll ignore devtool settings to avoid
+	// source mapping bloat.
+	production: ['devtool'],
+};
 
 const IGNORE_PLUGINS = [
 	'CommonsChunkPlugins',
@@ -46,6 +44,6 @@ const merge = mergeBase({
  */
 module.exports = function mergeWebpackConfig(baseConfig, userConfig, env) {
 	const userConfigObject = isFunction(userConfig) ? userConfig(env) : userConfig;
-	const safeUserConfig = omit(userConfigObject, IGNORE_SECTIONS);
+	const safeUserConfig = omit(userConfigObject, IGNORE_SECTIONS.concat(IGNORE_SECTIONS_ENV[env]));
 	return merge(baseConfig, safeUserConfig);
 };


Test patch:
diff --git a/scripts/utils/__tests__/mergeWebpackConfig.spec.js b/scripts/utils/__tests__/mergeWebpackConfig.spec.js
index 8907a3f6..d66d4cc3 100644
--- a/scripts/utils/__tests__/mergeWebpackConfig.spec.js
+++ b/scripts/utils/__tests__/mergeWebpackConfig.spec.js
@@ -38,3 +38,21 @@ it('should ignore certain Webpack plugins', () => {
 	expect(result.plugins[0].constructor.name).toBe('UglifyJsPlugin');
 	expect(result.plugins[1].constructor.name).toBe('MyPlugin');
 });
+
+it('should pass devtool settings in development', () => {
+	const result = mergeWebpackConfig(
+		{ devtool: false },
+		() => ({ devtool: 'source-map' }),
+		'development'
+	);
+	expect(result).toEqual({ devtool: 'source-map' });
+});
+
+it('should ignore devtool settings in production', () => {
+	const result = mergeWebpackConfig(
+		{ devtool: false },
+		() => ({ devtool: 'source-map' }),
+		'production'
+	);
+	expect(result).toEqual({ devtool: false });
+});
diff --git a/src/styles/__tests__/createStyleSheet.spec.js b/src/styles/__tests__/createStyleSheet.spec.js
new file mode 100644
index 00000000..35901e55
--- /dev/null
+++ b/src/styles/__tests__/createStyleSheet.spec.js
@@ -0,0 +1,63 @@
+import * as theme from '../theme';
+import createStyleSheet from '../createStyleSheet';
+
+const customThemeColor = '#123456';
+const customThemeBorderColor = '#654321';
+const customThemeMaxWidth = 9999;
+
+const customStyleBorderColor = '#ABCDEF';
+
+const testComponentName = 'TestComponentName';
+const testRuleName = 'testRule';
+
+const styles = theme => ({
+	[testRuleName]: {
+		color: theme.color.base,
+		backgroundColor: theme.color.baseBackground,
+		borderColor: theme.color.border,
+		borderRadius: theme.borderRadius,
+		maxWidth: theme.maxWidth,
+	},
+});
+
+const config = {
+	theme: {
+		color: {
+			base: customThemeColor,
+			border: customThemeBorderColor,
+		},
+		maxWidth: customThemeMaxWidth,
+	},
+	styles: {
+		[testComponentName]: {
+			[testRuleName]: {
+				borderColor: customStyleBorderColor,
+			},
+		},
+	},
+};
+
+describe('createStyleSheet', () => {
+	it('should use theme variables', () => {
+		const styleSheet = createStyleSheet(styles, config, testComponentName);
+		const style = styleSheet.getRule(testRuleName).style;
+
+		expect(style.backgroundColor).toBe(theme.color.baseBackground);
+		expect(style.borderRadius).toBe(theme.borderRadius);
+	});
+
+	it('should override theme variables with config theme', () => {
+		const styleSheet = createStyleSheet(styles, config, testComponentName);
+		const style = styleSheet.getRule(testRuleName).style;
+
+		expect(style.color).toBe(customThemeColor);
+		expect(style.maxWidth).toBe(customThemeMaxWidth);
+	});
+
+	it('should override config theme variables with config styles', () => {
+		const styleSheet = createStyleSheet(styles, config, testComponentName);
+		const style = styleSheet.getRule(testRuleName).style;
+
+		expect(style.borderColor).toBe(customStyleBorderColor);
+	});
+});
diff --git a/src/styles/createStyleSheet.js b/src/styles/createStyleSheet.js
index 5c86fef4..c7a715aa 100644
--- a/src/styles/createStyleSheet.js
+++ b/src/styles/createStyleSheet.js
@@ -4,7 +4,11 @@ import memoize from 'lodash/memoize';
 import * as theme from './theme';
 
 export default memoize((styles, config, componentName) => {
-	const mergedTheme = merge(theme, config.theme);
-	const mergedStyles = merge(styles(mergedTheme), config.styles && config.styles[componentName]);
+	const mergedTheme = merge({}, theme, config.theme);
+	const mergedStyles = merge(
+		{},
+		styles(mergedTheme),
+		config.styles && config.styles[componentName]
+	);
 	return jss.createStyleSheet(mergedStyles, { meta: componentName, link: true });
 });