opened
lfurzewaddock
username_0
## Summary

Currently plugins can use the GatsbyJS SSR API `onRenderBody` `setPostBodyComponents` parameter which appears to be implemented here: [gatsby/packages/gatsby/cache-dir/static-entry.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/static-entry.js) to inject scripts below the main html content inside the body tag.

However, at run time `gatsby-script-loader` and `gatsby-chunk-mapping` are placed below anything injected using `setPostBodyComponents` and therefore blocked.
    
### Feature Request

Create a new GatsbyJS SSR API `onRenderBody` parameter called something like `setPostBodyBlockingScripts` or `setPostBodyLastComponents` based upon`setPostBodyComponents`, but is injected last before the closing body tag below `gatsby-script-loader` and `gatsby-chunk-mapping`.

### Motivation

Enable plugins to support 3rd party synchronous/blocking scripts including those that use `document.write`
Ability for plugins to inject 3rd party blocking scripts last on page before closing body tag
issue
created
pieh
username_1
You can use [`onPreRenderHTML`](https://www.gatsbyjs.org/docs/ssr-apis/#onPreRenderHTML) SSR api to manipulate final order of components.

It's called just before constructing final html - so you can move any blocking scripts after `gatsby-script-loader` and `gatsby-chunk-mapping` there using `getPostBodyComponents`, re-ordering and `replacePostBodyComponents` to set final array
https://github.com/gatsbyjs/gatsby/blob/bbd2a46e88de6ee6fe4da71978a3b2940bc31374/packages/gatsby/cache-dir/static-entry.js#L362-L382
comment
created
lfurzewaddock
username_0
Thanks @username_1, I'll attempt to implement your answer and let you know.
comment
created
KyleAMathews
username_2
Maybe we could also just ensure the gatsby script tags go first? Would that solve the issue?
comment
created
lfurzewaddock
username_0
Thanks @username_1, I got that working in production now. 

I did have trouble though using `$ gatsby develop` as `getPostBodyComponents` only returned plugin components, not 'gatsby-script-loader', 'gatsby-chunk-mapping', etc. so I needed to use `$ gatsby build` for development instead.

Question: When using `$ gatsby serve` for the production code locally, I'm still seeing a blocking affect?
The site loads in the browser, but JavaScript does not fire, while waiting for the 3rd party server hosting the script referenced in the tag, now placed directly before the closing body tag. I had believed that if a blocking script was last after all other scripts on the page, the other scripts should run or is this just related to how `$ gatsby serve` works, so I should just code the plugin to only run in production?

Hi @username_2, yes if the Gatsby script tags were placed before the plugin scripts this would have made it easier, but by using `onPreRenderHTML` I've learned that I'm able to rearrange components/scripts provided other plugins and Gatsby core too, which is very usefull.
comment
created
neoswf
username_3
If I might say @username_2, I think that this is the desired result. I don't see why 3'd party scripts needs to come before the gatsby script tags.
Thank you.
comment