npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@vyvrhel/critical-css-import-webpack-plugin

v1.0.0

Published

Webpack plugin that creates critical CSS from flagged imports in Sass/Less file.

Downloads

15

Readme

Critical CSS Import Webpack Plugin

Webpack plugin that simplifies manual maintaining of critical CSS(s). Plugin gets critical @imports from given Sass/Less file and adds them as a separate entry. Critical @imports are flagged by special comment.

Install / Usage / Options / Use case / Notes

Install

npm install @vyvrhel/critical-css-import-webpack-plugin --save-dev

Usage

Register plugin in webpack configuration with proper options (set source file and one critical id at least):

webpack.config.js

const CriticalCssImportPlugin = require('@vyvrhel/critical-css-import-webpack-plugin');

module.exports = {
  // ..
  plugins: [
    // ...
    new CriticalCssImportPlugin ({
      source: 'main.scss',
      criticals: [ 'home', 'blog', 'article' ], // list of critical ids
    }),
  ],
};

Flag critical @imports by adding special comment with critical CSS ids:

main.scss

@import 'tools/mixins'; // critical: all
@import 'components/molecules/articles'; // critical: blog, article
@import 'components/organisms/header'; // critical: all
@import 'components/organisms/footer';
@import 'components/pages/home'; // critical: home
@import 'components/pages/blog'; // critical: blog
// ...

Comment syntax

"critical: " ( critical-id ( "," critical-id)* ) | "all"

  • Notation critical: followed by comma-separated list of critical ids.
  • For including @import in all critical CSS use keyword all instead of critical id.
  • Comment format can be change by pattern option.

Result

Now, depending on your webpack workflow, application should output files like home.critical.css, blog.critical.css and article.critical.css.

In other words, plugin simulates source files with flagged @imports and adds them as separate entries. In the words of webpack config, plugin basically does the following on background:

module.exports = {
  // ...
  entry: {
    // ...
    'home.critical': /* main.scss only with imports flagged as 'home' or 'all' */,
    'blog.critical': /* main.scss only with imports flagged as 'blog or 'all' */,
    'article.critical': /* main.scss only with imports flagged as 'article or 'all' */,
  }
  // ...
};

Entry names for each critical id can be changed by criticals options.

Options

source

Type: {String} Required

Path to source Less/Sass file.

criticals

Type: {Array|Object|String} Required

Array of critical CSS objects:

[
  {
    id: 'critical-name-1',
    entry: 'critical-name-1.critical'
  },
  {
    id: 'critical-name-2',
    entry: 'critical-name-2.critical'
  },
]
  • id
    Type: {String} Required
    The unique identifier for a critical CSS (used in CSS comment).

  • entry
    Type: {String} Default: [id].critical
    Webpack entry name.

Possible shortcuts:

// string (one critical CSS with default entry name)
'critical-name'

// array of strings (more critical CSSs with default entry name)
[ 'critical-name-1', 'critical-name-2' ]

// object (one critical CSS)
{ id: 'critical-name' } // with default entry name
{ id: 'critical-name', entry : 'entry-name' }

deleteJsOutput

Type: {Boolean} Default: true

If enabled then .js output file that is generated together with .css file by webpack will be deleted.

pattern

Type: {Function} Default:

(criticalId) => new RegExp(`critical: ([a-zA-Z0-9\_\-]*, )*(all|${criticalId})(,|;|$)`, 'g')

Function returning regular expression used to filter out @imports from source file.

Use Case

Without plugin

We have one main Sass/Less file with many imports:

main.scss

// common styles for whole project
@import 'settings/colors';
@import 'tools/mixins';
@import 'components/molecule/articles';
@import 'components/organism/header';
@import 'components/organism/footer';
@import 'components/page/home';
@import 'components/page/blog';
// ...

We also have partially duplicated file(s) that imports only critical styles:

home.critical.scss

// critical styles for homepage
@import 'tools/mixins';
@import 'components/organism/header';
@import 'components/page/home';
// ...

blog.critical.scss

// critical styles for blog page
@import 'tools/mixins';
@import 'components/molecule/articles';
@import 'components/organism/header';
@import 'components/page/blog';
// ...

article.critical.scss

// critical styles for article page
@import 'tools/mixins';
@import 'components/molecule/articles';
@import 'components/organism/header';
// ...

All processed by webpack:

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: './main.scss',
  module: {
    rules: [
      {
        test: /\.scss$/i,
        use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin(),
  ],
};

With plugin

Maintaining these multiple files can be annoying, therefore plugin allows us to handle critical styles directly within main file:

main.scss

// common styles for whole project
@import 'tools/mixins'; // critical: all
@import 'components/molecule/articles'; // critical: blog, article
@import 'components/organism/header'; // critical: all
@import 'components/organism/footer';
@import 'components/page/home'; // critical: home
@import 'components/page/blog'; // critical: blog
// ...

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CriticalCssImportPlugin = require('@vyvrhel/critical-css-import-webpack-plugin');

module.exports = {
  entry: './main.scss',
  module: {
    rules: [
      {
        test: /\.scss$/i,
        use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin(),
    new CriticalCssImportPlugin ({
      source: './main.scss',
      criticals: [ 'home', 'blog', 'article' ],
    }),
  ],
};

Now, with correctly configured plugin, files home.critical.scss, blog.critical.scss and article.critical.scss are automaticaly simulated by webpack.

Notes

Further optimization of generated critical CSS is recommended (e.g. by removing background-urls).