penthouse

repository·master·Indexed 25 days ago

https://github.com/pocketjoso/penthouse

A critical path CSS generator (version 2.3.3) that uses Puppeteer and a headless Chromium instance to extract the minimal CSS required to render the above-the-fold content of a webpage. It allows for viewport customization via width and height, selector-based inclusion or exclusion, and the ability to block JavaScript requests to optimize page rendering speed.

Tokens
2K
Snippets
4
Records
13
Agent score
82%

What's inside penthouse

  1. Configure penthouse options

    master

    Penthouse accepts an options object to customize the extraction process.

    NameTypeDefaultDescription
    urlstringAccessible url. Use file:/// protocol for local html files.
    cssStringstringOriginal css to extract critical css from
    cssstringPath to original css file on disk (if using instead of cssString)
    widthinteger1300Width for critical viewport
    heightinteger900Height for critical viewport
    screenshotsobjectConfiguration for screenshots (not used by default).
    keepLargerMediaQueriesbooleanfalseKeep media queries even for width/height values larger than critical viewport.
    forceIncludearray[]Array of css selectors to keep in critical css, even if not appearing in critical viewport. Strings or regex (e.f. ['.keepMeEvenIfNotSeenInDom', /^\.button/])
    forceExcludearray[]Array of css selectors to remove in critical css, even if appearing in critical viewport. Strings or regex (e.f. ['.doNotKeepMeEvenIfNotSeenInDom', /^\.button/])
    propertiesToRemovearray['(.*)transition(.*)', 'cursor', 'pointer-events', '(-webkit-)?tap-highlight-color', '(.*)user-select']Css properties to filter out from critical css
    timeoutinteger30000Ms; abort critical CSS generation after this time
    puppeteerobjectSettings for puppeteer.
    pageLoadSkipTimeoutinteger0Ms; stop waiting for page load after this time
    renderWaitTimeinteger100ms; wait time after page load before critical css extraction starts
    blockJSRequestsbooleantrueset to false to load JS (not recommended)
    maxEmbeddedBase64Lengthinteger1000characters; strip out inline base64 encoded resources larger than this
    maxElementsToCheckPerSelectorintegerundefinedLimit nr of elements to inspect per css selector to reduce execution time.
    userAgentstring'Penthouse Critical Path CSS Generator'specify which user agent string when loading the page
    customPageHeadersobjectSet extra http headers to be sent with the request for the url.
    cookiesarray[]For formatting of each cookie, see Puppeteer setCookie docs
    strictbooleanfalseMake Penthouse throw on errors parsing the original CSS. (Legacy, not recommended)
    allowedResponseCodenumber|regex|functionLet Penthouse stop if the server response code is not matching this value.
  2. Troubleshoot unstyled content flashes

    master

    If you see flashes of unstyled content (FOUC) when using critical CSS, check the following:

    1. Dynamic/JS Content: Penthouse runs with JavaScript disabled. Ensure all elements you want styled appear in the initial HTML. If content is injected via JS, use the forceInclude option to keep those styles in the critical CSS.
    2. DOM Position vs Viewport: Penthouse does not account for absolute positioning or transform values when determining if an element is in the viewport. If an element is early in the DOM but moved into the viewport via CSS, Penthouse might exclude its styles. Use forceInclude to prevent this.
  3. Fixing 'Not working on Linux' issues

    master

    If you are running on Linux and encounter issues with headless Chrome, you may need to install missing dependencies. A common requirement is libnss3.

    sudo apt-get install libnss3
    sudo apt-get install libnss3
  4. Fix special glyph display issues in CSS

    master

    If special characters (like arrows) are not showing correctly, ensure you are using the correct hexadecimal format in your CSS, prepended with a backslash.

    Example for the arrow glyph :

    1. Find the hex code: '→'.charCodeAt(0).toString(16) (returns 2192).
    2. Use in CSS: content: '\2192';
  5. Enable debug logging for penthouse

    master

    Penthouse uses the debug module. You can enable verbose logging for all components by setting the DEBUG environment variable.

    # Basic verbose logging for all components
    env DEBUG="penthouse,penthouse:*" node script.js
    # Basic verbose logging for all components
    env DEBUG="penthouse,penthouse:*" node script.js
  6. Generate critical path CSS with penthouse()

    master

    Penthouse extracts the critical CSS needed to render the above-the-fold content of a page. It uses Puppeteer and a headless Chromium instance.

    Only url and cssString (or css) are required. Note that the HTML found via the url is expected to be styled; Penthouse does not inject styles, it only prunes the provided CSS.

    To run many jobs effectively, reuse a single browser instance and run each job in its own browser tab to optimize performance.

    penthouse({
      url: 'http://google.com',
      cssString: 'body { color: red }'
    })
    .then(criticalCss => {
      // use the critical css
      fs.writeFileSync('outfile.css', criticalCss);
    })
  7. Configure browser environment and request interception

    master

    Penthouse allows fine-grained control over the Puppeteer browser instance used for CSS pruning. Key configuration capabilities include:

    • userAgent: Set a custom User-Agent string.
    • cookies: Pass an array of cookie objects to be set in the browser.
    • customPageHeaders: Set extra HTTP headers for the page requests.
    • blockJSRequests: If set to true, Penthouse will disable JavaScript and intercept/abort all .js requests to speed up the process and reduce noise.
    • width & height: Define the viewport dimensions used to determine critical CSS.
  8. Handle PAGE_UNLOADED_DURING_EXECUTION error

    master

    If you encounter the error PAGE_UNLOADED_DURING_EXECUTION: Critical css generation script could not be executed., it typically means the page navigated away (via window.location, a meta tag refresh, or a redirect) after loading but before Penthouse could finish.

    To resolve this:

    • Remove redirects or move them to the server-side.
    • Disable redirects for the critical CSS generation process (e.g., by using a specific query parameter).
  9. Capture screenshots during critical CSS generation

    master

    You can capture screenshots to visually verify the critical CSS application. Provide a screenshots object with a basePath to enable this. Penthouse will take two screenshots:

    1. before: A screenshot of the page with original styles.
    2. after: A screenshot of the page after the generated critical CSS has been inlined.

    The file extension is determined by the screenshots.type (e.g., jpeg results in .jpg, otherwise .png).

  10. Generate critical CSS with penthouse

    master

    The main export of penthouse is an asynchronous function used to generate critical-path CSS for a given URL. It accepts an options object and can be used with a callback or as a Promise.

    Key features include:

    • Support for providing CSS via a string (cssString) or a file path (css).
    • Viewport configuration via width and height.
    • Custom Puppeteer browser control via puppeteer.getBrowser.
    • Control over request blocking (blockJSRequests).
    • Inclusion/Exclusion of specific selectors (forceInclude, forceExclude).
    • Post-formatting to remove specific CSS properties (propertiesToRemove).
  11. Validate server response status with allowedResponseCode

    master

    When configuring Penthouse, you can use the allowedResponseCode option to ensure the page loads with the expected HTTP status. This option supports three types of validation:

    • Number: The response status must exactly match this number (e.g., 200).
    • RegExp: The response status string must match the regular expression.
    • Function: A custom predicate function that receives the response object and returns a boolean.