crittr

    1.3.0 • Public • Published

    crittr

    CI Build Status GitHub release npm Github Releases

    NPM

    High performance critical css extraction library with a multiple url support. crittr enables you to extract the critical path stylesheet rules of a single or multiple urls with lightning speed. Multiple urls are the unique selling point of this library due to the fact that nearly every website using one css file for multiple sub pages. Now you are able to gather the critical css of all pages in one extracting process. And this blazing fast even with rich internet applications! 💪

    Feature Facts

    • Amazing speed
    • Designed to be used by power users as a nodejs module (no useless browser usage)
    • 💥 Only library which is able to extract summarized critical css from multiple urls which has a common use case -> Most of the websites using one css file for multiple subpages 💥 🤘
    • When using multiple urls a max concurrency of extraction is adjustable. For machines with less power
    • Ongoing maintenance because of being used in enterprise environment
    • Returns not only the critical css. Also returns the remaining css of your given file. You don't need to include the full css on your page or reduce the css on your own ❤️

    Performance

    If you use many urls to check against a single css file it will slow down the process. Anyway this is the scenario where crittr can shine. The only thing you need to take care of is the power of the machine you're running crittr on.

    Comparison

    There are some other libraries out there dealing with the topic of extracting the critical css. Crittr has it's own approach of dealing with this topic. Many features allow users to forget about using any other libraries because crittr already deal with the most things which are important for extracting critical css.

    Comparison

    Getting Started

    Requirements

    • minimum nodejs > 7.6 | recommended nodejs 8+
      • async/await
      • Promises
    • puppeteer dependecies on UNIX bases OS (including MacOSX)

    Due to some dependencies of crittr you may need to install some additional software. Puppeteer has some special requirements if you are running on an UNIX based operation system. You can read more about this fact here. Including a list of what to install: Puppeteer Troubleshooting

    Installation

    To use crittr as a module or cli in your nodejs environment just install it with

    npm i crittr
    

    Usage

    Modul usage

    To use crittr as a module just require it and choose your options.

    The crittr module has the expects an object as input parameter and returns an array with 2 css strings. The first one is the criticalCss string and the second one is the remaining css without the critical selectors.

    // async/await
    (async () => {
      const { critical, rest } = await crittr(options);
    })();
    
    // Promise
    crittr(options).then(({ critical, rest }) => {
      // handle css
    });
    Basic
    const Crittr = require("crittr");
    
    Crittr({
      urls: ["https://github.com/"],
      css: `.header-logo-invertocat {
                margin: -1px 15px -1px -2px;
                color: #fff;
                white-space: nowrap;
            }`,
      device: {
        width: 1920,
        height: 1080,
      },
    })
      .then(({ critical, rest }) => {
        console.log(critical);
      })
      .catch((err) => {
        console.error(err);
      });

    As you can also read in the options section there is the possibility to use a css file as a path instead of a string. If the path provided ends with .css it is treated as a file path.

    const Crittr = require("crittr");
    
    Crittr({
      urls: ["https://github.com/"],
      css: "./test/data/test.css",
    }).then(({ critical, rest }) => {
      console.log(critical);
    });

    Due to the fact, that crittr is returning a Promise you can also use async/await syntax to handle the result.

    (async () => {
      const Crittr = require("crittr");
      try {
        const { critical, rest } = await Crittr({
          urls: ["https://github.com/"],
          css: "./test/data/test.css",
        });
      } catch (err) {
        console.error(err);
      }
    })();
    Advanced - Multiple urls

    To use the full power of crittr and get the most of the performance advantage you should pass in multiple urls. As of the fact that the most websites use one css file for multiple pages this is the ultimate way to get the critical css for all of them!

    const Crittr = require("crittr");
    
    const urls = [
      "https://example.com/page1",
      "https://example.com/page2",
      "https://example.com/about",
      "https://example.com/shop",
    ];
    
    Crittr({
      urls: urls,
      css: "./example.com/css/main.css",
    }).then(({ critical, rest }) => {
      // criticalCss contains all the above the fold css
      // restCss is the rest remaining after excluding the criticalCss.
      // You can start including it directly as a defered css without
      // any need to calculate it on your own
      console.log(critical);
    });

    You can see the output of the time measurement after every run. So you will be able to check you overall processing time.

    ▶  Crittr Run Initialized timer...
    ◼  Crittr Run Timer run for: 2.33s
    

    CLI Usage

    The CLI usage is not implemented yet 😱. At the moment there is no need of cli usage, but if you need it just open an issue and I will try to get it done! ❤️

    Options

    Property Values Description
    css string Can be a plain css string or path to a css file. If it is a path it has to end with .css! Otherwise it is not recognized as a path.
    urls Array An array containing the urls to check the css against. Has to be at least 1 url.
    timeout Number Optional. Integer number of milliseconds to wait for a page to navigate to. After timeout is reached the page navigation is aborted. ATTENTION: The critical css of the url timed out is not included. Default: 30000
    pageLoadTimeout Number Optional. After the page load event is fired the pageLoadTimeout is started. After the amount of milliseconds the ongoing loading of assets or xhr requests is stopped and the extraction continues. Default: 2000
    outputRemainingCss Boolean Optional. If set to false the result obj will not contain any rest css. Only an empty string will be given. Default: true
    browser Object Optional. Configuration object of browser. E.g. userAgent, ... See documentation for browser object.
    device Object Optional. Configuration object of device. E.g. width, height, ... See documentation for device object.
    puppeteer Object Optional. Configuration object of puppeteer options like an already existing browser instance or a path to a Chrome instead of the used Chromium. See documentation for puppeteer object.
    printBrowserConsole Boolean Optional. If set to true prints console output of urls to the stdoutput. Defaults: false
    dropKeyframes Boolean Optional. If set to false keeps keyframes as critical css content. Otherwise they are removed. Default: false
    takeScreenshots Boolean Optional. If set a screenshot is taken for every url processed. Default: false
    screenshotPath String Optional. The path the screenshots will be saved to. Default: "." (execution path)
    keepSelectors Array Optional. Every CSS Selector in this array will be kept as part of the critical css even if they are not part of it. You can use wildcards (%) to capture more rules with one entry. Read more. Default: []
    removeSelectors: Array Optional. Every CSS Selector in this array will be removed of the critical css even if they are part of it. You can use wildcards (%) to capture more rules with one entry. Read more. Default: []
    blockRequests Array Optional. Some of the requests made by pages are an

    Browser options

    Property Values Description
    userAgent String Optional. Can be set to any existing user agent
    isCacheEnabled Boolean Optional. If set to false the browser will cache the result assets as normal behaviour. Default: true
    isJsEnabled: Boolean Optional. If set to false the execution of Javascript in the browser page is prevented. Default: true
    concurrentTabs Number Optional. Sets the maximal allowed concurrent tabs being opened at the same time in the browser. This is a useful option if the system has only low performance and to prevent high load. Default: 10 (Can also be set to "Infinity")

    Device options

    Property Values Description
    width Number Optional. Browser window width in px. Default: 1200
    height Number Optional. Browser window height in px. Default: 1080
    scaleFactor: Number Optional. Scaling factor of page. Only needed for mobile device emulation like iPhone. Default: 1
    isMobile Boolean Optional. If set to true the device type for checking pages is set to mobile. Default: false
    isLandscape Boolean Optional. If set to true the device orientation is set to landscape. Default: false
    hasTouch Boolean Optional. If set to true the device viewing the page is assumed having touch. Default: false

    Puppeteer options

    Property Values Description
    browser Promise Optional. If you already have an puppeteer browser instance created you can use it with this options to prevent crittr from creating a new one. Just for performance!. Default: null
    chromePath String Optional. Path to other Chrome or Chromium executable/bin file to use. . Default: Default Chromium shipped with puppeteer
    headless: Boolean Optional. If set to false the browser will launch with GUI to be visible while processing. Default: true

    Wildcards

    You are already able to define the selectors to force keep or remove. With wildcards you can define a range of selectors to match against one entry in force selectors. The wildcard symbol is the % character. It can put at the beginning or end of a string. Take care of whitespaces between the selector string and the % as it will count as a character. Let's have a quick example:

    const { critical, rest } = await Crittr({
      urls: urls,
      css: css,
      keepSelectors: [".test %"],
    });

    This keepSelectors options will match every selector that begins with .test and has no further selectors attached. Means .test.test2wouldn't match because there is a whitespace in there. But it will match .test .test2 .test3. Also this example wouldn't match selectors like this:

    .pre .test .test2 {
    } /* no match */
    .pre.test .test2 {
    } /* no match */
    .test .test2 {
    } /* match */
    .test.test2 {
    } /* no match */
    .test .test2:before {
    } /* match */

    FAQ 😕

    • Why do I need to put my css file in when I only want to extract the critical css? You don't need to but if you don't set your css file as an option you may not receive all vendor prefixes you may expect. This is due testing with only one browser engine which drop other prefixes.
    • After including the remaining css aswell my page starts looking different. Why is that? If you progress more than 1 url at the same time crittr can not determinate where a rule has to be positioned in the whole css to not get in conflict with other rules overwriting them. You have to write clean css to prevent such an behaviour. Overwriting rules should always have longer selectors than the rules they are overwriting to raise priority.

    Upcoming 🎺

    • [ ] cookie includes
    • [x] wildcards
    • [x] 👍 compress output option
    • [x] 🔥 return of the remaining css aswell
    • [x] multi selector partial matches
    • [x] 🍵 returning of remaining css aswell (optional)
    • [x] 🕑 performance boost for large css

    Known Bugs 💩

    None yet

    Troubleshooting

    WSL / Windows Linux Subsystem Support

    Some unkown reasons prevent puppeteer to run properly in a WSL environment. If you have any errors please try to use your default OS command shell or equivalent. If the error still exists don't hesitate to create an issue ticket.

    Inspiration

    puppeteer penthouse critical criticalCSS

    Install

    npm i crittr

    DownloadsWeekly Downloads

    82

    Version

    1.3.0

    License

    GPL-3.0

    Unpacked Size

    215 kB

    Total Files

    28

    Last publish

    Collaborators

    • hummal