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

Test code splitting with PostCSS #5

Closed
leebenson opened this issue Apr 16, 2017 · 2 comments
Closed

Test code splitting with PostCSS #5

leebenson opened this issue Apr 16, 2017 · 2 comments
Assignees
Labels

Comments

@leebenson
Copy link
Member

Per leebenson/reactql#4

@leebenson
Copy link
Member Author

TL;DR CSS that is imported dynamically (i.e. via code-splitting) will wind up in dist/public/assets/css/styles.css, exactly the same as 'synced' code.

I experimented this morning with code-splitting and CSS. The aim was to see how PostCSS / CSS extraction works with Javascript that has been imported dynamically, that in turn calls out to CSS code synchronously.

I created a new ReactQL project, and used the following app code:

app.js

import React from 'react';

export default class Loader extends React.Component {
  constructor() {
    super();
    this.state = {
      codeSplit: <h1>Not loaded yet</h1>,
    };
  }
  componentDidMount() {
    import('./loaded').then(component => {
      this.setState({
        codeSplit: component.default(),
      });
    });
  }
  render() {
    return (
      <div>
        <h1>From the loading component</h1>
        {this.state.codeSplit}
      </div>
    );
  }
}

loaded.js

import React from 'react';
import css from './loaded.css';

export default () => (
  <h1 className={css.loaded}>This was code-split</h1>
);

loaded.css

.loaded {
  color: red;
}

I then built/ran the app with npm run build-run and this was the (expected) result:

screen shot 2017-04-19 at 10 59 24

Since I'm making a call to import inside of componentDidMount, the code-split component will only be asked for in the browser. This prevents an error stating that the server attempted to change a React component after it had already been rendered to HTML, and would simulate a 'truly' code-split component because it's a separate AJAX request back to the server for the loaded.js bundle:

screen shot 2017-04-19 at 11 01 47

Inside the style.css file that was generated by Webpack, you can see that the CSS class was pre-embedded, even though it's only called a) after the initial app.js code has rendered, and b) specifically from the browser, after componentDidMount fetches loaded.js, which in turn contains the import statement for loaded.css:

screen shot 2017-04-19 at 11 02 50

So, conclusion: CSS that is loaded via 'dynamic' or code-split components will still wind up in our production CSS, even if it doesn't form part of the initial call.

This means two things:

  1. It's safe to use CSS anywhere. You don't need to worry about style 'flicker', because even components that aren't loaded yet will have their styles pre-loaded by the bundle, ensuring they're available by the time the relevant component(s) is/are loaded.

  2. The bundle size will include ALL styles. If you have particularly heavy components that load lots of styles/fonts, etc and may or may not be relevant to your initial view, all associated styles will still be compiled into the sole styles.css file and loaded on any route. For 95% of web apps, this is a minor issue-- minified/gzipped styles generally represent a tiny fraction of the overall code base... but it is something to consider if you're using things like embedded fonts or images that inflate the styles.css file significantly. In those cases, a different loading mechanism or using styled components may be a better option.

Just some food for thought, for now. I'll be investigating different loading patterns for CSS and will report back here/update the docs accordingly.

@leebenson
Copy link
Member Author

I'll close this ticket. On reflection, having all stylesheet code wind up in a single file is ideal for the majority of use cases. It prevents flicker, and ensures that a consistent style is available across the whole application.

If more dynamic CSS is required with code-split components, then there are plenty of libraries where CSS can be written as plain JS inside the component file, and loaded ad-hoc. Even basic React style props can use JS in this way; no library required.

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

No branches or pull requests

1 participant