Skip to content

Commit

Permalink
feat: add loader context in less plugins (#378)
Browse files Browse the repository at this point in the history
  • Loading branch information
cap-Bernardito authored Aug 25, 2020
1 parent 12dca5b commit 7b7fc5e
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 2 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,7 @@ module.exports = {

### Plugins

In order to use [plugins](http://lesscss.org/usage/#plugins), simply set the
`plugins` option like this:
In order to use [plugins](http://lesscss.org/usage/#plugins), simply set the `plugins` option like this:

```js
// webpack.config.js
Expand All @@ -499,6 +498,20 @@ module.exports = {
};
```

> ℹ️ Access to the [loader context](https://webpack.js.org/api/loaders/#the-loader-context) inside the custom plugin can be done using the `less.webpackLoaderContext` property.
```js
module.exports = {
install: function (less, pluginManager, functions) {
functions.add('pi', function () {
// Loader context is available in `less.webpackLoaderContext`

return Math.PI;
});
},
};
```

### Extracting style sheets

Bundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or [hot module replacement](https://webpack.js.org/concepts/hot-module-replacement/) in development. In production, on the other hand, it's not a good idea to apply your style sheets depending on JS execution. Rendering may be delayed or even a [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) might be visible. Thus it's often still better to have them as separate files in your final production build.
Expand Down
7 changes: 7 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ function getLessOptions(loaderContext, loaderOptions) {
lessOptions.plugins.unshift(createWebpackLessPlugin(loaderContext));
}

lessOptions.plugins.unshift({
install(lessProcessor) {
// eslint-disable-next-line no-param-reassign
lessProcessor.webpackLoaderContext = loaderContext;
},
});

const useSourceMap =
typeof loaderOptions.sourceMap === 'boolean'
? loaderOptions.sourceMap
Expand Down
11 changes: 11 additions & 0 deletions test/__snapshots__/loader.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,17 @@ exports[`loader should watch imports correctly: errors 1`] = `Array []`;
exports[`loader should watch imports correctly: warnings 1`] = `Array []`;
exports[`loader should work loaderContext in less plugins: css 1`] = `
".webpackLoaderContext {
isDefined: true;
}
"
`;
exports[`loader should work loaderContext in less plugins: errors 1`] = `Array []`;
exports[`loader should work loaderContext in less plugins: warnings 1`] = `Array []`;
exports[`loader should work third-party plugins as fileLoader: css 1`] = `
".file-loader {
background: coral;
Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/basic-plugins.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@plugin "plugin-1";

.webpackLoaderContext {
isDefined: run();
}
11 changes: 11 additions & 0 deletions test/fixtures/plugin-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
registerPlugin({
install: function(less, pluginManager, functions) {
functions.add('run', function() {
if (typeof less.webpackLoaderContext !== 'undefined') {
return 'true';
}

return 'false';
});
}
})
46 changes: 46 additions & 0 deletions test/loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -727,4 +727,50 @@ describe('loader', () => {
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('should work loaderContext in less plugins', async () => {
let contextInClass;
let contextInObject;

// eslint-disable-next-line global-require
class Plugin extends require('less').FileManager {
constructor(less) {
super();

if (typeof less.webpackLoaderContext !== 'undefined') {
contextInClass = true;
}
}
}

class CustomClassPlugin {
// eslint-disable-next-line class-methods-use-this
install(less, pluginManager) {
pluginManager.addFileManager(new Plugin(less));
}
}

const customObjectPlugin = {
install(less) {
if (typeof less.webpackLoaderContext !== 'undefined') {
contextInObject = true;
}
},
};

const testId = './basic-plugins.less';
const compiler = getCompiler(testId, {
lessOptions: {
plugins: [new CustomClassPlugin(), customObjectPlugin],
},
});
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle(stats, compiler);

expect(contextInClass).toBe(true);
expect(contextInObject).toBe(true);
expect(codeFromBundle.css).toMatchSnapshot('css');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
});

0 comments on commit 7b7fc5e

Please sign in to comment.