Repository: webpack-contrib/css-loader
Pull request #1116 (2020-07-21 15:33:11)

refactor: rename the `onlyLocals` option
BREAKING CHANGE: the `onlyLocals` option was renamed to the `exportOnlyLocals` option and moved to the `module` option

<!--
  HOLY CRAP a Pull Request. We ❤️ those!

  If you remove or skip this template, you'll make the 🐼 sad and the mighty god
  of Github will appear and pile-drive the close button from a great height
  while making animal noises.

  Please place an x (no spaces!) in all [ ] that apply
-->

This PR contains a:

- [ ] **bugfix**
- [ ] new **feature**
- [x] **code refactor**
- [x] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [x] **metadata update**

### Motivation / Use-Case

All modules options is now under the `module` option 

### Breaking Changes

Yes

### Additional Info

No


Patch:
diff --git a/README.md b/README.md
index 57b406b..f3dc62f 100644
--- a/README.md
+++ b/README.md
@@ -116,7 +116,6 @@ module.exports = {
 |       **[`modules`](#modules)**       | `{Boolean\|String\|Object}` |      `false`       | Enables/Disables CSS Modules and their configuration                   |
 |     **[`sourceMap`](#sourcemap)**     |         `{Boolean}`         | `compiler.devtool` | Enables/Disables generation of source maps                             |
 | **[`importLoaders`](#importloaders)** |         `{Number}`          |        `0`         | Enables/Disables or setups number of loaders applied before CSS loader |
-|    **[`onlyLocals`](#onlylocals)**    |         `{Boolean}`         |      `false`       | Export only locals                                                     |
 |      **[`esModule`](#esmodule)**      |         `{Boolean}`         |      `false`       | Use ES modules syntax                                                  |
 
 ### `url`
@@ -535,6 +534,7 @@ module.exports = {
             context: path.resolve(__dirname, 'src'),
             hashPrefix: 'my-custom-hash',
             namedExport: true,
+            exportOnlyLocals: false,
           },
         },
       },
@@ -968,6 +968,37 @@ module.exports = {
 };
 ```
 
+### `exportOnlyLocals`
+
+Type: `Boolean`
+Default: `false`
+
+Export only locals.
+
+**Useful** when you use **css modules** for pre-rendering (for example SSR).
+For pre-rendering with `mini-css-extract-plugin` you should use this option instead of `style-loader!css-loader` **in the pre-rendering bundle**.
+It doesn't embed CSS but only exports the identifier mappings.
+
+**webpack.config.js**
+
+```js
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.css$/i,
+        loader: 'css-loader',
+        options: {
+          modules: {
+            exportOnlyLocals: true,
+          },
+        },
+      },
+    ],
+  },
+};
+```
+
 ### `sourceMap`
 
 Type: `Boolean`
@@ -1032,35 +1063,6 @@ module.exports = {
 
 This may change in the future when the module system (i. e. webpack) supports loader matching by origin.
 
-### `onlyLocals`
-
-Type: `Boolean`
-Default: `false`
-
-Export only locals.
-
-**Useful** when you use **css modules** for pre-rendering (for example SSR).
-For pre-rendering with `mini-css-extract-plugin` you should use this option instead of `style-loader!css-loader` **in the pre-rendering bundle**.
-It doesn't embed CSS but only exports the identifier mappings.
-
-**webpack.config.js**
-
-```js
-module.exports = {
-  module: {
-    rules: [
-      {
-        test: /\.css$/i,
-        loader: 'css-loader',
-        options: {
-          onlyLocals: true,
-        },
-      },
-    ],
-  },
-};
-```
-
 ### `esModule`
 
 Type: `Boolean`
diff --git a/src/options.json b/src/options.json
index 7189313..215568e 100644
--- a/src/options.json
+++ b/src/options.json
@@ -104,6 +104,10 @@
             "namedExport": {
               "description": "Use the named export ES modules.",
               "type": "boolean"
+            },
+            "exportOnlyLocals": {
+              "description": "Export only locals (https://github.com/webpack-contrib/css-loader#exportonlylocals).",
+              "type": "boolean"
             }
           }
         }
@@ -124,10 +128,6 @@
         }
       ]
     },
-    "onlyLocals": {
-      "description": "Export only locals (https://github.com/webpack-contrib/css-loader#onlylocals).",
-      "type": "boolean"
-    },
     "esModule": {
       "description": "Use the ES modules syntax (https://github.com/webpack-contrib/css-loader#esmodule).",
       "type": "boolean"
diff --git a/src/utils.js b/src/utils.js
index 2d0bbe6..8a7b712 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -123,6 +123,7 @@ function getModulesOptions(rawOptions, loaderContext) {
     hashPrefix: '',
     exportGlobals: false,
     namedExport: false,
+    exportOnlyLocals: false,
   };
 
   if (
@@ -183,17 +184,13 @@ function normalizeOptions(rawOptions, loaderContext) {
         ? rawOptions.sourceMap
         : loaderContext.sourceMap,
     importLoaders: rawOptions.importLoaders,
-    onlyLocals:
-      typeof rawOptions.onlyLocals !== 'undefined'
-        ? rawOptions.onlyLocals
-        : false,
     esModule:
       typeof rawOptions.esModule === 'undefined' ? true : rawOptions.esModule,
   };
 }
 
 function shouldUseImportPlugin(options) {
-  if (options.onlyLocals) {
+  if (options.modules.exportOnlyLocals) {
     return false;
   }
 
@@ -205,7 +202,7 @@ function shouldUseImportPlugin(options) {
 }
 
 function shouldUseURLPlugin(options) {
-  if (options.onlyLocals) {
+  if (options.modules.exportOnlyLocals) {
     return false;
   }
 
@@ -326,7 +323,7 @@ function getPreRequester({ loaders, loaderIndex }) {
 function getImportCode(loaderContext, imports, options) {
   let code = '';
 
-  if (options.onlyLocals !== true) {
+  if (options.modules.exportOnlyLocals !== true) {
     const apiUrl = stringifyRequest(
       loaderContext,
       require.resolve('./runtime/api')
@@ -357,7 +354,7 @@ function getModuleCode(
   icssReplacements,
   options
 ) {
-  if (options.onlyLocals === true) {
+  if (options.modules.exportOnlyLocals === true) {
     return 'var ___CSS_LOADER_EXPORT___ = {};\n';
   }
 


Test patch:
diff --git a/test/__snapshots__/modules-option.test.js.snap b/test/__snapshots__/modules-option.test.js.snap
index 64cb240..9b9d00a 100644
--- a/test/__snapshots__/modules-option.test.js.snap
+++ b/test/__snapshots__/modules-option.test.js.snap
@@ -2190,6 +2190,242 @@ Array [
 
 exports[`"modules" option should work and respect the "context" option: warnings 1`] = `Array []`;
 
+exports[`"modules" option should work and respect the "exportOnlyLocals" option with the "esModule" option: errors 1`] = `Array []`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option with the "esModule" option: module 1`] = `
+"// Imports
+import ___CSS_LOADER_ICSS_IMPORT_0___ from \\"-!../../../../src/index.js??[ident]!./values.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_1___ from \\"-!../../../../src/index.js??[ident]!./something.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_2___ from \\"-!../../../../src/index.js??[ident]!./imported-simple.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_3___ from \\"-!../../../../src/index.js??[ident]!./relative.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_4___ from \\"-!../../../../src/index.js??[ident]!./top-relative.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_5___ from \\"-!../../../../src/index.js??[ident]!../issue-861/node_modules/package/style.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_6___ from \\"-!../../../../src/index.js??[ident]!./alias.css\\";
+var ___CSS_LOADER_EXPORT___ = {};
+// Exports
+___CSS_LOADER_EXPORT___.locals = {
+	\\"v-def\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-def\\"] + \\"\\",
+	\\"v-other\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-other\\"] + \\"\\",
+	\\"s-white\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"s-white\\"] + \\"\\",
+	\\"m-small\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"m-small\\"] + \\"\\",
+	\\"v-something\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_1___.locals[\\"v-something\\"] + \\"\\",
+	\\"v-foo\\": \\"blue\\",
+	\\"v-bar\\": \\"block\\",
+	\\"v-primary\\": \\"#BF4040\\",
+	\\"s-black\\": \\"black-selector\\",
+	\\"m-large\\": \\"(min-width: 960px)\\",
+	\\"v-ident\\": \\"validIdent\\",
+	\\"v-pre-defined-ident\\": \\"left\\",
+	\\"v-string\\": \\"'content'\\",
+	\\"v-string-1\\": \\"''\\",
+	\\"v-url\\": \\"url(https://www.exammple.com/images/my-background.png)\\",
+	\\"v-url-1\\": \\"url('https://www.exammple.com/images/my-background.png')\\",
+	\\"v-url-2\\": \\"url(\\\\\\"https://www.exammple.com/images/my-background.png\\\\\\")\\",
+	\\"v-integer\\": \\"100\\",
+	\\"v-integer-1\\": \\"-100\\",
+	\\"v-integer-2\\": \\"+100\\",
+	\\"v-number\\": \\".60\\",
+	\\"v-number-1\\": \\"-456.8\\",
+	\\"v-number-2\\": \\"-3.4e-2\\",
+	\\"v-dimension\\": \\"12px\\",
+	\\"v-percentage\\": \\"100%\\",
+	\\"v-hex\\": \\"#fff\\",
+	\\"v-function\\": \\"rgb(0,0,0)\\",
+	\\"v-unicode-range\\": \\"U+0025-00FF\\",
+	\\"ghi\\": \\"_ghi\\",
+	\\"class\\": \\"_class\\",
+	\\"other\\": \\"_other\\",
+	\\"other-other\\": \\"_other-other\\",
+	\\"green\\": \\"_green\\",
+	\\"foo\\": \\"_foo\\",
+	\\"simple\\": \\"_simple \\" + ___CSS_LOADER_ICSS_IMPORT_2___.locals[\\"imported-simple\\"] + \\"\\",
+	\\"relative\\": \\"_relative \\" + ___CSS_LOADER_ICSS_IMPORT_3___.locals[\\"imported-relative\\"] + \\"\\",
+	\\"top-relative\\": \\"_top-relative \\" + ___CSS_LOADER_ICSS_IMPORT_4___.locals[\\"imported-relative\\"] + \\"\\",
+	\\"module\\": \\"_module \\" + ___CSS_LOADER_ICSS_IMPORT_5___.locals[\\"imported-module\\"] + \\"\\",
+	\\"alias\\": \\"_alias \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
+	\\"alias-duplicate\\": \\"_alias-duplicate \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
+	\\"primary-selector\\": \\"_primary-selector\\",
+	\\"black-selector\\": \\"_black-selector\\",
+	\\"header\\": \\"_header\\",
+	\\"foobarbaz\\": \\"_foobarbaz\\",
+	\\"url\\": \\"_url\\"
+};
+export default ___CSS_LOADER_EXPORT___;
+"
+`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option with the "esModule" option: result 1`] = `
+Object {
+  "locals": Object {
+    "alias": "_alias _imported-alias",
+    "alias-duplicate": "_alias-duplicate _imported-alias",
+    "black-selector": "_black-selector",
+    "class": "_class",
+    "foo": "_foo",
+    "foobarbaz": "_foobarbaz",
+    "ghi": "_ghi",
+    "green": "_green",
+    "header": "_header",
+    "m-large": "(min-width: 960px)",
+    "m-small": "(min-width: 320px)",
+    "module": "_module _imported-module",
+    "other": "_other",
+    "other-other": "_other-other",
+    "primary-selector": "_primary-selector",
+    "relative": "_relative _imported-relative",
+    "s-black": "black-selector",
+    "s-white": "white",
+    "simple": "_simple _imported-simple",
+    "top-relative": "_top-relative undefined",
+    "url": "_url",
+    "v-bar": "block",
+    "v-def": "red",
+    "v-dimension": "12px",
+    "v-foo": "blue",
+    "v-function": "rgb(0,0,0)",
+    "v-hex": "#fff",
+    "v-ident": "validIdent",
+    "v-integer": "100",
+    "v-integer-1": "-100",
+    "v-integer-2": "+100",
+    "v-number": ".60",
+    "v-number-1": "-456.8",
+    "v-number-2": "-3.4e-2",
+    "v-other": "green",
+    "v-percentage": "100%",
+    "v-pre-defined-ident": "left",
+    "v-primary": "#BF4040",
+    "v-something": "2112moon",
+    "v-string": "'content'",
+    "v-string-1": "''",
+    "v-unicode-range": "U+0025-00FF",
+    "v-url": "url(https://www.exammple.com/images/my-background.png)",
+    "v-url-1": "url('https://www.exammple.com/images/my-background.png')",
+    "v-url-2": "url(\\"https://www.exammple.com/images/my-background.png\\")",
+  },
+}
+`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option with the "esModule" option: warnings 1`] = `Array []`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option: errors 1`] = `Array []`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option: module 1`] = `
+"// Imports
+import ___CSS_LOADER_ICSS_IMPORT_0___ from \\"-!../../../../src/index.js??[ident]!./values.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_1___ from \\"-!../../../../src/index.js??[ident]!./something.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_2___ from \\"-!../../../../src/index.js??[ident]!./imported-simple.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_3___ from \\"-!../../../../src/index.js??[ident]!./relative.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_4___ from \\"-!../../../../src/index.js??[ident]!./top-relative.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_5___ from \\"-!../../../../src/index.js??[ident]!../issue-861/node_modules/package/style.css\\";
+import ___CSS_LOADER_ICSS_IMPORT_6___ from \\"-!../../../../src/index.js??[ident]!./alias.css\\";
+var ___CSS_LOADER_EXPORT___ = {};
+// Exports
+___CSS_LOADER_EXPORT___.locals = {
+	\\"v-def\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-def\\"] + \\"\\",
+	\\"v-other\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-other\\"] + \\"\\",
+	\\"s-white\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"s-white\\"] + \\"\\",
+	\\"m-small\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"m-small\\"] + \\"\\",
+	\\"v-something\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_1___.locals[\\"v-something\\"] + \\"\\",
+	\\"v-foo\\": \\"blue\\",
+	\\"v-bar\\": \\"block\\",
+	\\"v-primary\\": \\"#BF4040\\",
+	\\"s-black\\": \\"black-selector\\",
+	\\"m-large\\": \\"(min-width: 960px)\\",
+	\\"v-ident\\": \\"validIdent\\",
+	\\"v-pre-defined-ident\\": \\"left\\",
+	\\"v-string\\": \\"'content'\\",
+	\\"v-string-1\\": \\"''\\",
+	\\"v-url\\": \\"url(https://www.exammple.com/images/my-background.png)\\",
+	\\"v-url-1\\": \\"url('https://www.exammple.com/images/my-background.png')\\",
+	\\"v-url-2\\": \\"url(\\\\\\"https://www.exammple.com/images/my-background.png\\\\\\")\\",
+	\\"v-integer\\": \\"100\\",
+	\\"v-integer-1\\": \\"-100\\",
+	\\"v-integer-2\\": \\"+100\\",
+	\\"v-number\\": \\".60\\",
+	\\"v-number-1\\": \\"-456.8\\",
+	\\"v-number-2\\": \\"-3.4e-2\\",
+	\\"v-dimension\\": \\"12px\\",
+	\\"v-percentage\\": \\"100%\\",
+	\\"v-hex\\": \\"#fff\\",
+	\\"v-function\\": \\"rgb(0,0,0)\\",
+	\\"v-unicode-range\\": \\"U+0025-00FF\\",
+	\\"ghi\\": \\"_ghi\\",
+	\\"class\\": \\"_class\\",
+	\\"other\\": \\"_other\\",
+	\\"other-other\\": \\"_other-other\\",
+	\\"green\\": \\"_green\\",
+	\\"foo\\": \\"_foo\\",
+	\\"simple\\": \\"_simple \\" + ___CSS_LOADER_ICSS_IMPORT_2___.locals[\\"imported-simple\\"] + \\"\\",
+	\\"relative\\": \\"_relative \\" + ___CSS_LOADER_ICSS_IMPORT_3___.locals[\\"imported-relative\\"] + \\"\\",
+	\\"top-relative\\": \\"_top-relative \\" + ___CSS_LOADER_ICSS_IMPORT_4___.locals[\\"imported-relative\\"] + \\"\\",
+	\\"module\\": \\"_module \\" + ___CSS_LOADER_ICSS_IMPORT_5___.locals[\\"imported-module\\"] + \\"\\",
+	\\"alias\\": \\"_alias \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
+	\\"alias-duplicate\\": \\"_alias-duplicate \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
+	\\"primary-selector\\": \\"_primary-selector\\",
+	\\"black-selector\\": \\"_black-selector\\",
+	\\"header\\": \\"_header\\",
+	\\"foobarbaz\\": \\"_foobarbaz\\",
+	\\"url\\": \\"_url\\"
+};
+export default ___CSS_LOADER_EXPORT___;
+"
+`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option: result 1`] = `
+Object {
+  "locals": Object {
+    "alias": "_alias _imported-alias",
+    "alias-duplicate": "_alias-duplicate _imported-alias",
+    "black-selector": "_black-selector",
+    "class": "_class",
+    "foo": "_foo",
+    "foobarbaz": "_foobarbaz",
+    "ghi": "_ghi",
+    "green": "_green",
+    "header": "_header",
+    "m-large": "(min-width: 960px)",
+    "m-small": "(min-width: 320px)",
+    "module": "_module _imported-module",
+    "other": "_other",
+    "other-other": "_other-other",
+    "primary-selector": "_primary-selector",
+    "relative": "_relative _imported-relative",
+    "s-black": "black-selector",
+    "s-white": "white",
+    "simple": "_simple _imported-simple",
+    "top-relative": "_top-relative undefined",
+    "url": "_url",
+    "v-bar": "block",
+    "v-def": "red",
+    "v-dimension": "12px",
+    "v-foo": "blue",
+    "v-function": "rgb(0,0,0)",
+    "v-hex": "#fff",
+    "v-ident": "validIdent",
+    "v-integer": "100",
+    "v-integer-1": "-100",
+    "v-integer-2": "+100",
+    "v-number": ".60",
+    "v-number-1": "-456.8",
+    "v-number-2": "-3.4e-2",
+    "v-other": "green",
+    "v-percentage": "100%",
+    "v-pre-defined-ident": "left",
+    "v-primary": "#BF4040",
+    "v-something": "2112moon",
+    "v-string": "'content'",
+    "v-string-1": "''",
+    "v-unicode-range": "U+0025-00FF",
+    "v-url": "url(https://www.exammple.com/images/my-background.png)",
+    "v-url-1": "url('https://www.exammple.com/images/my-background.png')",
+    "v-url-2": "url(\\"https://www.exammple.com/images/my-background.png\\")",
+  },
+}
+`;
+
+exports[`"modules" option should work and respect the "exportOnlyLocals" option: warnings 1`] = `Array []`;
+
 exports[`"modules" option should work and respect the "getLocalIdent" option: errors 1`] = `Array []`;
 
 exports[`"modules" option should work and respect the "getLocalIdent" option: module 1`] = `
