Một mục tập trung giao diện trong kho dữ liệu GitHub của TopGit: stereobooster/react-snap, 5.1k sao, nhóm Frontend, JavaScript. 👻 Zero-configuration framework-agnostic static prerendering for SPAs
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
Pre-renders a web app into static HTML. Uses Headless Chrome to crawl all available links starting from the root. Heavily inspired by prep and react-snapshot, but written from scratch. Uses best practices to get the best loading performance.
😍 Features
Enables SEO (Google, DuckDuckGo...) and SMO (Twitter, Facebook...) for SPAs.
Works out-of-the-box with create-react-app - no code-changes required.
Uses a real browser behind the scenes, so there are no issues with unsupported HTML5 features, like WebGL or Blobs.
Does a lot of load performance optimization. Here are details, if you are curious.
Does not depend on React. The name is inspired by react-snapshot but works with any technology (e.g., Vue).
npm package does not have a compilation step, so you can fork it, change what you need, and install it with a GitHub URL.
Zero configuration is the main feature. You do not need to worry about how it works or how to configure it. But if you are curious, here are details.
source - output folder of webpack or any other bundler of your choice
Read more about minifyHtml caveats in #142.
Example: Switch from prerender-spa-plugin to react-snap
Caveats
Only works with routing strategies using the HTML5 history API. No hash(bang) URLs.
Vue uses the data-server-rendered attribute on the root element to mark SSR generated markup. When this attribute is present, the VDOM rehydrates instead of rendering everything from scratch, which can result in a flash.
window.snapSaveState is a callback to save the state of the application at the end of rendering. It can be used for Redux or async components. In this example, it is repurposed to alter the DOM, this is why I call it a "hack." Maybe in future versions of react-snap, I will come up with better abstractions or automate this process.
Vue 1.x
Make sure to use replace: false for root components
✨ Examples
Emotion website load performance optimization
Load performance optimization
recipes
stereobooster/an-almost-static-stack
⚙️ Customization
If you need to pass some options for react-snap, you can do this in your package.json like this:
"reactSnap": {
"inlineCss": true
}
Not all options are documented yet, but you can check defaultOptions in index.js.
inlineCss
Experimental feature - requires improvements.
react-snap can inline critical CSS with the help of minimalcss and full CSS will be loaded in a non-blocking manner with the help of loadCss.
Use inlineCss: true to enable this feature.
TODO: as soon as this feature is stable, it should be enabled by default.
⚠️ Caveats
Async components
Also known as code splitting, dynamic import (TC39 proposal), "chunks" (which are loaded on demand), "layers", "rollups", or "fragments". See: Guide To JavaScript Async Components
An async component (in React) is a technique (typically implemented as a higher-order component) for loading components on demand with the dynamic import operator. There are a lot of solutions in this field. Here are some examples:
react.lazy
loadable-components
react-loadable
react-async-component
It is not a problem to render async components with react-snap, the tricky part happens when a prerendered React application boots and async components are not loaded yet, so React draws the "loading" state of a component, and later when the component is loaded, React draws the actual component. As a result, the user sees a flash:
Usually a code splitting library provides an API to handle it during SSR, but as long as "real" SSR is not used in react-snap - the issue surfaces, and there is no simple way to fix it.
Use react-prerendered-component. This library holds onto the prerendered HTML until the dynamically imported code is ready.
import loadable from "@loadable/component";
import { PrerenderedComponent } from "react-prerendered-component";
const prerenderedLoadable = dynamicImport => {
const LoadableComponent = loadable(dynamicImport);
return React.memo(props => (
// you can use the `.preload()` method from react-loadable or react-imported-component`
<PrerenderedComponent live={LoadableComponent.load()}>
<LoadableComponent {...props} />
</PrerenderedComponent>
));
};
const MyComponent = prerenderedLoadable(() => import("./MyComponent"));
MyComponent will use prerendered HTML to prevent the page content from flashing (it will find the required piece of HTML using an id attribute generated by PrerenderedComponent and inject it using dangerouslySetInnerHTML).
The same approach will work with React.lazy, but React.lazy doesn't provide a prefetch method (load or preload), so you need to implement it yourself (this can be a fragile solution).
loadable-components were deprecated in favour of @loadable/component, but @loadable/component dropped getState. So if you want to use loadable-components you can use old version (2.2.3 latest version at the moment of writing) or you can wait until React will implement proper handling of this case with asynchronous rendering and React.lazy.
Redux
See: Redux Server Rendering Section
// Grab the state from a global variable injected into the server-generated HTML
const preloadedState = window.__PRELOADED_STATE__;
// Allow the passed state to be garbage-collected
delete window.__PRELOADED_STATE__;
// Create Redux store with initial state
const store = createStore(counterApp, preloadedState || initialState);
// Tell react-snap how to save Redux state
window.snapSaveState = () => ({
__PRELOADED_STATE__: store.getState()
});
Caution: as of now, only basic "JSON" data types are supported: e.g. Date, Set, Map, and NaNwon't be handled correctly (#54).
Third-party requests: Google Analytics, Mapbox, etc.
You can block all third-party requests with the following config:
"skipThirdPartyRequests": true
AJAX
react-snap can capture all AJAX requests. It will store json requests in the domain in window.snapStore[<path>], where <path> is the path of the request.
Use "cacheAjaxRequests": true to enable this feature.
This feature can conflict with the browser cache. See #197 for details. You may want to disable cache in this case: "puppeteer": { "cache": false }.
Service Workers
By default, create-react-app uses index.html as a fallback:
navigateFallback: publicUrl + '/index.html',
You need to change this to an un-prerendered version of index.html - 200.html, otherwise you will see index.html flash on other pages (if you have any). See Configure sw-precache without ejecting for more information.
Containers and other restricted environments
Puppeteer (Headless Chrome) may fail due to sandboxing issues. To get around this,
you may use:
See this PR. At the moment of writing, Heroku doesn't support HTTP/2.
Semantic UI
Semantic UI is defined over class substrings that contain spaces
(e.g., "three column"). Sorting the class names, therefore, breaks the styling. To get around this,
use the following configuration:
"minifyHtml": { "sortClassName": false }
From version 1.17.0, sortClassName is false by default.
JSS
Once JS on the client is loaded, components initialized and your JSS styles are regenerated, it's a good time to remove server-side generated style tag in order to avoid side-effects
This basically means that JSS doesn't support rehydration. See #99 for a possible solutions.
react-router v3
See #135.
userAgent
You can use navigator.userAgent == "ReactSnap" to do some checks in the app code while snapping—for example, if you use an absolute path for your API AJAX request. While crawling, however, you should request a specific host.
stereobooster/react-snap thuộc nhóm Frontend trên TopGit, cùng 8 topic GitHub. Trang Trending và Topics liệt kê các repo cùng số sao và cùng ngôn ngữ để so sánh.
Đọc thêm về stereobooster/react-snap ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/stereobooster/react-snap là nguồn chính thức.
stereobooster/react-snap có bao nhiêu sao?
stereobooster/react-snap có 5.1k sao GitHub — tải lại trang để xem số mới nhất, hoặc xem trực tiếp github.com/stereobooster/react-snap. TopGit phản chiếu số sao của GitHub nhưng không cam kết đến từng phút.
stereobooster/react-snap có những chủ đề gì?
GitHub topics của stereobooster/react-snap: "prerender", "react", "seo", "server-side-rendering", "ssr", "static-site-generator", "vue", "zero-configuration". TopGit xếp repo vào nhóm Frontend.
stereobooster/react-snap có phải mã nguồn mở không?
Có — stereobooster/react-snap phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/stereobooster/react-snap.
stereobooster/react-snap có website riêng không?
TopGit chưa ghi nhận URL trang chủ cho stereobooster/react-snap. Phần README ở tab phía trên thường có link demo, hoặc xem mô tả GitHub của repo.
stereobooster/react-snap còn đang phát triển không?
Commit gần nhất trên stereobooster/react-snap là 6 tháng trước (theo timestamp GitHub). Repo có 398 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
Đọc đầy đủ README ở tab phía trên.
Vẫn đang phân vân về react-snap?
Một cú bấm sẽ gửi câu hỏi kèm trang này cho AI — xem AI nói gì về react-snap.