Extracting css without a media query
iamschulz opened this issue · 15 comments
Hi! Thank you for building this awesome package :)
Is there a way to extract the leftover css without media queries, additionally to the media-query chunks?
.red {
color: red;
}
@media (min-width:1080px) {
.red {
color: maroon;
}
}
That would give me the latter rule as style-lg.css
, but I still want to include style.css
with the former rule only. The MiniCssExtractPlugin only gives the complete css and the media-query-chunks back.
Here's my config:
module: {
rules: [
{
test: /styles.css/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
MediaQueryPlugin.loader,
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: `generated/css/[name].[contenthash].css`,
}),
new MediaQueryPlugin({
include: true,
queries: {
'(max-width:719px)': 'sm',
'(min-width:720px) and (max-width:1079px)': 'md',
'(min-width:1080px)': 'lg' }
}),
]
I'm facing the exact same issue. Judging by the readme, this seems to be a bug:
In case there's no match the extracted CSS gets simply emited as CSS file (it doesn't disappear in nirvana 😉).
@SassNinja can we get a quick info about whether this is intended or not? :)
@babielfe did you find solution?
@erichstark Sadly, I haven't been able to further work on it. :/ Still hoping for a reply from @SassNinja.
I wrote a new package for this - Extract CSS Media Queries
and a Laravel Mix extension - Laravel Mix Extract Media Queries
I hope they can help some of you. @babielfe , @erichstark - My first webpack plugin and my first published npm package!
@elambro thanks, I will look into it. Do you plan to add grouping for similair breakpoints to create only one file?
for example something like:
name: mobile,
breakpoints: [(min-width: 567px), (min-width: 567px) and (max-width: 767px)]
This could include all statements into one file xx-mobile.
@erichstark It targets mobile first CSS, so you can separate out the desktop style that mobile users don't have to download.
const options = {breakpoints:[567,767]}
Will give you 3 files:
style.css
- Common style, with all media queries@media (min-width: 567px)
and higher extracted out.style-767.css
- Only media queries@media(min-width: 767px)
and above. e.g.@media(min-width: 800px)
is also included.style-567.css
- Only media queries@media(min-width: 567px)
up to@media(min-width: 767px)
Duplicate media queries are merged in the results, then they're sorted with the highest min-width
(and min-height
) media queries at the bottom of the file.
@elambro that looks reasonable. I give it definitely a try! Btw I found this article about multiple media queries and all of them are downloaded anyway to the user :/
https://blog.tomayac.com/2018/11/08/why-browsers-download-stylesheets-with-non-matching-media-queries-180513/
I know, but they have low priority which will speed up the page load. The extracted stylesheet(s) can also be loaded with js after getting the page width.
Of course it can be loaded with JS, but then you get visible reflow of UI.
Hi everyone,
sorry for the long time I didn't respond – I had to take care of many private things
@iamschulz
Is there a way to extract the leftover css without media queries, additionally to the media-query chunks?
I'm afraid I don't understand your question.
Is the following your expected output?
// example.css
.red {
color: red;
}
// example-lg.css
@media (min-width: 1080px) {
.red {
color: maroon;
}
}
@babielfe same question to you:
would the above code meet your expectation?
@erichstark
Do you plan to add grouping for similair breakpoints to create only one file?
Are you aware this plugin supports grouping?
queries: {
'print, screen and (min-width: 60em)': 'desktop',
'print, screen and (min-width: 60em) and (orientation: landscape)': 'desktop'
}
Of course it can be loaded with JS, but then you get visible reflow of UI.
Yup, that's definitely true. Lazy loading stylesheets is not suitable for above-the-fold content.
Unfortunately it's sometimes not easy to separate critical from non-critical CSS.
However for lazy loaded components it can be quite useful to extract the media queries.
I've reread this issue and now I'm even less sure what's the problem.
First I thought it might be about this
queries: {
'(min-width: 1080px)': 'lg'
}
should behave identical to
queries: {
'(min-width:1080px)': 'lg'
}
(added as #46 btw)
However since the example of @iamschulz doesn't use the sass-loader it's apparently not the issue in talk.
Is it about extracting media queries of CSS which is included but doesn't match any defined query in the options?
// webpack.config.js
queries {
'(min-width: 1000px)': 'lg'
}
// example.scss
.foo { color: red; }
@media (min-width: 2000px) {
.foo { color: green }
}
Are you expecting an example.css
and an example-unkown-media.css
here?
If not I've really no idea what you guys expect.
@SassNinja Jumping in for @iamschulz here, since we are working on the same project.
I'm afraid I don't understand your question.
Is the following your expected output?// example.css .red { color: red; } // example-lg.css @media (min-width: 1080px) { .red { color: maroon; } }
You are completely right, that is the output we are expecting. However, what we are receiving is:
/* style.css */
.red {
color: red;
}
@media (min-width:1080px) {
.red {
color: maroon;
}
}
/* style-lg.css */
@media (min-width:1080px) {
.red {
color: maroon;
}
}
Is that the way the plugin is intended to behave? Or did we miss something in our configuration? Thanks for your help!
Is that the way the plugin is intended to behave?
Definitely not!
If this plugin finds a query match it extracts it and doesn't leave it in the original CSS.
Or did we miss something in our configuration?
I think so or maybe you've revealed an edge case that's not working.
Requires some investigation.
Would you share your package.json so I can better reproduce it?
Hi @SassNinja, thanks for you reply! After some investigation on our side, I found the error in our configuration and not in the MediaQueryPlugin. Sorry we bothered you without reason.
What happened: In addition to our example configuration, we also had the CopyWebpackPlugin configured, like so:
new CopyPlugin([
{
from: 'src/css/styles.css',
to: 'generated/css/[name].[hash].[ext]',
}
]),
The plugin copied the original source file over to the same output folder as the MiniCssExtractPlugin, using the same naming pattern. So the CopyPlugin basically overwrote all changes from the MediaQueryPlugin, reverting the whole file back to zero. Removing the obsolete copy rule solved the problem for us.
Hope this helps prevent similar misconfiguration in the future. And, again, sorry to bother you and thanks for your patience!
Edit: As I am not the author, I cannot close the issue, but feel free to do so yourself :)
I'm glad you've been able to solve the issue :-)