diff --git a/test/__snapshots__/onlyLocals-option.test.js.snap b/test/__snapshots__/onlyLocals-option.test.js.snap
deleted file mode 100644
index e95fb26..0000000
--- a/test/__snapshots__/onlyLocals-option.test.js.snap
+++ /dev/null
@@ -1,237 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`"onlyLocals" option should work with the "esModule" option: errors 1`] = `Array []`;
-
-exports[`"onlyLocals" option should work with the "esModule" option: module 1`] = `
-"// Imports
-import ___CSS_LOADER_ICSS_IMPORT_0___ from \\"-!../../../../src/index.js??[ident]!./values.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_1___ from \\"-!../../../../src/index.js??[ident]!./something.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_2___ from \\"-!../../../../src/index.js??[ident]!./imported-simple.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_3___ from \\"-!../../../../src/index.js??[ident]!./relative.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_4___ from \\"-!../../../../src/index.js??[ident]!./top-relative.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_5___ from \\"-!../../../../src/index.js??[ident]!../issue-861/node_modules/package/style.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_6___ from \\"-!../../../../src/index.js??[ident]!./alias.css\\";
-var ___CSS_LOADER_EXPORT___ = {};
-// Exports
-___CSS_LOADER_EXPORT___.locals = {
-	\\"v-def\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-def\\"] + \\"\\",
-	\\"v-other\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-other\\"] + \\"\\",
-	\\"s-white\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"s-white\\"] + \\"\\",
-	\\"m-small\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"m-small\\"] + \\"\\",
-	\\"v-something\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_1___.locals[\\"v-something\\"] + \\"\\",
-	\\"v-foo\\": \\"blue\\",
-	\\"v-bar\\": \\"block\\",
-	\\"v-primary\\": \\"#BF4040\\",
-	\\"s-black\\": \\"black-selector\\",
-	\\"m-large\\": \\"(min-width: 960px)\\",
-	\\"v-ident\\": \\"validIdent\\",
-	\\"v-pre-defined-ident\\": \\"left\\",
-	\\"v-string\\": \\"'content'\\",
-	\\"v-string-1\\": \\"''\\",
-	\\"v-url\\": \\"url(https://www.exammple.com/images/my-background.png)\\",
-	\\"v-url-1\\": \\"url('https://www.exammple.com/images/my-background.png')\\",
-	\\"v-url-2\\": \\"url(\\\\\\"https://www.exammple.com/images/my-background.png\\\\\\")\\",
-	\\"v-integer\\": \\"100\\",
-	\\"v-integer-1\\": \\"-100\\",
-	\\"v-integer-2\\": \\"+100\\",
-	\\"v-number\\": \\".60\\",
-	\\"v-number-1\\": \\"-456.8\\",
-	\\"v-number-2\\": \\"-3.4e-2\\",
-	\\"v-dimension\\": \\"12px\\",
-	\\"v-percentage\\": \\"100%\\",
-	\\"v-hex\\": \\"#fff\\",
-	\\"v-function\\": \\"rgb(0,0,0)\\",
-	\\"v-unicode-range\\": \\"U+0025-00FF\\",
-	\\"ghi\\": \\"_ghi\\",
-	\\"class\\": \\"_class\\",
-	\\"other\\": \\"_other\\",
-	\\"other-other\\": \\"_other-other\\",
-	\\"green\\": \\"_green\\",
-	\\"foo\\": \\"_foo\\",
-	\\"simple\\": \\"_simple \\" + ___CSS_LOADER_ICSS_IMPORT_2___.locals[\\"imported-simple\\"] + \\"\\",
-	\\"relative\\": \\"_relative \\" + ___CSS_LOADER_ICSS_IMPORT_3___.locals[\\"imported-relative\\"] + \\"\\",
-	\\"top-relative\\": \\"_top-relative \\" + ___CSS_LOADER_ICSS_IMPORT_4___.locals[\\"imported-relative\\"] + \\"\\",
-	\\"module\\": \\"_module \\" + ___CSS_LOADER_ICSS_IMPORT_5___.locals[\\"imported-module\\"] + \\"\\",
-	\\"alias\\": \\"_alias \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
-	\\"alias-duplicate\\": \\"_alias-duplicate \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
-	\\"primary-selector\\": \\"_primary-selector\\",
-	\\"black-selector\\": \\"_black-selector\\",
-	\\"header\\": \\"_header\\",
-	\\"foobarbaz\\": \\"_foobarbaz\\",
-	\\"url\\": \\"_url\\"
-};
-export default ___CSS_LOADER_EXPORT___;
-"
-`;
-
-exports[`"onlyLocals" option should work with the "esModule" option: result 1`] = `
-Object {
-  "locals": Object {
-    "alias": "_alias _imported-alias",
-    "alias-duplicate": "_alias-duplicate _imported-alias",
-    "black-selector": "_black-selector",
-    "class": "_class",
-    "foo": "_foo",
-    "foobarbaz": "_foobarbaz",
-    "ghi": "_ghi",
-    "green": "_green",
-    "header": "_header",
-    "m-large": "(min-width: 960px)",
-    "m-small": "(min-width: 320px)",
-    "module": "_module _imported-module",
-    "other": "_other",
-    "other-other": "_other-other",
-    "primary-selector": "_primary-selector",
-    "relative": "_relative _imported-relative",
-    "s-black": "black-selector",
-    "s-white": "white",
-    "simple": "_simple _imported-simple",
-    "top-relative": "_top-relative undefined",
-    "url": "_url",
-    "v-bar": "block",
-    "v-def": "red",
-    "v-dimension": "12px",
-    "v-foo": "blue",
-    "v-function": "rgb(0,0,0)",
-    "v-hex": "#fff",
-    "v-ident": "validIdent",
-    "v-integer": "100",
-    "v-integer-1": "-100",
-    "v-integer-2": "+100",
-    "v-number": ".60",
-    "v-number-1": "-456.8",
-    "v-number-2": "-3.4e-2",
-    "v-other": "green",
-    "v-percentage": "100%",
-    "v-pre-defined-ident": "left",
-    "v-primary": "#BF4040",
-    "v-something": "2112moon",
-    "v-string": "'content'",
-    "v-string-1": "''",
-    "v-unicode-range": "U+0025-00FF",
-    "v-url": "url(https://www.exammple.com/images/my-background.png)",
-    "v-url-1": "url('https://www.exammple.com/images/my-background.png')",
-    "v-url-2": "url(\\"https://www.exammple.com/images/my-background.png\\")",
-  },
-}
-`;
-
-exports[`"onlyLocals" option should work with the "esModule" option: warnings 1`] = `Array []`;
-
-exports[`"onlyLocals" option should work: errors 1`] = `Array []`;
-
-exports[`"onlyLocals" option should work: module 1`] = `
-"// Imports
-import ___CSS_LOADER_ICSS_IMPORT_0___ from \\"-!../../../../src/index.js??[ident]!./values.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_1___ from \\"-!../../../../src/index.js??[ident]!./something.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_2___ from \\"-!../../../../src/index.js??[ident]!./imported-simple.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_3___ from \\"-!../../../../src/index.js??[ident]!./relative.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_4___ from \\"-!../../../../src/index.js??[ident]!./top-relative.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_5___ from \\"-!../../../../src/index.js??[ident]!../issue-861/node_modules/package/style.css\\";
-import ___CSS_LOADER_ICSS_IMPORT_6___ from \\"-!../../../../src/index.js??[ident]!./alias.css\\";
-var ___CSS_LOADER_EXPORT___ = {};
-// Exports
-___CSS_LOADER_EXPORT___.locals = {
-	\\"v-def\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-def\\"] + \\"\\",
-	\\"v-other\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"v-other\\"] + \\"\\",
-	\\"s-white\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"s-white\\"] + \\"\\",
-	\\"m-small\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"m-small\\"] + \\"\\",
-	\\"v-something\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_1___.locals[\\"v-something\\"] + \\"\\",
-	\\"v-foo\\": \\"blue\\",
-	\\"v-bar\\": \\"block\\",
-	\\"v-primary\\": \\"#BF4040\\",
-	\\"s-black\\": \\"black-selector\\",
-	\\"m-large\\": \\"(min-width: 960px)\\",
-	\\"v-ident\\": \\"validIdent\\",
-	\\"v-pre-defined-ident\\": \\"left\\",
-	\\"v-string\\": \\"'content'\\",
-	\\"v-string-1\\": \\"''\\",
-	\\"v-url\\": \\"url(https://www.exammple.com/images/my-background.png)\\",
-	\\"v-url-1\\": \\"url('https://www.exammple.com/images/my-background.png')\\",
-	\\"v-url-2\\": \\"url(\\\\\\"https://www.exammple.com/images/my-background.png\\\\\\")\\",
-	\\"v-integer\\": \\"100\\",
-	\\"v-integer-1\\": \\"-100\\",
-	\\"v-integer-2\\": \\"+100\\",
-	\\"v-number\\": \\".60\\",
-	\\"v-number-1\\": \\"-456.8\\",
-	\\"v-number-2\\": \\"-3.4e-2\\",
-	\\"v-dimension\\": \\"12px\\",
-	\\"v-percentage\\": \\"100%\\",
-	\\"v-hex\\": \\"#fff\\",
-	\\"v-function\\": \\"rgb(0,0,0)\\",
-	\\"v-unicode-range\\": \\"U+0025-00FF\\",
-	\\"ghi\\": \\"_ghi\\",
-	\\"class\\": \\"_class\\",
-	\\"other\\": \\"_other\\",
-	\\"other-other\\": \\"_other-other\\",
-	\\"green\\": \\"_green\\",
-	\\"foo\\": \\"_foo\\",
-	\\"simple\\": \\"_simple \\" + ___CSS_LOADER_ICSS_IMPORT_2___.locals[\\"imported-simple\\"] + \\"\\",
-	\\"relative\\": \\"_relative \\" + ___CSS_LOADER_ICSS_IMPORT_3___.locals[\\"imported-relative\\"] + \\"\\",
-	\\"top-relative\\": \\"_top-relative \\" + ___CSS_LOADER_ICSS_IMPORT_4___.locals[\\"imported-relative\\"] + \\"\\",
-	\\"module\\": \\"_module \\" + ___CSS_LOADER_ICSS_IMPORT_5___.locals[\\"imported-module\\"] + \\"\\",
-	\\"alias\\": \\"_alias \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
-	\\"alias-duplicate\\": \\"_alias-duplicate \\" + ___CSS_LOADER_ICSS_IMPORT_6___.locals[\\"imported-alias\\"] + \\"\\",
-	\\"primary-selector\\": \\"_primary-selector\\",
-	\\"black-selector\\": \\"_black-selector\\",
-	\\"header\\": \\"_header\\",
-	\\"foobarbaz\\": \\"_foobarbaz\\",
-	\\"url\\": \\"_url\\"
-};
-export default ___CSS_LOADER_EXPORT___;
-"
-`;
-
-exports[`"onlyLocals" option should work: result 1`] = `
-Object {
-  "locals": Object {
-    "alias": "_alias _imported-alias",
-    "alias-duplicate": "_alias-duplicate _imported-alias",
-    "black-selector": "_black-selector",
-    "class": "_class",
-    "foo": "_foo",
-    "foobarbaz": "_foobarbaz",
-    "ghi": "_ghi",
-    "green": "_green",
-    "header": "_header",
-    "m-large": "(min-width: 960px)",
-    "m-small": "(min-width: 320px)",
-    "module": "_module _imported-module",
-    "other": "_other",
-    "other-other": "_other-other",
-    "primary-selector": "_primary-selector",
-    "relative": "_relative _imported-relative",
-    "s-black": "black-selector",
-    "s-white": "white",
-    "simple": "_simple _imported-simple",
-    "top-relative": "_top-relative undefined",
-    "url": "_url",
-    "v-bar": "block",
-    "v-def": "red",
-    "v-dimension": "12px",
-    "v-foo": "blue",
-    "v-function": "rgb(0,0,0)",
-    "v-hex": "#fff",
-    "v-ident": "validIdent",
-    "v-integer": "100",
-    "v-integer-1": "-100",
-    "v-integer-2": "+100",
-    "v-number": ".60",
-    "v-number-1": "-456.8",
-    "v-number-2": "-3.4e-2",
-    "v-other": "green",
-    "v-percentage": "100%",
-    "v-pre-defined-ident": "left",
-    "v-primary": "#BF4040",
-    "v-something": "2112moon",
-    "v-string": "'content'",
-    "v-string-1": "''",
-    "v-unicode-range": "U+0025-00FF",
-    "v-url": "url(https://www.exammple.com/images/my-background.png)",
-    "v-url-1": "url('https://www.exammple.com/images/my-background.png')",
-    "v-url-2": "url(\\"https://www.exammple.com/images/my-background.png\\")",
-  },
-}
-`;
-
-exports[`"onlyLocals" option should work: warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap
index c0d1bbc..beca906 100644
--- a/test/__snapshots__/validate-options.test.js.snap
+++ b/test/__snapshots__/validate-options.test.js.snap
@@ -39,7 +39,7 @@ exports[`validate options should throw an error on the "importLoaders" option wi
 exports[`validate options should throw an error on the "modules" option with "{"auto":"invalid"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.auto should be one of these:
@@ -60,10 +60,16 @@ exports[`validate options should throw an error on the "modules" option with "{"
  - options.modules.exportGlobals should be a boolean."
 `;
 
+exports[`validate options should throw an error on the "modules" option with "{"exportOnlyLocals":"invalid"}" value 1`] = `
+"Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
+ - options.modules.exportOnlyLocals should be a boolean.
+   -> Export only locals (https://github.com/webpack-contrib/css-loader#exportonlylocals)."
+`;
+
 exports[`validate options should throw an error on the "modules" option with "{"getLocalIdent":[]}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.getLocalIdent should be one of these:
@@ -86,7 +92,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"localIdentRegExp":true}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.localIdentRegExp should be one of these:
@@ -106,7 +112,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":"globals"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -120,7 +126,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":"locals"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -134,7 +140,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":"pures"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -148,7 +154,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":true}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -168,59 +174,53 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "globals" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }"
+      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }"
 `;
 
 exports[`validate options should throw an error on the "modules" option with "locals" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }"
