Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing selector when using sourcemaps, plugins, and compiling Less files in parallel #3574

Closed
TopGrd opened this issue Dec 14, 2020 · 29 comments · May be fixed by PGP-or-D1E/openlibrary#6
Closed

Comments

@TopGrd
Copy link

TopGrd commented Dec 14, 2020

I have some code like bottom.

	@root-name: business-bundle
    /* other file */
	.@{root-name} .wrapper{
		/* css... */
	}

When webpack use less 3.12.2, that is ok. But when use 3.13.0, webpack build error.
image

@matthew-dean
Copy link
Member

@TopGrd That really isn't enough to go on, especially when it's an error in a package that Less doesn't maintain. Can you make a test repo with a minimal test case? Also, does this error occur when just using lessc to compile your Less code?

@endze1t
Copy link

endze1t commented Dec 16, 2020

Having a similar issue with v3.13.0 - 3.12.2 working for me as well.

image

It's a huge project, so nearly impossible to find where in the less file this happend.

@matthew-dean
Copy link
Member

matthew-dean commented Dec 16, 2020

@endbay @TopGrd

I'm not sure what's expected here. With no reproducible example, and with the error not thrown in Less itself, there's no hope in a resolution. Someone will need to set a breakpoint at that error and see what selector was expected and why it isn't present.

@matthew-dean
Copy link
Member

matthew-dean commented Dec 16, 2020

@TopGrd

One clue, this Less code is invalid:

	@root-name: business-bundle
    /* other file */
	.@{root-name} .wrapper{
		/* css... */
	}

@root-name: business-bundle is missing a semi-colon. So it could be that you have some library layered on top of Less which is expecting an error, doesn't find one, and tries to go ahead and parse Less's output, but fails with this "missing selector" error. That's just a guess, since I have no repo to look at.

@Justineo
Copy link
Contributor

Justineo commented Dec 16, 2020

I'm experiencing a similar problem in 3.13.0. (Still trying to find out a minimal reproduction.)

Related code looks like:

// button.less
@import "./lib.less";

.@{prefix}-button {
  color: red;

  &:hover {
    color: blue;
  }
}
// lib.less
@import "./vars"; // where @prefix is defined

Which is compiled as:

{
  color: red;
}

:hover {
  color: blue;
}

It's weird that no compilation error occurred.

@TopGrd
Copy link
Author

TopGrd commented Dec 16, 2020

@matthew-dean It is a very huge project where error occurred. I am trying to reproduce it in a demo

@TopGrd
Copy link
Author

TopGrd commented Dec 16, 2020

@TopGrd

One clue, this Less code is invalid:

	@root-name: business-bundle
    /* other file */
	.@{root-name} .wrapper{
		/* css... */
	}

@root-name: business-bundle is missing a semi-colon. So it could be that you have some library layered on top of Less which is expecting an error, doesn't find one, and tries to go ahead and parse Less's output, but fails with this "missing selector" error. That's just a guess, since I have no repo to look at.

@root-name: business-bundle; Sorry, this is my code. It have a semi-colon.

@TopGrd
Copy link
Author

TopGrd commented Dec 16, 2020

I'm experiencing a similar problem in 3.13.0. (Still trying to find out a minimal reproduction.)

Related code looks like:

// button.less
@import "./lib.less";

.@{prefix}-button {
  color: red;

  &:hover {
    color: blue;
  }
}
// lib.less
@plugin "~some-less-plugin"; // where @prefix is injected which preprocessing plugins

Which is compiled as:

{
  color: red;
}

:hover {
  color: blue;
}

It's weird that no compilation error occurred.

I use style-resources-loader to inject some global variables too. Maybe it has something to do with that?

{
  test: /\.less$/i,
  use: [
    {
      loader: MiniCssExtractPlugin.loader,
      options: {
        hmr: process.env.NODE_ENV === 'development',
        reloadAll: true,
      },
    },
    {
      loader: 'css-loader',
    },
    {
      loader: 'postcss-loader',
      options: {
        config: {
          path: path.resolve(__dirname, '../postcss.config.js'),
        },
      },
    },
    {
      loader: 'less-loader',
      options: {
        lessOptions: {
          javascriptEnabled: true,
          paths: [path.resolve(cwd, 'node_modules')],
        },
      },
    },
    {
      loader: 'style-resources-loader',
      options:{
            patterns: path.resolve(
              cwd,
              './node_modules/@somemodule/style/index.less',
            ),
            injector: 'prepend',
          },
    },
  ],
},

@TopGrd
Copy link
Author

TopGrd commented Dec 16, 2020

My code:
image

debugger less.render output: no selector
image

The variable @{bundle-root-class} is settingBundle. It looks like the variables in the first line are not compiled?

@Justineo
Copy link
Contributor

Justineo commented Dec 16, 2020

Still cannot find out a simple reproduction. It's very weird that when hot module replacement is triggered and the compiled output of the changed file seems to be correct. And the problem only occurs for selector interpolation:

@import "./lib.less";

.@{prefix}-button {
  val: @prefix;
}

Compiles to:

{
  val: foo;
}

(Note the whole selector is missing, not only the interpolated part.)

@matthew-dean
Copy link
Member

@Justineo

the compiled output of the changed file seems to be correct

