kriasoft / isomorphic-style-loader

CSS style loader for Webpack that is optimized for isomorphic (universal) web apps.
https://reactstarter.com
MIT License
1.27k stars 144 forks source link

Integrating with Extract Text Plugin #42

Open papigers opened 8 years ago

papigers commented 8 years ago

Is there a way to integrate the isomorphic style loader with the extract text plugin, which I currently use on prod? Also, how could you include many styles to single component? (for instance, in my root component, in addition to my style file I also include external styles like font awesome (.less) and bootstrap grid (.scss))

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/34670738-integrating-with-extract-text-plugin?utm_campaign=plugin&utm_content=tracker%2F26439769&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F26439769&utm_medium=issues&utm_source=github).
koistya commented 8 years ago

@papigers if you need to extract all the CSS into a single file for production, then there is no need in using isomorphic style loader for you, as you can just use regular style-loader provided by Webpack.

The goal of this loader is being able to extract critical path CSS and pre-render that CSS individually for each web page. For example:

<html>
  <head>
    <style>/* critical-path CSS, only what's required to render that page */</style>
    <script async src="/bundle.js"></script>
  </head>
  <body>
    <div id="container"><%-- pre-rendered HTML --%></div>
  </body>
</html>

For more info visit: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/

Regarding your second question, you can include multiple styles as follows:

import React from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s1 from './Style1.css';
import s2 from './Style2.css';

function MyComponent() {
  return <div className={`${s1.one} ${s2.two}`}>...</div>;
}

export default withStyles(s1, s2)(MyComponent);
papigers commented 8 years ago

Got it, thanks! So, between extract text plugin and isomorphic style loader, what is better, performance wise? On the one hand isomorphic style loader enables you to render only critical path css, as you said. But on the other hand extract text plugin bundles your entire css which can be fetched in parallel along the application code.

koistya commented 8 years ago

The approach with extract text plugin doesn't allow you to embed into the page critical-path CSS thus optimizing the initial page load time, also it requires at least two HTTP requests do download app code - one for bundle.css file and another one for bundle.js file, whereas with isomorphic style loader both CSS and JavaScript code can be downloaded with a single HTTP request that can be started asynchronously, e.g. when you put <script async src="/bundle.js"></script> in the head section of your HTML page.

papigers commented 8 years ago

K, thanks. I'm having difficulties deciding which tools are best for universal/isomorphic web development. I've used extract text plugin so far but I think I'll migrate to this. Any tips or tutorials you found useful? Also, how compatible is it with webpack-somorphic-tools?

mjsisley commented 8 years ago

What about accomplishing what ExtractTextPlugin does - a separate file, but pull the critical css out and put it inline as you are doing here. This may not be the tool for that... but that seems a good alternative for some use cases.

ezekielchentnik commented 8 years ago

@mjsisley agreed, trying to accomplish that myself. I want to async load a full css bundle, and inline critical path css. right now I'm running webpack twice. once to build critical path css bundle, and manually inlining, then a second time to produce my main bundle and asyncing loading it.

horyd commented 8 years ago

I've resorted to the same method as you @ezekielchentnik. It does the trick for now :)

alexanderchr commented 8 years ago

@ezekielchentnik

Inlining critical css and having the full css-bundle asynchronously loaded definitely seems to be the way to go. I've been experimenting with only using this loader server side and using extract-text-loader on the client, thus avoiding having to run webpack multiple times. Seems to work well enough.

papigers commented 8 years ago

@alexanderchr how to you accomplish loading css asynchronously? Does the link element have an async attribute, as the script element? or you just load it in the bottom of the body?

alexanderchr commented 8 years ago

I'm by no means an expert on this, but there seems to be a lot of browser inconsistency in how link tags are handled. Putting it in the body will work in some browsers while others will render-block as if it were in the head.

There is something like async, rel='preload' which would be ideal but its browser support is unimpressive. filamentgroup/loadCSS provides a polyfill for it. This is what I use.

More reading:

rossthedevigner commented 8 years ago

@ezekielchentnik or @horyd Do you have a gist of how you are accomplishing this?

...once to build critical path css bundle, and manually inlining, then a second time to produce my main bundle and asyncing loading it.

wzup commented 7 years ago

@koistya

you can just use regular style-loader provided by Webpack

Wrong! You can't use style-loader on server-side!