html-critical-webpack-plugin icon indicating copy to clipboard operation
html-critical-webpack-plugin copied to clipboard

"css should not be empty" with postcss config in next.js with purge css

Open vinutha93bnvs opened this issue 6 years ago • 7 comments

const path = require('path');
const glob = require('glob');
const webpack = require('webpack');
const withCSS = require('@zeit/next-css');
const withEslint = require('next-eslint');
const withImages = require('next-images');
const withPurgeCss = require('next-purgecss');
const withPlugins = require('next-compose-plugins');
const HtmlCriticalWebpackPlugin = require('html-critical-webpack-plugin');

const generatePathMaps = require('./helpers/generate-export-urls');
require('dotenv').config();

// const PATHS = {
//   src: path.join(__dirname, './pages'),
//   out: path.join(__dirname, './out'),
// };

class TailwindExtractor {
  static extract(content) {
    return content.match(/[A-Za-z0-9-_:/]+/g) || [];
  }
}

const nextConfig = {
  webpack: (config, { dev }) => {
    config.plugins.push(
      new webpack.EnvironmentPlugin(process.env),
      new HtmlCriticalWebpackPlugin({
        base: path.resolve(__dirname, ''),
        src: 'out/en-ca/index.html',
        dest: 'out/en-ca/index.html',
        // css: 'static/css/index.css',
        inline: true,
        minify: true,
        extract: true,
        width: 375,
        height: 565,
        penthouse: {
          timeOut: 300000,
          blockJSRequests: false,
        },
      })
    );

    return config;
  },
  useFileSystemPublicRoutes: false,
  exportPathMap: async () => {
    const extraPathMaps = {
      '/en-ca': { page: '/homePage', query: { locale: 'en-CA' } },
    };
    const pathMapObject = await generatePathMaps();
    return Object.assign({}, extraPathMaps, pathMapObject[0]);
  },
};

module.exports = withPlugins(
  [
    [
      withPurgeCss,
      {
        purgeCssPaths: ['pages/**/*.js', 'components/**/*.js', 'utils/**/*.js'],
        purgeCss: {
          whitelistPatterns: () => [/^slick-/],
          extractors: [
            {
              extractor: TailwindExtractor,

              // Specify the file extensions to include when scanning for
              // class names.
              extensions: ['js'],
            },
          ],
        },
      },
    ],
    withCSS,
    withImages,
  ],
  nextConfig
);

I am expecting the .css file to be picked from index.html and inject inline critical css.

vinutha93bnvs avatar Nov 20 '18 10:11 vinutha93bnvs

Also getting this with the following config (where I'm not using either PostCSS or nextCSS):

const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
// const ExtractTextPlugin = require("extract-text-webpack-plugin");
const { GenerateSW } = require('workbox-webpack-plugin');
const HtmlCriticalWebpackPlugin = require("html-critical-webpack-plugin");

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },

    module: {
        rules: [
            // {
            //     test: /\.css$/,
            //     // use: ['style-loader', 'css-loader']
            //     use: [
            //         {
            //             loader: MiniCssExtractPlugin.loader,
            //             options: {
            //                 // you can specify a publicPath here
            //                 // by default it use publicPath in webpackOptions.output
            //                 publicPath: '../'
            //             }
            //         },
            //         "css-loader"
            //     ]
            // },
            {
                test: /\.css$/,
                use: [
                    'isomorphic-style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1
                        }
                    }
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    'style-loader',
                    "css-loader", // translates CSS into CommonJS
                    "sass-loader" // compiles Sass to CSS, using Node Sass by default
                ]
            },
            {
                test: /\.(png|svg|jpg|gif)$/i,
                loader: 'url-loader',
                options: {
                    limit: 80192
                },
            }, {
                test: /\.html$/,
                use: ['file-loader?name=[name].[ext]', 'extract-loader', 'html-loader'],
            },
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[id].css"
        }),
        new GenerateSW({
            swDest: path.resolve(__dirname, 'dist/sw.js')
        }),
        new HtmlCriticalWebpackPlugin({
            base: path.resolve(__dirname, 'dist'),
            src: 'index.html',
            dest: 'index.html',
            inline: true,
            minify: true,
            extract: true,
        })
    ],
    optimization: {
        minimizer: [
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                sourceMap: true // set to true if you want JS source maps
            }),
            new OptimizeCSSAssetsPlugin({})
        ]
    },
};

dalanmiller avatar Dec 28 '18 23:12 dalanmiller

Thanks for your code snippets @vinutha93bnvs and @dalanmiller .

In both cases, are you confirming index.html is being generated before HtmlCriticalWebpackPlugin runs? Any errors?

thescientist13 avatar Jan 01 '19 20:01 thescientist13

@thescientist13 , Yes. I have generated a sample index.html with external css file. However i dont see this working

vinutha93bnvs avatar Jan 13 '19 11:01 vinutha93bnvs

@vinutha93bnvs Are you developing a SPA (Single Page Application, eg. React, Angular) by chance? (what does your index.html look like?

thescientist13 avatar Jan 15 '19 23:01 thescientist13

yes. my main intention was SPA. But to start with, i tested with a demo index.html file generated by static site generator (Gatsby), with external css file linked, critical css did not work.

To my knowledge, external style tag detection and path is not extracted in a proper way by this plugIn.

vinutha93bnvs avatar Jan 30 '19 05:01 vinutha93bnvs

Can you please share the contents of your index.html though? My main concern is that critical needs DOM to scan in index.html to see what styles need to get extracted. So with a SPA, there usually isn't much DOM in index.html, and so not much for critical to scan.

thescientist13 avatar Feb 15 '19 01:02 thescientist13

Just to follow up, a user with a similar report found that running critical manually also produced the same results, so maybe critical itself isn't well suited to SPAs?

Can you please confirm as well? Might not be a plugin issue. https://github.com/anthonygore/html-critical-webpack-plugin/issues/39#issuecomment-499293813

thescientist13 avatar Jun 15 '19 12:06 thescientist13