less.js
less.js copied to clipboard
Inconsistent results of multiple imports with `(reference)`.
Variables in @import statement cause for unexpected result.
I prepared demo app. https://github.com/mantsevich/less-variables-import-issue-demo
- download
- npm i
- npm start
- compare "correct.css" & "issue.css" files.
What do we have:
- Two similar files: entry-correct.less & entry-issue.less import 2 components: hello-galaxy & hello-world
- hello-world imports hello-galaxy component with (reference) flag
Difference in the source code: entry-issue.less uses variable in @import statement. Difference in the result: issue.css doesn't include hello-galaxy component at all.
Expected result: Result of CSS files should be identical.
I think problem related @import with variable in the path + @import (reference) in the child less files. If remove (reference) flag from hello-world.less file, then result will be "the same".
At quick glance I suspect it's about the "once import rule" and the order of imports:
Since hello-world.less already imports hello-galaxy.less, the second hello-galaxy.less import (the one in entry.less) is ignored. Thus different result with and without (reference) of the only applied import is expected.
In other words, it seems to be the same issue as #3040 (i.e. current behavior is expected, but there's room for a feature request if someone is interested to design/implement that).
I locally remove extra "/" - result the same.
I think it's different issue. Why does code work if I don't use variable in the path?
Working:
@import "./components/hello-world/hello-world.less";
@import "./components/hello-galaxy/hello-galaxy.less";
With issue:
@import "./@{path-to-components}/hello-world/hello-world.less";
@import "./@{path-to-components}/hello-galaxy/hello-galaxy.less";
Result: Correct entry - exports hello-galaxy, but issued (with variables in the path) - don't.
I tested this in both Less 3.9.0 and 2.7.3 and the issue that inconsistency being wider than just "variable-in-import-vs-reference".
Here's a few minimalistic examples to illustrate the inconsistency: whatever.less:
whatever {whatever: whatever}
indirect.less:
@import "whatever.less";
indirect-ref.less:
@import (reference) "whatever.less";
main-1:
@import (reference) "whatever.less";
@import "whatever.less"; // not imported
/* something */
main-2:
@import "indirect-ref.less";
@import "whatever.less"; // imported
/* something */
main-3:
@w: w;
@import "indirect-ref.less";
@import "@{w}hatever.less"; // not imported
/* something */
main-4:
@import "indirect-ref.less";
@import "indirect.less"; // not imported
/* something */
Labeling as a bug since regardless of what result we expect, what is important is that we expect the same output from all these main files (there're obviously other (in)direct-import/reference-vs-ones/var-interp combinations to imagine to suffer from this).
I guess this is related to https://github.com/less/less.js/pull/2729 (i.e. most likely a main-2-like code triggers some importing-chain patterns introduced there), thus it's basically a continuation of the issues mentioned in the PR.
Though I was not able to test Less 2.5.3 (the version before the #2729 patch) to make sure, as it no longer works with recent Node.js versions.
@mantsevich Still notice that technically it's entry-correct.less producing "wrong" result if compared to other snippets (despite it making more logical sense for your use-case). And the variable in the import only triggers the "proper" ("currently expected" per #3040) behavior I described in my previous post.