From 40be03ab0b1a9bd3f7409f86a88e64f9d761bc51 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Mon, 24 Aug 2020 20:23:36 +0300 Subject: [PATCH] feat: add webpack-importer option --- README.md | 44 +++++++++++++-- src/options.json | 4 ++ src/utils.js | 9 +++- test/__snapshots__/loader.test.js.snap | 16 ------ .../validate-options.test.js.snap | 54 +++++++++++++++++++ .../webpackImporter-options.test.js.snap | 50 +++++++++++++++++ test/loader.test.js | 13 ----- test/validate-options.test.js | 8 +++ test/webpackImporter-options.test.js | 49 +++++++++++++++++ 9 files changed, 212 insertions(+), 35 deletions(-) create mode 100644 test/__snapshots__/webpackImporter-options.test.js.snap create mode 100644 test/webpackImporter-options.test.js diff --git a/README.md b/README.md index adb2a6e3..e624e831 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,12 @@ And run `webpack` via your preferred method. ## Options -| Name | Type | Default | Description | -| :-------------------------------------: | :------------------: | :----------------------: | :----------------------------------------------------- | -| **[`lessOptions`](#lessoptions)** | `{Object\|Function}` | `{ relativeUrls: true }` | Options for Less. | -| **[`additionalData`](#additionalData)** | `{String\|Function}` | `undefined` | Prepends/Appends `Less` code to the actual entry file. | -| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps. | +| Name | Type | Default | Description | +| :---------------------------------------: | :------------------: | :----------------------: | :----------------------------------------------------- | +| **[`lessOptions`](#lessoptions)** | `{Object\|Function}` | `{ relativeUrls: true }` | Options for Less. | +| **[`additionalData`](#additionalData)** | `{String\|Function}` | `undefined` | Prepends/Appends `Less` code to the actual entry file. | +| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps. | +| **[`webpackImporter`](#webpackimporter)** | `{Boolean}` | `true` | Enables/Disables the default Webpack importer. | ### `lessOptions` @@ -296,6 +297,39 @@ module.exports = { }; ``` +### `webpackImporter` + +Type: `Boolean` +Default: `true` + +Enables/Disables the default Webpack importer. + +This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starting with `~` will not work. + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.less$/i, + use: [ + 'style-loader', + 'css-loader', + { + loader: 'less-loader', + options: { + webpackImporter: false, + }, + }, + ], + }, + ], + }, +}; +``` + ## Examples ### Normal usage diff --git a/src/options.json b/src/options.json index 3481c51c..cc1cf3fa 100644 --- a/src/options.json +++ b/src/options.json @@ -27,6 +27,10 @@ "sourceMap": { "description": "Enables/Disables generation of source maps (https://github.com/webpack-contrib/less-loader#sourcemap).", "type": "boolean" + }, + "webpackImporter": { + "description": "Enables/Disables default `webpack` importer (https://github.com/webpack-contrib/less-loader#webpackimporter).", + "type": "boolean" } }, "additionalProperties": false diff --git a/src/utils.js b/src/utils.js index 599eb951..b2113be6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -157,7 +157,14 @@ function getLessOptions(loaderContext, loaderOptions) { ...options, }; - lessOptions.plugins.unshift(createWebpackLessPlugin(loaderContext)); + const shouldUseWebpackImporter = + typeof loaderOptions.webpackImporter === 'boolean' + ? loaderOptions.webpackImporter + : true; + + if (shouldUseWebpackImporter) { + lessOptions.plugins.unshift(createWebpackLessPlugin(loaderContext)); + } const useSourceMap = typeof loaderOptions.sourceMap === 'boolean' diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index b7939fe3..6d4b7738 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -379,26 +379,10 @@ exports[`loader should resolve all imports from node_modules using webpack's res " `; -exports[`loader should resolve all imports from node_modules using webpack's resolver: css 2`] = ` -"@import \\"~@scope/css.css\\"; -.modules-dir-scope-module, -#it-works { - color: hotpink; -} -#it-works { - margin: 10px; -} -" -`; - exports[`loader should resolve all imports from node_modules using webpack's resolver: errors 1`] = `Array []`; -exports[`loader should resolve all imports from node_modules using webpack's resolver: errors 2`] = `Array []`; - exports[`loader should resolve all imports from node_modules using webpack's resolver: warnings 1`] = `Array []`; -exports[`loader should resolve all imports from node_modules using webpack's resolver: warnings 2`] = `Array []`; - exports[`loader should resolve all imports from the given paths using Less resolver: css 1`] = ` ".modules-dir-some-module { color: hotpink; diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap index 45c3e9e4..e3c85e22 100644 --- a/test/__snapshots__/validate-options.test.js.snap +++ b/test/__snapshots__/validate-options.test.js.snap @@ -120,3 +120,57 @@ exports[`validate options should throw an error on the "sourceMap" option with " - options.sourceMap should be a boolean. -> Enables/Disables generation of source maps (https://github.com/webpack-contrib/less-loader#sourcemap)." `; + +exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` +"Invalid options object. Less 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 { lessOptions?, additionalData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "webpackImporter" option with "string" value 1`] = ` +"Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. + - options.webpackImporter should be a boolean. + -> Enables/Disables default \`webpack\` importer (https://github.com/webpack-contrib/less-loader#webpackimporter)." +`; diff --git a/test/__snapshots__/webpackImporter-options.test.js.snap b/test/__snapshots__/webpackImporter-options.test.js.snap new file mode 100644 index 00000000..3d23968b --- /dev/null +++ b/test/__snapshots__/webpackImporter-options.test.js.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`webpackImporter option not specify webpackImporter option: css 1`] = ` +"@import \\"~some/css.css\\"; +@import \\"~some/css.css\\"; +#it-works { + color: hotpink; +} +.modules-dir-some-module, +#it-works { + background: hotpink; +} +#it-works { + margin: 10px; +} +" +`; + +exports[`webpackImporter option not specify webpackImporter option: errors 1`] = `Array []`; + +exports[`webpackImporter option not specify webpackImporter option: warnings 1`] = `Array []`; + +exports[`webpackImporter option webpackImporter option is false: errors 1`] = ` +Array [ + "ModuleBuildError: Module build failed (from \`replaced original path\`): +", +] +`; + +exports[`webpackImporter option webpackImporter option is false: warnings 1`] = `Array []`; + +exports[`webpackImporter option webpackImporter option is true: css 1`] = ` +"@import \\"~some/css.css\\"; +@import \\"~some/css.css\\"; +#it-works { + color: hotpink; +} +.modules-dir-some-module, +#it-works { + background: hotpink; +} +#it-works { + margin: 10px; +} +" +`; + +exports[`webpackImporter option webpackImporter option is true: errors 1`] = `Array []`; + +exports[`webpackImporter option webpackImporter option is true: warnings 1`] = `Array []`; diff --git a/test/loader.test.js b/test/loader.test.js index 25c9840d..e8076eb8 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -176,19 +176,6 @@ describe('loader', () => { expect(getErrors(stats)).toMatchSnapshot('errors'); }); - it("should resolve all imports from node_modules using webpack's resolver", async () => { - const testId = './import-scope.less'; - const compiler = getCompiler(testId); - const stats = await compile(compiler); - const codeFromBundle = getCodeFromBundle(stats, compiler); - const codeFromLess = await getCodeFromLess(testId); - - expect(codeFromBundle.css).toBe(codeFromLess.css); - expect(codeFromBundle.css).toMatchSnapshot('css'); - expect(getWarnings(stats)).toMatchSnapshot('warnings'); - expect(getErrors(stats)).toMatchSnapshot('errors'); - }); - it('should resolve aliases in diffrent variants', async () => { const testId = './import-webpack-aliases.less'; const compiler = getCompiler( diff --git a/test/validate-options.test.js b/test/validate-options.test.js index 91340351..d699720c 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -19,6 +19,14 @@ describe('validate options', () => { success: [true, false], failure: ['string'], }, + webpackImporter: { + success: [true, false], + failure: ['string'], + }, + unknown: { + success: [], + failure: [1, true, false, 'test', /test/, [], {}, { foo: 'bar' }], + }, }; function stringifyValue(value) { diff --git a/test/webpackImporter-options.test.js b/test/webpackImporter-options.test.js new file mode 100644 index 00000000..1bf8415d --- /dev/null +++ b/test/webpackImporter-options.test.js @@ -0,0 +1,49 @@ +import { + compile, + getCodeFromBundle, + getCodeFromLess, + getCompiler, + getErrors, + getWarnings, +} from './helpers'; + +describe('webpackImporter option', () => { + it('not specify webpackImporter option', async () => { + const testId = './import-webpack.less'; + const compiler = getCompiler(testId); + const stats = await compile(compiler); + const codeFromBundle = getCodeFromBundle(stats, compiler); + const codeFromLess = await getCodeFromLess(testId); + + expect(codeFromBundle.css).toBe(codeFromLess.css); + expect(codeFromBundle.css).toMatchSnapshot('css'); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); + + it('webpackImporter option is true', async () => { + const testId = './import-webpack.less'; + const compiler = getCompiler(testId, { + webpackImporter: true, + }); + const stats = await compile(compiler); + const codeFromBundle = getCodeFromBundle(stats, compiler); + const codeFromLess = await getCodeFromLess(testId); + + expect(codeFromBundle.css).toBe(codeFromLess.css); + expect(codeFromBundle.css).toMatchSnapshot('css'); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); + + it('webpackImporter option is false', async () => { + const testId = './import-webpack.less'; + const compiler = getCompiler(testId, { + webpackImporter: false, + }); + const stats = await compile(compiler); + + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); +});