stereobooster / react-snap Goto Github PK
View Code? Open in Web Editor NEW๐ป Zero-configuration framework-agnostic static prerendering for SPAs
License: MIT License
๐ป Zero-configuration framework-agnostic static prerendering for SPAs
License: MIT License
Hi there.
I'm having a create-react-app with material-ui, and their components are inlining their css already. I've noticed that the property "display: flex" has been removed in the built version that runs with react-snap right now.
Is this an expected behavior?
// TODO: this doesn't work
var wrap = document.createElement('div');
wrap.appendChild(link.cloneNode(false));
var noscriptTag = document.createElement('noscript');
noscriptTag.innerHTML = wrap.innerHTML;
document.head.appendChild(noscriptTag);
like :
inlineCss: true
Where can I put it?
As of now react-snap can "precache" ajax requests, but we actually can save state of redux. The same way as in geelen/react-snapshot#46
On adding the option inlineCss: true
the important styles are extracted, but the main style accessed by link still has a property rel="stylesheet"
while it should be rel="preload"
This is actually bug of react-mapbox-gl (alex3165/react-mapbox-gl#249)
lua
script for nginx
, which will read http2-push-manifest.json
and send appropriate headers.ruby
script for h2o
, which will read http2-push-manifest.json
and send appropriate headers.continuation of #3
Need to have demo server. Maybe Heroku or similar:
Heroku doesn't support HTTP2 so ยฏ\_(ใ)_/ยฏ
It should clean up all resource (e.g. close browser and server) instead of failing if user interrupts execution with Ctrl + C
Pre-renders web app into static HTML.
, but nothing changed in build/200.html
, build/400.html
or build/index.html
. Just minified. Why... But I can build successfully. HELP!!!
Example:
๐ฅ /shell.html pageerror: Error: DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('[object Object]') is not a valid name.
at createElement (../node_modules/preact/dist/preact.esm.js:183:0)
at createNode (../node_modules/preact/dist/preact.esm.js:364:0)
at idiff (../node_modules/preact/dist/preact.esm.js:306:0)
at diff (../node_modules/preact/dist/preact.esm.js:949:0)
at vnode (../node_modules/preact-compat/dist/preact-compat.es.js:149:0)
at __WEBPACK_IMPORTED_MODULE_0_react__ (index.js:30:7)
at call (../webpack/bootstrap 3d46b713f8f74ea5ecff:49:0)
at __webpack_require__ (../static/js/main.6fe07f11.js:3020:17)
at call (../webpack/bootstrap 3d46b713f8f74ea5ecff:49:0)
at http://localhost:45678/static/js/main.6fe07f11.js:1:1387
(node:17059) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('[object Object]') is not a valid name.
at p (http://localhost:45678/static/js/main.6fe07f11.js:1:54860)
at g (http://localhost:45678/static/js/main.6fe07f11.js:1:56858)
at b (http://localhost:45678/static/js/main.6fe07f11.js:1:56327)
at L (http://localhost:45678/static/js/main.6fe07f11.js:1:61366)
at a (http://localhost:45678/static/js/main.6fe07f11.js:1:2078)
at Object.<anonymous> (http://localhost:45678/static/js/main.6fe07f11.js:1:50384)
at e (http://localhost:45678/static/js/main.6fe07f11.js:1:101)
at Object.<anonymous> (http://localhost:45678/static/js/main.6fe07f11.js:1:39516)
at e (http://localhost:45678/static/js/main.6fe07f11.js:1:101)
at http://localhost:45678/static/js/main.6fe07f11.js:1:1387
(node:17059) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
๐ธ (1/1) /shell.html
error Command failed with exit code 1.
๐ฅ /shell.html...
- this is page error handled by react-snap
(node:17059) UnhandledPromiseRejectionWarning:..
this is the same error unhandled from minimalcss
Extracted from #36
path/index.html
vs path.html
From the ticket #22. I do not see any sense to generate path.html
for /path
route instead of path/index.html
. This convention was copied from react-snapshot.
After the change react-snap
will generate path/index.html
for both: /path
and /path/
As of now, this config does two things:
window.snapStore[<path>]
<link rel="preload" as="image">
)Need to fix two things:
window.snapStore
to window.SERVER_DATA
as in c-r-a instruction https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#injecting-data-from-the-server-into-the-pageThere is a hack to make webpack code splitting work. Because we assume usage with c-r-a it should be enabled by default. But before enabling it by default need to fix it - use <link rel="preload"
instead of script tags
As of now react-snap by default generates 404 page, which I consider a good practice, but it actually doesn't make sense to generate 404 if you do not use routing (like react-route or similar), I mean if you have only one page.
So I consider changing this behavior and generate 404 page if there is more than one page discovered by the crawler or listed in include.
Another thing that I was wondering is how to detect that 404.html
is actually a "not found page". How to make sure programmer didn't forget to handle this case?
The only option I came up is: check if the title of the page contains the string "404". It can be in any position. Also, the nice benefit is that it will possible to track that no other page is "404".
Check if target directory contains 200.html
, and if it does fail with an error message and non-zero exit code.
Also, exit with non-zero exit code if any error occurred during generation and stop generation. As of now react-snap reports error in console, but continues to generate pages.
Hi, i always get this error, no matter how i change html or the homepage
field in the package.json. Thank you in advance for your help
๐ฅ / pageerror: Error: SyntaxError: Unexpected token < at Page._handleException (/Users/Chevalier/projects/lola-client-landing-react/node_modules/puppeteer/lib/Page.js:295:38) at Session.Page.client.on.exception (/Users/Chevalier/projects/lola-client-landing-react/node_modules/puppeteer/lib/Page.js:86:60) at emitOne (events.js:115:13) at Session.emit (events.js:210:7) at Session._onMessage (/Users/Chevalier/projects/lola-client-landing-react/node_modules/puppeteer/lib/Connection.js:199:12) at Connection._onMessage (/Users/Chevalier/projects/lola-client-landing-react/node_modules/puppeteer/lib/Connection.js:98:19) at emitOne (events.js:115:13) at WebSocket.emit (events.js:210:7) at Receiver._receiver.onmessage (/Users/Chevalier/projects/lola-client-landing-react/node_modules/ws/lib/WebSocket.js:143:47) at Receiver.dataMessage (/Users/Chevalier/projects/lola-client-landing-react/node_modules/ws/lib/Receiver.js:389:14) ๐ธ (1/1) /
index.html
It looks like react-snap it pre-rendering everything but the root page. Can we opt-in to pre-render it?
When deploying I am getting this error, which actually seems to freeze the build process on Heroku:
(node:629) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/tmp/build_2e66391b352738bb3c9a1b44c5632458/jesshmusic-living_music_database-ca09d15273a13f10f1a1a9e7ffd147503a55dc26/node_modules/react-snap/node_modules/puppeteer/.local-chromium/linux-499413/chrome-linux/chrome: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md
(node:629) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I have attempted to add the puppeteer
build pack as described in the troubleshooting link above but it doesn't do any good. Does anyone have a solution to get this to deploy in Heroku? If it is something I missed in the docs kindly point me in that direction.
Possible alternatives
If you use project and especially experimental features, like inlineCss
or preloadResources
. Drop by to say how it goes. It would be nice if you show webpagetest.org report before and after.
loadable-components
- provides solution for Server Side Rendering, need to find a way to use with snapshots.react-async-component
react-loadable
react-code-splitting
Caching both file#hash1.html
and file#hash2.html
doesn't seem to make sense. Shouldn't it only cache file.html in that case?
I tried react-snap on a code-splitted create-react-app project (using react-loadable
but that's not the issue). Once deployed, the browser started to complain as it didn't know what to do with
<link type="text/css" rel="stylesheet" href="blob:http://localhost:45678/fd887ea6-961a-4721-8a91-a7a08223b642">
The explanation is just above style-loader#useable : If sourcemaps are not turned off (which gaearon usually advices against style-loader fetches the splitted styles this way.
Hey, this is a pretty sweet project ๐ I put together an example project using react-snap & create-react-app & react-router and it seems to work well with ReactDOM.hydrate()
: Check it out here: https://github.com/badsyntax/react-snap-example
Reproducible example at https://github.com/govau/cloud.gov.au/tree/master/www/ui
Run yarn build && yarn build-2-TODO
and you'll see the command fails but with no reason why:
$ yarn build && yarn build-2-TODO
yarn run v1.3.2
$ react-scripts-ts build
Creating an optimized production build...
No valid rules have been specified
ts-loader: Using [email protected] and /Users/Jonathan/go/src/github.com/govau/cloud.gov.au/www/ui/tsconfig.json
Compiled successfully.
File sizes after gzip:
101 KB build/static/js/0.1664397f.chunk.js
73.24 KB build/static/js/main.fb89c8e0.js
1.2 KB build/static/js/1.1f44138b.chunk.js
291 B build/static/js/3.c54b25e2.chunk.js
288 B build/static/js/2.a77791b7.chunk.js
226 B build/static/css/main.688a7215.css
The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
The build folder is ready to be deployed.
You may serve it with a static server:
yarn global add serve
serve -s build
โจ Done in 18.99s.
yarn run v1.3.2
$ react-snap
๐ธ (1/4) /
๐ธ (2/4) /404.html
๐ธ (3/4) /about/
๐ธ (4/4) /insights/
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Any ideas?
I would like to know if is there any option to include a sitemap or a list of path for include?
JS error looks like:
Error: TypeError: Cannot read property 'resize' of undefined
at e.resize (http://localhost:45678/static/js/main.91ecf917.js:1:478812)
at new e (http://localhost:45678/static/js/main.91ecf917.js:1:476478)
at n.componentDidMount (http://localhost:45678/static/js/main.91ecf917.js:1:734681)
at commitLifeCycles (http://localhost:45678/static/js/main.91ecf917.js:1:832876)
at n (http://localhost:45678/static/js/main.91ecf917.js:1:836981)
at u (http://localhost:45678/static/js/main.91ecf917.js:1:838648)
at c (http://localhost:45678/static/js/main.91ecf917.js:1:839091)
at m (http://localhost:45678/static/js/main.91ecf917.js:1:841114)
at d (http://localhost:45678/static/js/main.91ecf917.js:1:840623)
at Object.updateContainer (http://localhost:45678/static/js/main.91ecf917.js:1:907103)
Options:
Related:
Use npm package for loadCss instead of vendoring it (see vendor folder).
Using CRA
if I add the following style link to my index.html
in my public
folder:
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/semantic.min.css" >
i also tried: <link rel="stylesheet" href="%PUBLIC_URL%/semantic.min.css">
And then I added the "inlineCss": true
I get the error:
Error: Evaluation failed: Error: Unable to querySelector('.ui.labels a.active.label:ActiveHover:before') [SyntaxError: Failed to execute 'querySelector' on 'Document': '.ui.labels a.active.label:ActiveHover:before' is not a valid selector.]
at objsCleaned.(anonymous function).selector (<anonymous>:153:21)
at values.filter.selectorString (<anonymous>:75:30)
at Array.filter (<anonymous>)
at children.filter.child (<anonymous>:71:41)
at Array.filter (<anonymous>)
at clean (<anonymous>:68:27)
at cleaner (<anonymous>:105:24)
at links.filter.forEach.stylesheet (<anonymous>:129:42)
at Array.forEach (<anonymous>)
at stylesheetAstObjects (<anonymous>:124:10)
When headless chrome generates page, it can track order of load of resources and generate http2 hints to do http2 push.
Example (waterfall diagram):
index.html
main.css
main.js
data.json
So we can instruct server to do http2 push for main.css
, main.js
and data.json
Static hosting that does not support custom headers:
CDN providers that support headers:
See also:
it is not possible to use both at the same time with react-snap: "0.6.2"
does this work with react-apollo?
sorry if this is a stupid question.
Hey, awesome library here. Excited to see someone improve upon react-snapshot! Moving off of JSDOM, working w/ react-loadable, adding critical css... all awesome! Thanks for your work on this.
Anyways, I appear to have an issue:
I have the following lines in my index.html file to use a google font.
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700" rel="stylesheet">
After running through react-snap, I'm getting:
<style data-href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700" media="@media{a{top:0}}">@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local('Open Sans Regular'),local('OpenSans-Regular'),url(https://fonts.gstatic.com/s/opensans/v15/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;src:local('Open Sans SemiBold'),local('OpenSans-SemiBold'),url(https://fonts.gstatic.com/s/opensans/v15/MTP_ySUJH_bn48VBG8sNSonF5uFdDttMLvmWuJdhhgs.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;src:local('Open Sans Bold'),local('OpenSans-Bold'),url(https://fonts.gstatic.com/s/opensans/v15/k3k702ZOKiLJc3WVjuplzInF5uFdDttMLvmWuJdhhgs.ttf) format('truetype')}</style>
The generated media="@media{a{top:0}}"
prevents the font from applying to anything. Removing the media tag manually resolves the issue.
Any idea on how to resolve this? Is there config that can be done?
Hello!
I don't really want to file a bug or anything, I was just wondering if you have tested this with react-native-web.
I've been working on a project where we have some universal components that we created using react-native-web, so in order to render the application I have to do something like:
const ComponentInst = (
<RootAppComponent
store={store}
persistor={persistor}
history={history}
/>
);
if (rootEl.hasChildNodes()) {
ReactNative.hydrate(ComponentInst, rootEl);
} else {
ReactNative.render(ComponentInst, rootEl);
}
At the beginning of the project we set up the configuration and everything seemed good, the development workflow and the building were working as expected, although we didn't have much content to test it on. The whole time while in development we haven't had any problems with the whole setup, we've been using react-native-web and styled-components.
Now we have deployed an early version of the app and when we built the application we noticed that some stuff wasn't being rendered correctly. I can't really find differences in the generated css, but for some elements the computed styles in the inspector are just different. For example some container elements lost their height.
I know in the react-native-web documentation they use the react-native to do the server side rendering, so maybe what I'm trying to do is not reasonable.
I could get rid of react-snap to "fix" this and maybe later on just do traditional server side rendering as per their docs but it would be really convenient to fix this keeping this approach because we also want to deploy using S3 and CloudFront.
So maybe is there a way to integrate this? Could you point me in the right direction or just tell me if it's not possible, it would save me some time.
Thanks for reading this!
I've noticed the static files for my routes are /ROUTE.html
as opposed to /ROUTE/index.html
. Is there any way I can change this?
It is possible to generate hashes for each inline script and expose them the same way as http2-push-manifest.
See:
Extracted from #33.
blob urls don't make any sense in snapshots, because they are created dynamically. The same way as you can not represent shadowDom in snapshot.
I am usinginlineCss: true
option
and and in my index.html i have a link tag:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.12/semantic.min.css">
I keep getting this error at build:
Error: Evaluation failed: Error: https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.12/semantic.min.css
not in stylesheetAstObjects!
at links.filter.forEach.stylesheet (<anonymous>:126:21)
at Array.forEach (<anonymous>)
at <anonymous>:124:12
screenshots.js:
#!/usr/bin/env node
const { run } = require("react-snap");
run({
source: "build",
destination: "build/screenshots",
saveAs: "png"
});
Error:
$ yarn screenshots
yarn run v1.2.1
$ scripts/screenshots.js
events.js:182
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open '/TST/react16/build/screenshots/index.html'
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
index.html
exists in /TST/react16/build/
and there is no problem if destination is set to destination: "build"
yarn tsc
$ tsc -p .
index.js(65,19): error TS2304: Cannot find name 'Page'.
index.js(136,19): error TS2304: Cannot find name 'Page'.
index.js(207,54): error TS6133: 'route' is declared but its value is never read.
index.js(222,38): error TS6133: 'options' is declared but its value is never read.
src/puppeteer_utils.js(8,19): error TS2304: Cannot find name 'Page'.
src/puppeteer_utils.js(25,19): error TS2304: Cannot find name 'Page'.
src/puppeteer_utils.js(55,19): error TS2304: Cannot find name 'Page'.
src/puppeteer_utils.js(73,75): error TS2304: Cannot find name 'Page'.
src/puppeteer_utils.js(73,139): error TS2304: Cannot find name 'Page'.
related puppeteer/puppeteer#1170
Discussed here errorception/snapshotify#1
For now, option "saveAs" only accept some file extension, but for dynamic router, only file without extension will work.
I have to manually remove extension like this:
for file in *.html; do mv $file ${file%.html}; done
I was using React-snapshot
was I am unable to use it with redux-persist
because the following code which renders main app only after the redux store has been re-hydrated using redux-persist
:
import {render as snapshotRender} from 'react-snapshot'
import {ConnectedRouter} from 'react-router-redux'
async function init() {
const store = await configureStore()
snapshotRender(
<Provider store={store}>
{/* ConnectedRouter will use the store from Provider automatically */}
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById('root')
)
}
registerServiceWorker()
init()
I get the error that react-snapshot render was never called. Will this lib work within async function like above ?
Hiya,
The server environment I'm deploying to has security restrictions on running Chromium, so in order for react-snap to run correctly I'll need to add the --no-sandbox
flag to Chromium when it runs. How would I go a bout doing that? Cheers.
If user bothered to do prerendering, lets make sure one will get max benefit out of it - I mean SEO (additionally to speed). Also possible to generate sitemap.xml
. Also can check budgets for file sizes.
Hello,
I've cloned the example repository which was created with create-react-app: https://github.com/badsyntax/react-snap-example.
I installed react-snap using npm install react-snap --save-dev
.
In the package.json, I also changed "build": "react-scripts build"
to "build": "react-scripts build && react-snap",
. In my command line I ran npm run build
, and got the following error:
/Users/Ludo/Documents/sites/react/react-snap-example/node_modules/react-snap/index.js:45
...defaultOptions,
^^^
SyntaxError: Unexpected token ...
at createScript (vm.js:56:10)
at Object.runInThisContext (vm.js:97:10)
at Module._compile (module.js:542:28)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:393:7)
at startup (bootstrap_node.js:150:9)
npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "build"
npm ERR! node v6.10.2
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build: `react-scripts build && node ./node_modules/react-snap`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script 'react-scripts build && node ./node_modules/react-snap'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the react-snap-example package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! react-scripts build && node ./node_modules/react-snap
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs react-snap-example
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls react-snap-example
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /Users/Ludo/Documents/sites/react/react-snap-example/npm-debug.log
npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "snap"
npm ERR! node v6.10.2
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] snap: `npm run build && node ./node_modules/react-snap`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] snap script 'npm run build && node ./node_modules/react-snap'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the react-snap-example package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! npm run build && node ./node_modules/react-snap
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs react-snap-example
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls react-snap-example
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /Users/Ludo/Documents/sites/react/react-snap-example/npm-debug.log
when I changed "build": "react-scripts build && react-snap"
to "build": "react-scripts build && node ./node_modules/react-snap",
I got the same error, and when I ran npm run snap
like in the tutorial aswell.
Am I doing something wrong?
Ludo
same as peterbe/minimalcss#33
create diagnostic tool which will give recommendations based on package.json. For example, if package.json contains loadable-components
recommend config to prevent flash etc. Basically check everything from caveats section.
Like brew doctor
this is not a bug, rather a question.
I am using some img
tags with images with image loading like so:
import four from 'media/images/landingPage/four.png'
but in the static html the images seem broken. even my placeholder src
is not rendering in the static page.
SO my question is how do I handle images with the lib?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.