critical icon indicating copy to clipboard operation
critical copied to clipboard

Multiple HTML sources

Open stn1978 opened this issue 9 years ago • 11 comments

Hey guys, is it possible to specify multiple HTML sources? Usecase: I've got the homepage and one more important entry point, a landing page. Now I need the critical CSS of both combined and inlined and all the rest in a separate file. Is there any way to do that? I read Issue #38, but I never got working what was described there. Thanks & merry christmas ;)

stn1978 avatar Dec 21 '15 13:12 stn1978

Multiple HTML sources are not supported by now. You may generate the critical css for both pages and squash the styles together with clean-css. But why don't you just inline the critical css for the homepage in the head of your homepage and the one for the landingpage in the landingpage?

bezoerb avatar Jan 18 '16 22:01 bezoerb

The method suggested by @bezoerb is best, to generate critical CSS for each file.

This is how I did it (using Gulp):

// Critical Render path CSS tasks - https://github.com/addyosmani/critical-path-css-demo#tutorial
gulp.task('copystyles', function() { // Copy our site styles to a site.css file for async loading later
    return gulp.src(['dist/styles/main.css'])
        .pipe($.rename({
            basename: 'site'
        }))
        .pipe(gulp.dest('dist/styles'));
});

// Generate & Inline Critical-path CSS
gulp.task('critical', function(cb) {
    runSequence(['default'], ['criticalhome', 'criticalblog'], cb);
});
gulp.task('criticalhome', ['copystyles'], function(cb) {
    // At this point, we have our
    // production styles in main/styles.css
    // As we're going to overwrite this with
    // our critical-path CSS let's create a copy
    // of our site-wide styles so we can async
    // load them in later. We do this with
    // 'copystyles' above
    critical.generate({
        // Inline the generated critical-path CSS
        // - true generates HTML
        // - false generates CSS
        inline: true,
        base: 'dist/',
        // HTML source file
        // src: ['index.html','blog/index.html','typography/index.html'],
        // src: 'index.html',
        src: 'index.html',
        // styleTarget: 'styles/main.css',
        // Your CSS Files (optional)
        css: ['dist/styles/main.css'],
        // htmlTarget: 'index.html',
        // Viewport width
        width: 1300,
        // Viewport height
        height: 900,
        // Target for final HTML output.
        // use some css file when the inline option is not set
        dest: 'dist/index.html',
        // Minify critical-path CSS when inlining
        minify: true,
        // Extract inlined styles from referenced stylesheets
        extract: true,
        // ignore css rules
        ignore: ['font-face']
    }, cb);
});

gulp.task('criticalblog', ['copystyles'], function(cb) {
    critical.generate({
        inline: true,
        base: 'dist/',
        src: 'blog/index.html',
        css: ['styles/main.css'],
        width: 1300,
        height: 900,
        dest: 'dist/blog/index.html',
        minify: true,
        extract: true,
        ignore: ['font-face']
    }, cb);
});

javdl avatar Jan 29 '16 08:01 javdl

Multiple HTML sources will be very useful for AngularJS with multiple views, where all critical css of every view (at least home and landing pages) should be inline in the index.html

ospar0829 avatar Feb 15 '16 22:02 ospar0829

This would also be extremely useful for CMS builds, which arguably could use these kinds of speed improvements the most. I'm trying to get this working with WordPress, and there really doesn't appear to be an elegant way to do it. I can't really generate a new CSS file for every page, because there may be new pages created, or the site may be too large to make that feasible (having hundreds of custom header.php files for a gigantic site wouldn't really work).

What I'd really like to be able to do is specify an array of "key" pages that get parsed, and a single combined critical gets output. Yes, there would be some unused code depending on the page being viewed, but this is a lot more practical than going the other route.

Until this is supported (and I know it may never be), my plan is to loop through a set of pages, generating CSS, and then cleaning it up any duplicate code and injecting it in to my header. It'll be kind of a mess, but it should work.

JacobDB avatar Feb 27 '17 20:02 JacobDB

You're right, @JacobDB. Loop through the HTML files, concatenate the generated critical CSS files, then use a plugin like nano to remove duplicate code and minify the output.

To reduce the strain of unneeded critical CSS on per page basis, I use loadCSS to sift through the code and apply critical styles as needed.

stephenasamoah avatar Jul 06 '17 02:07 stephenasamoah

@stephenasamoah I ended up creating an array of one example page per template, using that to generate a critical CSS file for each template, and including it on each page that uses the same template. Seems to be working alright for me, but I'll definitely look in to your suggestions :)

JacobDB avatar Jul 06 '17 13:07 JacobDB

+1 enhancement for managing multiple HTML sources.

geosigno avatar Aug 23 '17 07:08 geosigno

+1 for this request. I've found my own solution as explained here but doing multiple html source files at once would eliminate having to initialise lots of chromium instances and a separate call to clean-css to combine the outputs into one.

wildhart avatar Nov 07 '19 00:11 wildhart

There's a problem when generating the critical css for multiple resources. If the paths differ we will end up with different asset paths for the same resources. Imagine the following scenario:

CSS /styles/main.css

...
.used-everywhere {
   background-image: url('../images/test.jpg');
}
...

File 1: /index.html -> background-image: url('images/test.jpg'); File 2: /info/imprint.html -> background-image: url('../images/test.jpg');

So depending on which file got processed first, one of these two sites would definitely have a broken image.

bezoerb avatar Nov 08 '19 23:11 bezoerb

@bezoerb use rebase property , this will solve the image path. https://www.npmjs.com/package/critical

akshayakbm avatar Feb 02 '21 12:02 akshayakbm

For anyone who wants to loop trough all the html files and update the critical internal css. Use this: https://github.com/TheVoxSiren/voxsiren.net/blob/main/.github/workflows/optimizecss.yml#L32

it’ll loop trough all the html files and it uses a clever sed command to remove the online internal css, so that critical can add a up to date one (no duplicates)

Macleykun avatar Mar 27 '21 10:03 Macleykun