Can you expand on this a bit more? The compiled output from Less seems to be correct, but it's not getting replaced correctly?

@matthew-dean
Copy link
Member

It's very weird that when hot module replacement is triggered and the compiled output of the changed file seems to be correct.

@Justineo This is a helpful clue. It's likely related to the resolution of this: #3434

In short, tree caching was removed from Less for a time, but it seemed to have too much of a negative performance impact in some scenarios, so I put it back in. It could be that Less is therefore not resetting some state of import trees, which ONLY causes an issue in a "live" environment where less.parse is called multiple times. Hmm, I wonder if I can test that theory in a reproduction.

@matthew-dean
Copy link
Member

@Justineo @TopGrd @endbay

Unfortunately, I still cannot reproduce this issue, so it's not debuggable. ☹️ If someone can make a repo where it's easily reproducible, I could step through it.

@PengJiyuan
Copy link

I'm experiencing a similar problem in 3.13.0. (Still trying to find out a minimal reproduction.)
Related code looks like:

// button.less
@import "./lib.less";

.@{prefix}-button {
  color: red;

  &:hover {
    color: blue;
  }
}
// lib.less
@plugin "~some-less-plugin"; // where @prefix is injected which preprocessing plugins

Which is compiled as:

{
  color: red;
}

:hover {
  color: blue;
}

It's weird that no compilation error occurred.

I use style-resources-loader to inject some global variables too. Maybe it has something to do with that?

{
  test: /\.less$/i,
  use: [
    {
      loader: MiniCssExtractPlugin.loader,
      options: {
        hmr: process.env.NODE_ENV === 'development',
        reloadAll: true,
      },
    },
    {
      loader: 'css-loader',
    },
    {
      loader: 'postcss-loader',
      options: {
        config: {
          path: path.resolve(__dirname, '../postcss.config.js'),
        },
      },
    },
    {
      loader: 'less-loader',
      options: {
        lessOptions: {
          javascriptEnabled: true,
          paths: [path.resolve(cwd, 'node_modules')],
        },
      },
    },
    {
      loader: 'style-resources-loader',
      options:{
            patterns: path.resolve(
              cwd,
              './node_modules/@somemodule/style/index.less',
            ),
            injector: 'prepend',
          },
    },
  ],
},

+1

Less @plugin + sourcemap will cause this problem

@matthew-dean 🙏

@matthew-dean
Copy link
Member

@PengJiyuan Can you create a reproducible example in a cloneable repo?

@kirazxyun
Copy link

+1
image
I think the problem is caused by this code. The tree node have wrong fileInfo In the case of parallel, which causes the inputSource is undefined.

@PengJiyuan
Copy link

+1
image
I think the problem is caused by this code. The tree node have wrong fileInfo In the case of parallel, which causes the inputSource is undefined.

@matthew-dean Wait a minute, we create a mini repo. We have located this line of code, hope to help you solve it quickly...

@kirazxyun
Copy link

+1
image
I think the problem is caused by this code. The tree node have wrong fileInfo In the case of parallel, which causes the inputSource is undefined.

This line of code has appeared since 3.10.0

@kirazxyun
Copy link

@PengJiyuan Can you create a reproducible example in a cloneable repo?

https://github.com/kirazxyun/less-question

This repo can reproduce the problem. You can run with 'npm run build',then view the results in the dist folder.

@kirazxyun
Copy link

@PengJiyuan Can you create a reproducible example in a cloneable repo?

https://github.com/kirazxyun/less-question

This repo can reproduce the problem. You can run with 'npm run build',then view the results in the dist folder.

@matthew-dean

@PengJiyuan
Copy link

@matthew-dean We use @plugin and it affects all our projects, please help us 🙏

@matthew-dean
Copy link
Member

@PengJiyuan You're right, the code in question shouldn't fail outputting the chunk if source map building doesn't work. It should be like:

                if (inputSource === undefined) {
                    this._css.push(chunk);
                    return;
                }

That would be a short-term fix, with the longer term fix being figuring out why one of the files has an incorrect import mapping. (It's probably being re-used when compiled in parallel.)

So I can do the temporary band-aid solution soon, and figure out the cause after.

matthew-dean added a commit to matthew-dean/less.js that referenced this issue Dec 17, 2020
@matthew-dean
Copy link
Member

@PengJiyuan @kirazxyun @Justineo etc please try testing with less@3.13.0-alpha.3

@Justineo
Copy link
Contributor

Problem solved with less@3.13.0-alpha.3. Thank you Matt!

@PengJiyuan
Copy link

@matthew-dean It works, thanks 🙏

@m1heng
Copy link

m1heng commented Dec 18, 2020

@matthew-dean confirm that problem is solved with less@3.13.0-alpha.3, hoping for a official release soon

@TopGrd TopGrd closed this as completed Dec 18, 2020
@TopGrd TopGrd reopened this Dec 18, 2020
@TopGrd
Copy link
Author

TopGrd commented Dec 18, 2020

It is solved with less@3.13.0-alpha.3.

@matthew-dean
Copy link
Member

3.13.1 published

@matthew-dean matthew-dean changed the title webpack build error when version is 3.13.0 Missing selector when using sourcemaps, plugins, and compiling Less files in parallel Dec 18, 2020
@matthew-dean
Copy link
Member

4.0.0 is also published, which contains this fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment