piuccio / prerender-chrome-headless

Pre-render single page applications to static HTML file
MIT License
33 stars 3 forks source link

adding inline stylesheet and javascript? #10

Open dark-kitt opened 5 years ago

dark-kitt commented 5 years ago

Hey,

first of all, great work! Everything works like expected. What do you think about adding this lines to your plugin? To inline the Stylesheets and the JavaScript files.

first

const urlModule = require('url');
const URL = urlModule.URL;

underneath const delayPageLoad, const puppeteerOptions etc...

const stylesheetContents = {};
const javascriptContents = {};

the first part of your chain() function behind (page) => page.on('pageerror', ...

`stash stylesheet and javascript`,
(page) => page.on('response', async resp => {
        const responseUrl = resp.url();
        const sameOrigin = new URL(responseUrl).origin === new URL(source).origin;
        const isStylesheet = resp.request().resourceType() === 'stylesheet';
        const isJavaScript = resp.request().resourceType() === 'script';
        if (sameOrigin && isStylesheet) {
            stylesheetContents[responseUrl] = await resp.text();
        }
        if (sameOrigin && isJavaScript) {
            javascriptContents[responseUrl] = await resp.text();
        }
    }),

the second part in .then(([browser, page]) => chain(... behind () => page.waitFor(delayPageLoad),...

`inline stylesheet`,
() => page.$$eval('link[rel="stylesheet"]', (links, content) => {
        links.forEach(link => {
            const ctx = content[link.href];
            if (ctx) {
                const style = document.createElement('style');
                style.textContent = ctx;
                link.replaceWith(style);
            }
        });
    }, stylesheetContents),

`inline javascript`,
() => page.$$eval('script[type="text/javascript"]', (links, content) => {
        links.forEach(link => {
            const ctx = content[link.src];
            if (ctx) {
                const script = document.createElement('script');
                script.textContent = ctx;
                link.replaceWith(script);
            }
        });
    }, javascriptContents),

Let me know about your thoughts :)

cheers

piuccio commented 5 years ago

Do I understand correctly that this will inline external stylesheets and script files? Tings like <link href="somefile.css" /> will be converted <style>file content</style>

I kind of like the idea but I don't have time to implement it, how about you go on and create a PR?

To simplify merging your pull request, I suggest:

  1. limit the scope for now to stylesheets
  2. add an option to enable this new behaviour, next to delayPageLoad you can add inlineStyles: true / false, default to false so things don't change for other users
  3. describe the new feature in the README
  4. if possible write some tests
  5. implement the code from above

I'll be able to review your code, if you work on the styles alone it should be faster for both of us, once that's merged it should be easier to do the scripts.

(PS. I think styles should be relatively easy because there are fewer things that can go wrong, when it comes to scripts we should take into account that <script async <script defer and <script module might have slightly different requirements)