GoogleChromeLabs / critters

🦔 A Webpack plugin to inline your critical CSS and lazy-load the rest.
https://npm.im/critters-webpack-plugin
Apache License 2.0
3.42k stars 108 forks source link

handling multiple HTMLWebpackPlugin instances & pruneSource #29

Open ezekielchentnik opened 5 years ago

ezekielchentnik commented 5 years ago

Critters doesn't appear to play nice with multiple HTMLWebpackPlugin instances when using pruneSource: true (see snippet below).

Effectively, once Critters 'prunes' the original stylesheet then processes subsequent html pages, it can't extract css when it no longer exists in the source.

I'm not sure the best way we can fix this (or if it makes sense to?). For now I'm simply not pruning the source pruneSource: false.

const URLS = [
  { "url": "/", "title": "Welcome" },
  { "url": "/tacos", "title": "Tacos" }
];

// ...

plugins: [

  new CrittersPlugin({
    mergeStylesheets: false,
    logLevel: "error",
    pruneSource: true // default
  }),

  ...URLS.map(({ url, title }) => {
    const options = {
      string: true,
      params: { url, title, mode }
    };
    const template = `!!prerender-loader?${JSON.stringify(options)}!${join(
      src,
      "index.html"
    )}`;
    return new HTMLWebpackPlugin({
      template,
      filename: join(dist, url, "index.html"),
      favicon: join(src, "assets/favicon.ico"), // perf 101, avoid penalties with missing favicon
      minify: isProd && {
        // minify our html for a tidy response
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        removeScriptTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true
      },
      inject: true // inject bundles assets automatically
    });
  }),

  // ...
]
tlambrou commented 5 years ago

+1

developit commented 5 years ago

In general, pruneSource can't be used with multi-page sites, since it either over-prunes for some pages or produces one CSS file per-page. My recommendation has generally been to use pruneSource:false when prerendering/generating multiple pages.

This might seem an odd choice, but the result is your lazy-loaded CSS is agnostic to the page and you don't end up with one cache entry per page (would be bad). I'm not 100% sure how other critical solutions handle this, but personally I've been having good luck with the non-pruning solution.