Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: preProcess and postProcess functionality #170

Closed
wants to merge 1 commit into from

Conversation

prasannavl
Copy link

Currently, with most options, it's either take what react-snap does, or you get nothing. For instance, removeScripts remove every single script. removeStyles removes every single style. There's no way to customise this in anyway. Similarly, I've also needed a defer scripts functionality before (PR: #169) but it didn't quite fit in nicely.

This solves all these problem by being able to any custom functionality to modify the output as desired by directly using chrome's puppeteer. This also helps moving all features as plugins and helps to easily experiment and add/remove features to react-snap.

Currently, with most options, it's either take what react-snap does, or you get nothing. For instance, `removeScripts` remove every single script. `removeStyles` removes every single style. There's no way to customise this in anyway. Similarly, I've also needed a `defer` scripts functionality before (PR: stereobooster#169) but it didn't quite fit in nicely. 

This solves all these problem by being able to any custom functionality to modify the output as desired by directly using chrome's  `puppeteer`. This also helps moving all features as plugins and helps to easily experiment and add/remove features to react-snap.
@prasannavl
Copy link
Author

prasannavl commented May 4, 2018

Example usage:

// snap.js

const url = require("url");
const { run } = require("react-snap");
const fs = require("fs-extra");
const path = require("path");

async function snap() {
    process.chdir(path.resolve(path.join(__dirname, "./../")));
    run({
        publicPath: "/",
        preProcess: (snappy) => {
            return removeScriptTagsWithSrcAttribute(snappy)
        },
    });
}

async function runAsync() {
    await snap();
    // workaround react-snap bug where the promise actually
    // gets resolved before it truly completes.
    process.once("beforeExit", () => {
        fs.unlink("./build/200.html");
        fs.unlink("./build/404.html");
    });
}

const deferScriptTags = ({ page }) => {
    return page.evaluate(() => {
        Array.from(document.querySelectorAll("script[src]")).forEach(x => {
            x.removeAttribute("async");
            x.setAttribute("defer", "true");
        });
    });
};

// This removes *only* the script tags with an `src` attribute - so that it's
// still possible to add some script in the file like Google Analytics, etc
// using direct `script` without the src attribute. 
const removeScriptTagsWithSrcAttribute = ({ page }) => {
    return page.evaluate(() => {
        Array.from(document.querySelectorAll("script")).filter(node => node.src).forEach(ell => {
            ell.parentElement && ell.parentElement.removeChild(ell);
        });
    });
};

runAsync();

PS: This also highlights a bug in react-snap where the promises are resolved before it's actually complete. Should file an issue. But for the lack of time, just using this opportunity to just throw it in at the moment :)

The above is a part of my website source. Here's the full source code if it's useful to someone: https://github.com/prasannavl/prasannavl.com/blob/master/tools/snap.js

@stereobooster
Copy link
Owner

At the moment I'm trying to write proper tests for the package. It was without tests way too long. This means, that all other PRs will be on hold. See #171

@prasannavl
Copy link
Author

Any update on this?

@stereobooster
Copy link
Owner

It is easy to introduce new functionality, but it will be hard to maintain it. You know you can install it from github url, right?

@prasannavl
Copy link
Author

@stereobooster - Hmm. I'd assume that being able to do this removes a lot of maintenance overhead, since it'd provide a pretty neat plugin hook. Anyway, whichever works for you!

I'm maintaining a fork of this with these two additions, that I rely pretty heavily on -- as different projects have different needs, and this hook provides me with the ability to change things at will without having to touch react-snap directly. So, was hoping to see what your thoughts were on this. Cheers!

@zheeeng
Copy link

zheeeng commented Jul 21, 2019

@stereobooster I have a question that how to cleanup dynamically inserted scripts? e.g. Google Analytics script is inserted by calling document.createEelement('script') and document.body.appendChild(script), the script is will be inserted in prerendering process and visiting time. I have the only solution is to comment the inserting script prevent prerendering generate these inserted scripts and remove the HTML comment by postProcess hook

@prasannavl prasannavl closed this Aug 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants