FortAwesome / react-fontawesome

Font Awesome React component
https://fontawesome.com
MIT License
3.69k stars 265 forks source link

Server-rendering + webpack... styles? #27

Closed stephen-last closed 6 years ago

stephen-last commented 6 years ago

I'm using React server-rendering and webpack, which works, however the CSS isn't server rendered.

I've looked at this page: https://fontawesome.com/how-to-use/server-side-rendering, however it's not clear to me how to get the CSS from @fortawesome/fontawesome to be picked up by webpack and included in my CSS bundle.

I also need to stop the inserting of the <style> tag in the <head> by the client-side fontawesome js.

Server-rendering with js disabled in the browser means no CSS for font awesome (the base styles), so I'm seeing this:

If the CSS is missing when this icon displays in the browser it will flash from a very large icon down to a properly sized one a moment later.

Are there any solutions for this..?

davidfurlong commented 6 years ago

my issue is a duplicate it seems.

stephen-last commented 6 years ago

Yep, I commented on yours...

I'm looking into this: https://fontawesome.com/how-to-use/font-awesome-api

This seems to work to stop the <style> tag being added.

fontawesome.config = {
  autoAddCss: false
}

Still trying to get the base styles into my bundle.

davidfurlong commented 6 years ago

@stephen-last I think the solution lies here:

fontawesome.dom.css()

Generates the accompanying CSS that is necessary to correctly display icons. If you choose to disable autoAddCss in the configuration you’ll need to grab these styles and insert them manually into the DOM.
davidfurlong commented 6 years ago

The css added may be dynamic => in your server render we need to call fontawesome.dom.css() and insert it into the head.

stephen-last commented 6 years ago

I was just looking at fontawesome.dom.css().

I've added it but no CSS is added to the bundle.

davidfurlong commented 6 years ago

I've added it but no CSS is added to the bundle.

I don't think thats intended to happen. Probably easiest to inline this css in the <head></head> for now. It's fairly long though, and doesn't seem particularly dynamic...

In order to bundle it we would need a webpack plugin that takes the output of fontawesome.dom.css(), adds it to your bundle and then reference it in your head. This is similar to the way fontawesome worked with webpack in version 4.

davidfurlong commented 6 years ago

For reference, here is the dom.css() method, which does do some dynamic stuff

var css = function () {
  var dfp = DEFAULT_FAMILY_PREFIX;
  var drc = DEFAULT_REPLACEMENT_CLASS;
  var fp = config.familyPrefix;
  var rc = config.replacementClass;
  var s = baseStyles;

  if (fp !== dfp || rc !== drc) {
    var dPatt = new RegExp('\\.' + dfp + '\\-', 'g');
    var rPatt = new RegExp('\\.' + drc, 'g');

    s = s.replace(dPatt, '.' + fp + '-').replace(rPatt, '.' + rc);
  }

  return s;
};

It looks like it mainly configures the css classNames according to the API config stuff. Looks like a webpack plugin where you can pass the options and add to your entry will solve this issue. I think I know enough to make it myself right now, however there seem to be a couple ways to do this, and some rely on a static config.

stephen-last commented 6 years ago

I've got this working...

import fontawesome from '@fortawesome/fontawesome'
import { OriginalSource } from 'webpack-sources'

class FontAwesome {
  apply (compiler) {
    compiler.plugin('compilation', (compilation) => {
      compilation.plugin('additional-assets', (callback) => {
        compilation.assets['css/fontawesome.css'] = new OriginalSource(
          fontawesome.dom.css(),
          'fontawesome.css'
        )
        callback()
      })
    })
  }
}

export default FontAwesome

It spits out a new CSS file with the FA base styles.

Going to see if I can add to the CSS asset I already create, rather than create a new asset. I'll keep posting here with what I have.

stephen-last commented 6 years ago

compilation.assets['css/fontawesome.css'] = new RawSource(fontawesome.dom.css())

Also works...

stephen-last commented 6 years ago

I've asked for help here: https://stackoverflow.com/questions/47714048/webpack-insert-add-new-css-to-the-bundle

robmadole commented 6 years ago

In the latest release of @fortawesome/fontawesome we've included the CSS for this as an external file. The packages.json points to it with the style property. I think the postcss plugins will use this value. Let me know if that helps.

davidfurlong commented 6 years ago

@stephen-last I think we can close this issue thanks @robmadole