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

IE hacks like \9 in CSS bundles #3929

Open
electroluxcode opened this issue Sep 27, 2024 · 5 comments · May be fixed by #3930
Open

IE hacks like \9 in CSS bundles #3929

electroluxcode opened this issue Sep 27, 2024 · 5 comments · May be fixed by #3930

Comments

@electroluxcode
Copy link

electroluxcode commented Sep 27, 2024

quesion

can we add css hack to resolve the quesion about ie ?

i had read the #2925 , This is very similar. But I think this is still worthy of discussion.

background

image

In our company's project, it depend on antdv4 ,it has some code about ie hack 。when using webpack's cssnano for compression, everything is normal. However, when I use vite for compression, at first, there is a situation of disordered styles. Later, it is found that vite 's compression by default uses esbuild for compression. "\9" is parsed into ";", which leads to the failure of parsing all styles in the entire CSS file.

But when using another compression configuration of vite, lightingcss, it is normal.

In summary, for the compression scenario, both cssnano and lightingcss can correctly handle the hack situation for IE, but it seems that esbuild has a deficiency in this regard.

I also understand that when IE is no longer maintained, it is a bit redundant to be compatible with IE. But when the dependency library uses "\9", the situation I mentioned above may occur.

@electroluxcode
Copy link
Author

this is smallest example ,other libraries can correctly parse the information.

index.less

a::after {
    position: absolute;
    top: 0;
    display: none \9;
}

cssnano.js

import postcss from 'postcss';
import cssnanoPlugin from 'cssnano';
import fs from "fs"
let input = fs.readFileSync('./test/index.less','utf-8');


// postcss
postcss([cssnanoPlugin]).process(input).then(({ css }) => {
   console.log("css:", css)
})

lightningcss

import fs from 'fs'
import * as lightningcss  from 'lightningcss'
let input = fs.readFileSync('./test/index.less','utf-8');

let {code }=lightningcss.transform({
   cssModules: undefined,
   code: Buffer.from(input),
   minify: true,
 })

 console.log(code.toString())

esbuild

import fs from 'fs'
import { transform } from 'esbuild'

let input = fs.readFileSync('./test/index.less','utf-8');

transform(input, { loader: 'css',minify: true }).then(({
    code
 })=>{
    console.log(code)
 })

@electroluxcode electroluxcode linked a pull request Sep 27, 2024 that will close this issue
@evanw
Copy link
Owner

evanw commented Sep 27, 2024

Sorry, I don't understand what the problem is. Here is some HTML containing the code you wrote:

<style>
a::after {
    content: 'test';
    position: absolute;
    top: 0;
    display: none \9;
}
</style>
<a>example</a>

And here is that HTML after the CSS has been minified with esbuild:

<style>
a:after{content:"test";position:absolute;top:0;display:none \	}
</style>
<a>example</a>

Both of these HTML snippets render exactly the same in all relevant browsers. This makes sense because they are the same. Both \9 and \ are equivalent encodings of the same character (a tab character). You can read more about this in the issue you linked to: #2925 (comment). It looks like you are just raising #2925 again, but I still don't see a reason why esbuild should be doing anything different here.

"\9" is parsed into ";", which leads to the failure of parsing all styles in the entire CSS file.

I'm not sure why you say this since \9 is parsed into a tab character, not a semicolon. You can see that for yourself here.

@electroluxcode
Copy link
Author

electroluxcode commented Sep 27, 2024

Sorry, I don't understand what the problem is. Here is some HTML containing the code you wrote:

<style>
a::after {
    content: 'test';
    position: absolute;
    top: 0;
    display: none \9;
}
</style>
<a>example</a>

And here is that HTML after the CSS has been minified with esbuild:

<style>
a:after{content:"test";position:absolute;top:0;display:none \	}
</style>
<a>example</a>

Both of these HTML snippets render exactly the same in all relevant browsers. This makes sense because they are the same. Both \9 and \ are equivalent encodings of the same character (a tab character). You can read more about this in the issue you linked to: #2925 (comment). It looks like you are just raising #2925 again, but I still don't see a reason why esbuild should be doing anything different here.

"\9" is parsed into ";", which leads to the failure of parsing all styles in the entire CSS file.

I'm not sure why you say this since \9 is parsed into a tab character, not a semicolon. You can see that for yourself here.

Thank you for your reply. Let me explain the workspace I am facing. I currently have a main package A. Package A is compressed using cssnano of webpack. Then there is a sub-package A-1.Package A-1 is a dependency of package A. This sub-package is compressed using esbuild of vite. Therefore, the code where I actually encounter the problem is like this.

index.less

.ant-container{
    display: none \9;
}

esbuild.js

import fs from 'fs'
import { transform } from 'esbuild'
import postcss from 'postcss';
import cssnanoPlugin from 'cssnano';
let input = fs.readFileSync('./index.less','utf-8');

transform(input, { loader: 'css',minify: true }).then(({
    code
 })=>{
    // 写入文件
    postcss([cssnanoPlugin]).process(code).then(({ css }) => {
        console.log("css:", css)
        fs.writeFileSync('./index.css',css)
     })
 })

it will generate a css file like this ,

.ant-container{display:none \}

This CSS selector is escaped by \. Therefore, all CSS styles including this selector will not take effect.

@evanw
Copy link
Owner

evanw commented Sep 27, 2024

This is a bug with cssnano, not esbuild. You can find their repository here and file a bug with them: https://github.com/cssnano/cssnano. I tried https://cssnano.github.io/cssnano/playground/ and cssnano turns this:

a:after {
  display: none \	;
}

into this:

a:after{display:none \}

That's an invalid minification from cssnano. They are not following the CSS specification.

@electroluxcode
Copy link
Author

electroluxcode commented Sep 27, 2024

Yes, I agree with your point. The compression of cssnano indeed does not fully follow the CSS specification.

But just as the passage in the CSS specification says:

U+005C REVERSE SOLIDUS () If the input stream starts with a valid escape, reconsume the current input code point, consume an ident-like token, and return it

At this time, it should directly return as stated in the CSS specification. But now \9 is parsed into \, This is the same as cssnano and does not meet expectations. i think esbuild should turn into \9 like cssnano and lightingcss

lastly I think The official lack of support for IE is not a reason to abandon the adaptation of other libraries.Because there are still many libraries that still use this writing hack method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants