react-universally icon indicating copy to clipboard operation
react-universally copied to clipboard

[FAQ] flash of unstyled content

Open bradennapier opened this issue 7 years ago • 13 comments

May not be worth adding since I believe this should only happen during development - but it does annoy me quite a bit. It could be worth looking into implementing a solution similar to what was done by universal-webpack

bradennapier avatar Jan 13 '17 23:01 bradennapier

Understand it's annoying, but I don't want to introduce hacks around this.

Let's update the FAQ though.

ctrlplusb avatar Jan 23 '17 16:01 ctrlplusb

How about using something like isomorphic-style-loader, which is used in react-starter-kit? I'd happily work on a PR, but am not comfortable with isomorphic apps enough to give it a shot just yet. Can anyone assess this approach? Will it work well? Is it worth to try? @ctrlplusb

elektronik2k5 avatar Feb 25 '17 20:02 elektronik2k5

Something like this in the HTML component will lessen the effect, if not solve it completely.

        ${
          _.keys(assets.css).length === 0 ?
            `<style>${
              // $FlowIssue
              require('../styles/normalize.css')._style +
              // $FlowIssue
              require('../components/App/styles.scss')._style +
              // $FlowIssue
              require('../components/Home/styles.scss')._style +
              // $FlowIssue
              require('../components/NotFound/styles.scss')._style
            }</style>` : ''
        }

strues avatar Feb 26 '17 03:02 strues

Hard-coding css file imports is not a solution IMO.

You need to enable extract-text-plugin on the server end, something along these lines:

// ./internal/webpack/configFactory.js

// in plugins

ifElse(isDev && isServer)(
  () => new ExtractTextPlugin({
    filename: 'dev-styles.css', allChunks: true,
  }),
),

// in module.rules css section

ifElse(isDev && isServer)(() => ({
  loader: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader/locals'], // You have to use locals on the server (no window).
  }),
})),

// ./server/middleware/reactApplication/ServerHTML.js
const headerElements = removeNil([
  // ...
  onlyIf(process.env.BUILD_FLAG_IS_DEV, () => stylesheetTag('/dev-styles.css')),
]);

birkir avatar Feb 26 '17 09:02 birkir

@birkir @strues @ctrlplusb can anyone more knowledgeable than me please have a look at my suggestion above to solve this without reinventing the wheel? :wheel_of_dharma:

elektronik2k5 avatar Mar 04 '17 07:03 elektronik2k5

I'm not a fan of isomorphic style loader HOC s method so i cannot really comment on the issue. If what we already have can be configured to work rather than bringing in another dependency, I would rather support that :)

Did the above solution not work for you?

birkir avatar Mar 04 '17 15:03 birkir

I'm probably going to present an unpopular opinion, but I've basically grown accustomed to the FOUC. It's been so common that I've accepted it as part of the game. I do know you can avoid it by adding BrowserSync to the mix, but that itself can be another headache.

strues avatar Mar 04 '17 17:03 strues

@birkir,

I'm not a fan of isomorphic style loader HOC s method

Can you please elaborate? I haven't tried using it myself, so don't have an informed opinion :(. I just saw it is in use in the very popular react-starter-kit universal boilerplate and thought we can use it to solve the same issue.

elektronik2k5 avatar Mar 04 '17 19:03 elektronik2k5

@strues Same for me and other devs at Ueno., we actually like the flash of unstyled content. We have had some issues when we're calculating element dimensions in componentDidMount with something like getBoundingClientRect, as the styles have not loaded so we get incorrect dimensions. So we are forced to think about this, as this will happen with clients with slow network as well.

@elektronik2k5 In components that will be using styles you have to add higher order component (export default withStyles(styles)(MyComponent)). I am fine with HOC's in general for special occasions, but every damn component is brutal if you think about that the below example will fail:

// Demo.js
import s from './Demo.css';

class Demo {
  render() {
    return <div className={s.foo}>Node 1</div>;
  }
}
export default withStyles(s)(Demo);


// Demo.spec.js
test('Demo component has div.foo', () => {
  const component = shallow(<Demo />);
  expect(component.childAt(0).equals(<div className={s.foo} />)).to.equal(true);
});

Some will be fine with using contains, find, etc. This is just my personal opinion.

birkir avatar Mar 04 '17 21:03 birkir

Wondering if anyone here has figured out a solution to this FoUC yet?

@ctrlplusb Would you consider hiding the DOM node with the app until style has loaded in 'development' mode a hack? 😄

oyeanuj avatar Sep 30 '17 01:09 oyeanuj

Accept that it happens in development. 9.9999/10 if will not happen in production. Most of the time during development the cause is styled-components or a Webpack loader. Once the styles are compiled and served, you wont be experiencing it.

Alternatively, here's a solution:

        ${
          _.keys(assets.css).length === 0 ?
            `<style>${
              // $FlowIssue
              require('../styles/normalize.css')._style +
              // $FlowIssue
              require('../components/App/styles.scss')._style +
              // $FlowIssue
              require('../components/Home/styles.scss')._style +
              // $FlowIssue
              require('../components/NotFound/styles.scss')._style
            }</style>` : ''
        }

Load each and every individual style 👎 .

strues avatar Sep 30 '17 02:09 strues

@strues It seems like it shouldn't be happening with styled-components according to these comments in that repo?

oyeanuj avatar Sep 30 '17 20:09 oyeanuj

An update:

So, I've fixed the FoUC with Styled-Component as part of #505. It turns out the SC styles were never being rendered on the server, only the client. With that fixed, FoUC from SC is gone in that feature branch. Check out https://github.com/ctrlplusb/react-universally/pull/505

Now that leaves three other sources of FoUC - Normalize.css, Globals.css, and Milligram.

For the SC feature branch: The first two of these can be fixed by using Polished (or other similar styled-components normalize/reset libraries), and using injectGlobal for globals.css. Solution for Milligrammight also beinjectGlobal`.

Not sure about solutions in the master branch.

oyeanuj avatar Oct 01 '17 00:10 oyeanuj