0

I used to use less-middleware, but switched to less as I needed to add custom functions/constants. I assume less-middleware uses less behind the scenes.

To define constants I used:

function lessDefine(name, value) {
  less.tree.functions[name] = function () {
    return new (less.tree.Anonymous)(value);
  };
}

and to create a constant:

lessDefine('backgroundImage', config.backgroundImage);

Then to link into Express:

router.use('/stylesheets',
  less.middleware(
    lessOpts.source, lessOpts.main,
    lessOpts.parser, lessOpts.compiler));

This was after crawling through bug reports, feature requests and google results, as the ability to extend LESS is not well documented. This worked last week, but now I see:

TypeError: Object #<Object> has no method 'middleware'

when I try to launch my node app.

What is the "correct" way to add functions/constants to LESS in Node.js?

Note that I use:

var less = require('less');
var lessMiddleware = require('less-middleware');

And my package.json uses the following version limits:

less-middleware: 1.0.3
less: 1.7.x
Mark K Cowan
  • 1,755
  • 1
  • 20
  • 28
  • I have no idea what `router.use(...)` should do but does `less` object really have this `middleware` method? It all depends on how you've create it I guess (i.e. if you use [`less`](https://github.com/less/less.js) to create `less` object then obviously it has no `middleware` method). – seven-phases-max Jun 21 '14 at 10:28
  • The code worked a week or so ago but not now. The `middleware` method was added by `require`ing `less-middleware` I think. But evidently it is not there now. – Mark K Cowan Jun 21 '14 at 10:30
  • I.e. it looks like what you really need is just to understand how to use `less` instead of `less-middleware` (in context of `Express`). It does not look like it has anything to do with adding functions to the less itself (injecting one into `less.tree.functions` is the correct method I suppose). – seven-phases-max Jun 21 '14 at 10:33
  • So you have two independent instances of Less compiler in your script: `less` (create with 'less') and `lessMiddleware` (created with 'less-middleware'). Now which one you actually use to compile your less files? – seven-phases-max Jun 21 '14 at 10:39
  • I assume `less-middleware` uses the `less` module on the backend. So I'm `require`ing `less` to configure it, but invoking `less-middleware` now (instead of `less.middleware`) to have less called when needed from the middleware stack. I just ran an `npm dedupe` and ensured that I only have one instance of the `less` module installed, so I'll check again now to see if its working. – Mark K Cowan Jun 21 '14 at 10:42
  • Yes, `less-middleware` may use `less` module behind the scenes but you don't access it by creating *another* object with `var less = require('less');`. – seven-phases-max Jun 21 '14 at 10:44
  • The dedupe worked, now I'll take a look through the `less-middleware` code to see where it exposes its instance of `less`. – Mark K Cowan Jun 21 '14 at 10:45
  • Interestingly, while searching, I see: `module.exports = less.middleware = function(source, options, parserOptions, compilerOptions)`... I guess duplicate instances of the module were the initial problem. – Mark K Cowan Jun 21 '14 at 10:49

1 Answers1

0

less.middleware is added by the less-middleware module.

Monkeypatching is frowned upon for a reason; less-middleware had its own less module installed within its folder (by npm), while my app was using a separate instance of less.

Hence, less.middleware was not being set in the instance of less that my app sees. After calling npm dedupe, the duplicate instances were consolidated and my app now works.

Mark K Cowan
  • 1,755
  • 1
  • 20
  • 28
  • Still looks quite weird. A webapp should not depend on where its `npm` modules are installed. In your case accessing the `tree.functions` via another instance of `less` object works only because `tree.functions` itself is a sort of global singleton (that's why it works after `dedupe` and does not w/o it). Ideally you have find the way to get access to the `tree.functions` through the object exposed by the `less-middleware` module (or completely get rid of it and use only `less` module). – seven-phases-max Jun 23 '14 at 09:02
  • Middleware doesnt expose the underlying less instance, it only monkey patches its instance instead – Mark K Cowan Jun 23 '14 at 10:18
  • Then you simply need to use this "monkey-patched" object to access `tree.functions`. E.g. `var lessMiddleware = require('less-middleware'); lessMiddleware.tree.functions[name] = function () { ...`. – seven-phases-max Jun 23 '14 at 10:32
  • Yes, the original problem was that the monkey-patched object wasn't accessible due to duplicate module instances. – Mark K Cowan Jul 11 '14 at 12:48