+      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }"
 `;
 
 exports[`validate options should throw an error on the "modules" option with "pures" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }"
+      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }"
 `;
 
 exports[`validate options should throw an error on the "modules" option with "true" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport? }"
-`;
-
-exports[`validate options should throw an error on the "onlyLocals" option with "true" value 1`] = `
-"Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
- - options.onlyLocals should be a boolean.
-   -> Export only locals (https://github.com/webpack-contrib/css-loader#onlylocals)."
+      object { auto?, mode?, exportGlobals?, localIdentName?, localIdentRegExp?, localsConvention?, context?, hashPrefix?, getLocalIdent?, namedExport?, exportOnlyLocals? }"
 `;
 
 exports[`validate options should throw an error on the "sourceMap" option with "true" value 1`] = `
@@ -232,49 +232,49 @@ exports[`validate options should throw an error on the "sourceMap" option with "
 exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options has an unknown property 'unknown'. These properties are valid:
-   object { url?, import?, modules?, sourceMap?, importLoaders?, onlyLocals?, esModule? }"
+   object { url?, import?, modules?, sourceMap?, importLoaders?, esModule? }"
 `;
 
 exports[`validate options should throw an error on the "url" option with "true" value 1`] = `
diff --git a/test/loader.test.js b/test/loader.test.js
index 115bcfd..cffd5eb 100644
--- a/test/loader.test.js
+++ b/test/loader.test.js
@@ -321,8 +321,11 @@ describe('loader', () => {
 
   it('issue #1033', async () => {
     const compiler = getCompiler('./modules/issue-1033/issue-1033.js', {
-      modules: { mode: 'local', localIdentName: '_[local]' },
-      onlyLocals: true,
+      modules: {
+        mode: 'local',
+        localIdentName: '_[local]',
+        exportOnlyLocals: true,
+      },
     });
     const stats = await compile(compiler);
 
diff --git a/test/modules-option.test.js b/test/modules-option.test.js
index 18aa3c7..52cefd2 100644
--- a/test/modules-option.test.js
+++ b/test/modules-option.test.js
@@ -954,4 +954,45 @@ describe('"modules" option', () => {
     expect(getWarnings(stats)).toMatchSnapshot('warnings');
     expect(getErrors(stats)).toMatchSnapshot('errors');
   });
+
+  it('should work and respect the "exportOnlyLocals" option', async () => {
+    const compiler = getCompiler('./modules/composes/composes.js', {
+      modules: {
+        mode: 'local',
+        localIdentName: '_[local]',
+        exportOnlyLocals: true,
+      },
+    });
+    const stats = await compile(compiler);
+
+    expect(
+      getModuleSource('./modules/composes/composes.css', stats)
+    ).toMatchSnapshot('module');
+    expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
+      'result'
+    );
+    expect(getWarnings(stats)).toMatchSnapshot('warnings');
+    expect(getErrors(stats)).toMatchSnapshot('errors');
+  });
+
+  it('should work and respect the "exportOnlyLocals" option with the "esModule" option', async () => {
+    const compiler = getCompiler('./modules/composes/composes.js', {
+      modules: {
+        mode: 'local',
+        localIdentName: '_[local]',
+        exportOnlyLocals: true,
+      },
+      esModule: true,
+    });
+    const stats = await compile(compiler);
+
+    expect(
+      getModuleSource('./modules/composes/composes.css', stats)
+    ).toMatchSnapshot('module');
+    expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
+      'result'
+    );
+    expect(getWarnings(stats)).toMatchSnapshot('warnings');
+    expect(getErrors(stats)).toMatchSnapshot('errors');
+  });
 });
diff --git a/test/onlyLocals-option.test.js b/test/onlyLocals-option.test.js
deleted file mode 100644
index 04c819c..0000000
--- a/test/onlyLocals-option.test.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import {
-  compile,
-  getCompiler,
-  getErrors,
-  getExecutedCode,
-  getModuleSource,
-  getWarnings,
-} from './helpers/index';
-
-describe('"onlyLocals" option', () => {
-  it('should work', async () => {
-    const compiler = getCompiler('./modules/composes/composes.js', {
-      modules: { mode: 'local', localIdentName: '_[local]' },
-      onlyLocals: true,
-    });
-    const stats = await compile(compiler);
-
-    expect(
-      getModuleSource('./modules/composes/composes.css', stats)
-    ).toMatchSnapshot('module');
-    expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
-      'result'
-    );
-    expect(getWarnings(stats)).toMatchSnapshot('warnings');
-    expect(getErrors(stats)).toMatchSnapshot('errors');
-  });
-
-  it('should work with the "esModule" option', async () => {
-    const compiler = getCompiler('./modules/composes/composes.js', {
-      modules: { mode: 'local', localIdentName: '_[local]' },
-      onlyLocals: true,
-      esModule: true,
-    });
-    const stats = await compile(compiler);
-
-    expect(
-      getModuleSource('./modules/composes/composes.css', stats)
-    ).toMatchSnapshot('module');
-    expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
-      'result'
-    );
-    expect(getWarnings(stats)).toMatchSnapshot('warnings');
-    expect(getErrors(stats)).toMatchSnapshot('errors');
-  });
-});
diff --git a/test/validate-options.test.js b/test/validate-options.test.js
index b53b24a..8556e95 100644
--- a/test/validate-options.test.js
+++ b/test/validate-options.test.js
@@ -39,6 +39,8 @@ describe('validate options', () => {
         { localsConvention: 'dashesOnly' },
         { namedExport: true },
         { namedExport: false },
+        { exportOnlyLocals: true },
+        { exportOnlyLocals: false },
       ],
       failure: [
         'true',
@@ -58,6 +60,7 @@ describe('validate options', () => {
         { auto: 'invalid' },
         { localsConvention: 'unknown' },
         { namedExport: 'invalid' },
+        { exportOnlyLocals: 'invalid' },
       ],
     },
     sourceMap: {
@@ -68,10 +71,6 @@ describe('validate options', () => {
       success: [false, 0, 1, 2],
       failure: ['1', 2.5],
     },
-    onlyLocals: {
-      success: [true, false],
-      failure: ['true'],
-    },
     esModule: {
       success: [true, false],
       failure: ['true'],