├── .gitignore
├── code-of-conduct.md
├── contributing.md
├── license.md
├── package.json
├── prerender-dynamic.md
├── prerender-static.md
├── readme.md
├── readme.template.md
├── reframe.md
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | npm-debug.log*
2 | yarn-error.log
3 | package-lock.json
4 | node_modules/
5 |
--------------------------------------------------------------------------------
/code-of-conduct.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at
59 | github.com/code-of-conduct@brillout.com. All
60 | complaints will be reviewed and investigated and will result in a response that
61 | is deemed necessary and appropriate to the circumstances. The project team is
62 | obligated to maintain confidentiality with regard to the reporter of an incident.
63 | Further details of specific enforcement policies may be posted separately.
64 |
65 | Project maintainers who do not follow or enforce the Code of Conduct in good
66 | faith may face temporary or permanent repercussions as determined by other
67 | members of the project's leadership.
68 |
69 | ## Attribution
70 |
71 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
72 | available at [http://contributor-covenant.org/version/1/4][version]
73 |
74 | [homepage]: http://contributor-covenant.org
75 | [version]: http://contributor-covenant.org/version/1/4/
76 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 |
3 | Note that this project is released with a [Contributor Code of Conduct](code-of-conduct.md).
4 | By participating in this project you agree to abide by its terms.
5 |
6 | -
7 |
8 | Contribution guidelines:
9 |
10 | - Make an individual pull request for each suggestion.
11 | - Use the following format for adding a tool: ` - [Project Name](https://github.com/owner/repo#readme) - Description without emojis.`.
12 | - There is no format for the learning section.
13 | - Your addition should be added to the bottom of the relevant section.
14 | - If it doesn't fit any category then open a new issue so we can discuss improving the categorization.
15 | - Check your spelling and grammar.
16 | - If you just created something, wait at least a couple of weeks before submitting it.
17 | - All texts should be translated to English.
18 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 |
3 | Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | 1. Copyright and Related Rights. A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | 3. Public License Fallback. Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | 4. Limitations and Disclaimers.
94 |
95 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
96 | surrendered, licensed or otherwise affected by this document.
97 |
98 | b. Affirmer offers the Work as-is and makes no representations or warranties
99 | of any kind concerning the Work, express, implied, statutory or otherwise,
100 | including without limitation warranties of title, merchantability, fitness
101 | for a particular purpose, non infringement, or the absence of latent or
102 | other defects, accuracy, or the present or absence of errors, whether or not
103 | discoverable, all to the greatest extent permissible under applicable law.
104 |
105 | c. Affirmer disclaims responsibility for clearing rights of other persons
106 | that may apply to the Work or any use thereof, including without limitation
107 | any person's Copyright and Related Rights in the Work. Further, Affirmer
108 | disclaims responsibility for obtaining any necessary consents, permissions
109 | or other rights required for any use of the Work.
110 |
111 | d. Affirmer understands and acknowledges that Creative Commons is not a
112 | party to this document and has no duty or obligation with respect to this
113 | CC0 or use of the Work.
114 |
115 | For more information, please see
116 |
117 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "docs": "mdocs"
5 | },
6 | "devDependencies": {
7 | "@brillout/mdocs": "^0.1.20"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/prerender-dynamic.md:
--------------------------------------------------------------------------------
1 | #### Dynamic Pre-Rendering
2 |
3 | Automatically and regularly render your deployed website to HTML.
4 |
5 | ##### SaaS
6 |
7 | - [Prerender.io](https://prerender.io/)
8 | - [SEO4Ajax](https://www.seo4ajax.com/)
9 | - [Prerender.cloud](https://www.prerender.cloud/)
10 | - [SEO.js](http://getseojs.com/)
11 | - [BromBone](https://www.brombone.com/)
12 |
13 | ##### Libraries
14 |
15 | - [Prerender.io Node Server](https://github.com/prerender/prerender#readme) - The prerender.io Node Server is open source.
16 |
--------------------------------------------------------------------------------
/prerender-static.md:
--------------------------------------------------------------------------------
1 | #### Static Pre-Rendering
2 |
3 | *Some static pre-renderers, instead of generating HTML upon a generated DOM, directly render your pages to HTML.*
4 |
5 | - [Prerender SPA Plugin](https://github.com/chrisvfritz/prerender-spa-plugin#readme) - Uses Puppeteer to crawl & render your pages.
6 | - [react-snap](https://github.com/stereobooster/react-snap#readme) - Uses Puppeteer to crawl & render your pages.
7 | - [prep](https://github.com/prismagraphql/prep#readme) - Uses Chromeless to crawl & render your pages.
8 | - [SSG webpack plugin](https://github.com/markdalgleish/static-site-generator-webpack-plugin#readme) - Directly render your pages to HTML. You provide render functions and routes. All routes are rendered at build-time using the render functions you provided. Also has a crawl mode to use a headless browser to automatically discover your website's URLs.
9 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
78 | # Awesome Universal Rendering [](https://awesome.re)
79 |
80 | Awesome resources about universal rendering:
81 | - **Introduction**
82 |
83 | Explains why universal rendering is beneficial,
84 | the different techniques of doing universal rendering (SSR, SSG, pre-rendering)
85 | and when to use what technique.
86 | - **Learning Material**
87 | - SEO benefits of universal rendering
88 | - Performance benefits of SSR
89 | - How to implement SSR
90 | - **Tools**
91 | - SSR frameworks & libraries
92 | - Pre-rendering services & tools
93 | - Static site generators
94 |
95 |
96 |
97 | #### Contents
98 |
99 | - [Introduction](#introduction)
100 | - [Learning Material](#learning-material)
101 | - [Tools](#tools)
102 |
103 |
104 |
105 | ## Introduction
106 |
107 | Modern view libraries (React, Vue, Angular, etc.) render views to the DOM in the browser but they can as well render views to HTML on the server.
108 | This capability can be used to render the same view twice:
109 | First to HTML then again to the DOM. (Re-rendering the view in the browser is called *hydrating*.)
110 | This practice is called *universal rendering* (aka isomorphic rendering).
111 |
112 | Universal rendering leads to improvements in SEO, SMO and performance.
113 |
114 | There are several techniques to achieve universal rendering:
115 |
116 | - Server-Side Rendering (SSR)
117 | - Static Site Generators (SSG)
118 | - Pre-Rendering
119 |
120 | In the following we explain these techniques and the benefits of universal rendering.
121 |
122 | - [Benefits](#benefits)
123 | - [Techniques](#techniques)
124 |
125 | ### Benefits
126 |
127 | #### SEO
128 |
129 | Modern frontends (React, Vue, Angular, ...) use JavaScript to load and display content.
130 | Such JavaScript-generated-content is invisible to crawlers that don't execute JavaScript.
131 | Most crawlers (search engines and social sites) don't execute JavaScript.
132 |
133 | The Google crawler is
134 | the only one that can successfully index JavaScript-generated-content.
135 | But it has limitations.
136 | (Mainly around delayed indexing and client-side routing,
137 | see [Learning Material](#learning-material).)
138 |
139 | If you want your content to be crawled by all other search engines (Bing, Baidu, DuckDuckGo, etc.), then your content needs to be included in your website's HTML.
140 |
141 | #### SMO
142 |
143 | The crawler of social media sites (Facebook, Twitter, ...) don't execute JavaScript and rely on HTML exclusively.
144 |
145 | If you want your website to be correctly previewed when a user shares your website, then the corresponding information needs to be included in your website's HTML.
146 |
147 | (SMO means "Social Media Optimization".)
148 |
149 | #### Performance
150 |
151 | Rendering your website's pages to HTML decreases the perceived loading time:
152 | Once the HTML is loaded, content can already be displayed before any JavaScript is loaded/executed.
153 |
154 | The improvement is considerable on mobile
155 | where loading and executing JavaScript is much slower.
156 |
157 | ### Techniques
158 |
159 | Server-Side Rendering (SSR), Pre-Rendering, and Static Site Generators (SSG) are techniques to render JavaScript-generated-content to HTML.
160 | Making the content visible to crawlers and improving performance.
161 |
162 | There are two ways to render JavaScript-generated-content to HTML:
163 |
164 | - **Directly render to HTML**
165 |
166 | Modern view libraries (React, Vue, Angular, ...) can render views to HTML (in addition to be able to render views to the DOM).
167 | (E.g. a React component can be rendered to HTML with `require('react-dom/server').renderToStaticMarkup()`.)
168 | - **Render to HTML via headless browser**
169 |
170 | A headless browser runs your website's JavaScript,
171 | the website's pages are rendered to the DOM of the headless browser,
172 | and HTML is automatically generated from the resulting DOM.
173 |
174 | Leading to the following techniques:
175 |
176 | - **Server-Side Rendering (SSR)**
177 |
178 | Directly render your website's pages to HTML at request-time:
179 | Every time a user requests a page, the server renders the page directly to HTML.
180 |
181 | SSR is the most reliable option if your HTML changes frequently.
182 | (If your website's content may change after deploy-time,
183 | e.g. if you website's content is generated by users.)
184 | - **Pre-Rendering**
185 |
186 | A headless browser crawls your website, executes the website's JavaScript, and generates HTML upon the resulting DOM.
187 | - **Static Site Generators (SSG)**
188 |
189 | A static site is a website that doesn't have any server code:
190 | The website is composed of static browser assets only (HTML, CSS, JavaScript, images, fonts, etc.).
191 | Some SSG are able to render your views to HTML at build-time:
192 | When your website is built, each page is rendered to a HTML file that includes your page's content.
193 |
194 | If your content only changes at deploy-time, then using a SSG is an option.
195 |
196 |
197 |
198 |
199 |
200 |
201 | ## Learning Material
202 |
203 | ### SEO/SMO
204 |
205 | - [Hacker News Comment](https://news.ycombinator.com/item?id=12759605) - This HN comment explains the problem with SEO and search engines other than Google.
206 | - [Tweet from Google employee](https://twitter.com/Paul_Kinlan/status/1039852756113080320) - Tweet about delayed Google indexing for pure client-side.
207 | - [What's Server Side Rendering and do I need it?](https://medium.com/@baphemot/whats-server-side-rendering-and-do-i-need-it-cb42dc059b38) - Good summary about the issues of JavaScript-generated-content.
208 | - [Deliver search-friendly JavaScript-powered websites (Google I/O '18)](https://www.youtube.com/watch?v=PFwUbgvpdaQ) - Talk that mentions how the Google crawler executes JavaScript. Main take away: Google does index JavaScript-generated-content but with a delay.
209 |
210 | ### How to implement SSR
211 |
212 | - [The Complete Guide for SSR with Vue](https://ssr.vuejs.org/) - Official guide.
213 | - [Reactjs SSR Tips and Tricks](https://medium.com/@atahani/reactjs-ssr-tips-and-tricks-be9edff5b7bb)
214 | - [Server-side rendering with create-react-app, code-splitting, preloaded data, React Router, Helmet, Redux, and Thunk](https://medium.com/@cereallarceny/server-side-rendering-in-create-react-app-with-all-the-goodies-without-ejecting-4c889d7db25e) - Walkthrough of implementing a SSR app based on CRA (without having ejected).
215 |
216 | ### General discussion
217 |
218 | - [The Benefits of Server Side Rendering Over Client Side Rendering](https://medium.com/walmartlabs/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8)
219 |
220 |
221 |
222 |
223 |
224 |
225 | ## Tools
226 |
227 | #### Contents
228 |
229 | - [React](#react)
230 | - [SSR](#ssr)
231 | - [SSG](#ssg)
232 | - [Pre-Rendering](#pre-rendering)
233 | - [Vue](#vue)
234 | - [SSR](#ssr-1)
235 | - [SSG](#ssg-1)
236 | - [Pre-Rendering](#pre-rendering-1)
237 | - [Angular](#angular)
238 | - [SSR](#ssr-2)
239 | - [Pre-Rendering](#pre-rendering-2)
240 | - [View Library Agnostic](#view-library-agnostic)
241 | - [SSG](#ssg-2)
242 | - [Pre-Rendering](#pre-rendering-3)
243 |
244 |
245 |
246 |
247 |
248 |
249 | ### React
250 |
251 | #### SSR
252 |
253 | ##### Frameworks
254 |
255 | - [Next.js](https://github.com/zeit/next.js#readme) - The most popular SSR tool.
256 | - [After.js](https://github.com/jaredpalmer/after.js#readme) - Similar to Next.js but with routing based on React Router.
257 | - [React Server](https://github.com/redfin/react-server#readme)
258 | - [Reframe](https://github.com/reframejs/reframe#readme) - Flexible web framework. It does SSR by default and can be used as SSG.
259 | - [Fusion.js](https://github.com/fusionjs) - Plugin-based universal web framework maintained by Uber.
260 |
261 | ##### Libraries
262 |
263 | - [Goldpage](https://github.com/reframejs/goldpage) - A do-one-thing-do-it-well library that supports all app types; "SPA", "SSR", "Static Website", etc.
264 | - [Razzle](https://github.com/jaredpalmer/razzle#readme) - Handles the building. You do the rest.
265 | - [React Universal Component](https://github.com/faceyspacey/react-universal-component#readme) - Utility to code split your SSR app.
266 | - [Rogue.js](https://github.com/alidcastano/rogue.js#readme) - SSR utilities focused on flexibility. First-class support for React Router, Apollo GraphQL, Redux, Emotion, and Styled-Components. The build step is up to you (but you can use Razzle.)
267 |
268 | ##### Boilerplates
269 |
270 | - [cra-ssr](https://github.com/cereallarceny/cra-ssr#readme) - SSR app boilerplate based on CRA (without having ejected).
271 |
272 | #### SSG
273 |
274 | - [Gatsby.js](https://github.com/gatsbyjs/gatsby#readme) - SSG based on React and GraphQL.
275 | - [React Static](https://github.com/nozzle/react-static#readme) - SSG based on React and focused on simplicity.
276 | - [Goldpage](https://github.com/reframejs/goldpage) - A do-one-thing-do-it-well library that supports all app types; "SPA", "SSR", "Static Website", etc.
277 | - [Phenomic](https://github.com/phenomic/phenomic#readme) - SSG based on a flexible plugin system.
278 | - [Next.js](https://github.com/zeit/next.js#readme) - Although primarily focused on SSR, Next.js can also generate static sites.
279 | - [Reframe](https://github.com/reframejs/reframe#readme) - Flexible web framework. It does SSR by default and can be used as SSG.
280 |
281 | #### Pre-Rendering
282 |
283 | #### Dynamic Pre-Rendering
284 |
285 | Automatically and regularly render your deployed website to HTML.
286 |
287 | ##### SaaS
288 |
289 | - [Prerender.io](https://prerender.io/)
290 | - [SEO4Ajax](https://www.seo4ajax.com/)
291 | - [Prerender.cloud](https://www.prerender.cloud/)
292 | - [SEO.js](http://getseojs.com/)
293 | - [BromBone](https://www.brombone.com/)
294 |
295 | ##### Libraries
296 |
297 | - [Prerender.io Node Server](https://github.com/prerender/prerender#readme) - The prerender.io Node Server is open source.
298 |
299 | #### Static Pre-Rendering
300 |
301 | *Some static pre-renderers, instead of generating HTML upon a generated DOM, directly render your pages to HTML.*
302 |
303 | - [Prerender SPA Plugin](https://github.com/chrisvfritz/prerender-spa-plugin#readme) - Uses Puppeteer to crawl & render your pages.
304 | - [react-snap](https://github.com/stereobooster/react-snap#readme) - Uses Puppeteer to crawl & render your pages.
305 | - [prep](https://github.com/prismagraphql/prep#readme) - Uses Chromeless to crawl & render your pages.
306 | - [SSG webpack plugin](https://github.com/markdalgleish/static-site-generator-webpack-plugin#readme) - Directly render your pages to HTML. You provide render functions and routes. All routes are rendered at build-time using the render functions you provided. Also has a crawl mode to use a headless browser to automatically discover your website's URLs.
307 | - [React Snapshot](https://github.com/geelen/react-snapshot#readme) - Pre-renders React apps at build-time. Uses `require('react-dom/server').renderToString` to directly render the HTML. Uses JSDOM as headless browser to automatically discover your app's URLs.
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 | ### Vue
316 |
317 | #### SSR
318 |
319 | ##### Frameworks
320 |
321 | - [Nuxt](https://github.com/nuxt/nuxt.js#readme) - Similar to Next.js but for Vue.
322 | - [Reframe](https://github.com/reframejs/reframe#readme) - Flexible web framework. It does SSR by default and can be used as SSG.
323 |
324 | ##### Libraries
325 |
326 | - [vue-server-renderer](https://www.npmjs.com/package/vue-server-renderer) - Official library for SSR with Vue.
327 | - [Goldpage](https://github.com/reframejs/goldpage) - A do-one-thing-do-it-well library that supports all app types; "SPA", "SSR", "Static Website", etc.
328 |
329 | #### SSG
330 |
331 | - [Phenomic](https://github.com/phenomic/phenomic#readme) - SSG based on a flexible plugin system.
332 | - [Reframe](https://github.com/reframejs/reframe#readme) - Flexible web framework. It does SSR by default and can be used as SSG.
333 |
334 | #### Pre-Rendering
335 |
336 | #### Dynamic Pre-Rendering
337 |
338 | Automatically and regularly render your deployed website to HTML.
339 |
340 | ##### SaaS
341 |
342 | - [Prerender.io](https://prerender.io/)
343 | - [SEO4Ajax](https://www.seo4ajax.com/)
344 | - [Prerender.cloud](https://www.prerender.cloud/)
345 | - [SEO.js](http://getseojs.com/)
346 | - [BromBone](https://www.brombone.com/)
347 |
348 | ##### Libraries
349 |
350 | - [Prerender.io Node Server](https://github.com/prerender/prerender#readme) - The prerender.io Node Server is open source.
351 |
352 | #### Static Pre-Rendering
353 |
354 | *Some static pre-renderers, instead of generating HTML upon a generated DOM, directly render your pages to HTML.*
355 |
356 | - [Prerender SPA Plugin](https://github.com/chrisvfritz/prerender-spa-plugin#readme) - Uses Puppeteer to crawl & render your pages.
357 | - [react-snap](https://github.com/stereobooster/react-snap#readme) - Uses Puppeteer to crawl & render your pages.
358 | - [prep](https://github.com/prismagraphql/prep#readme) - Uses Chromeless to crawl & render your pages.
359 | - [SSG webpack plugin](https://github.com/markdalgleish/static-site-generator-webpack-plugin#readme) - Directly render your pages to HTML. You provide render functions and routes. All routes are rendered at build-time using the render functions you provided. Also has a crawl mode to use a headless browser to automatically discover your website's URLs.
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 | ### Angular
369 |
370 | #### SSR
371 |
372 | - [Angular Universal](https://github.com/angular/universal#readme) - Official packages for SSR with Angular.
373 |
374 | #### Pre-Rendering
375 |
376 | #### Dynamic Pre-Rendering
377 |
378 | Automatically and regularly render your deployed website to HTML.
379 |
380 | ##### SaaS
381 |
382 | - [Prerender.io](https://prerender.io/)
383 | - [SEO4Ajax](https://www.seo4ajax.com/)
384 | - [Prerender.cloud](https://www.prerender.cloud/)
385 | - [SEO.js](http://getseojs.com/)
386 | - [BromBone](https://www.brombone.com/)
387 |
388 | ##### Libraries
389 |
390 | - [Prerender.io Node Server](https://github.com/prerender/prerender#readme) - The prerender.io Node Server is open source.
391 |
392 | #### Static Pre-Rendering
393 |
394 | *Some static pre-renderers, instead of generating HTML upon a generated DOM, directly render your pages to HTML.*
395 |
396 | - [Prerender SPA Plugin](https://github.com/chrisvfritz/prerender-spa-plugin#readme) - Uses Puppeteer to crawl & render your pages.
397 | - [react-snap](https://github.com/stereobooster/react-snap#readme) - Uses Puppeteer to crawl & render your pages.
398 | - [prep](https://github.com/prismagraphql/prep#readme) - Uses Chromeless to crawl & render your pages.
399 | - [SSG webpack plugin](https://github.com/markdalgleish/static-site-generator-webpack-plugin#readme) - Directly render your pages to HTML. You provide render functions and routes. All routes are rendered at build-time using the render functions you provided. Also has a crawl mode to use a headless browser to automatically discover your website's URLs.
400 |
401 |
402 |
403 |
404 |
405 |
406 | ### View Library Agnostic
407 |
408 | #### SSG
409 |
410 | - [Phenomic](https://github.com/phenomic/phenomic#readme) - SSG based on a flexible plugin system.
411 | - [Reframe](https://github.com/reframejs/reframe#readme) - Flexible web framework. It does SSR by default and can be used as SSG.
412 |
413 | #### Pre-Rendering
414 |
415 | #### Dynamic Pre-Rendering
416 |
417 | Automatically and regularly render your deployed website to HTML.
418 |
419 | ##### SaaS
420 |
421 | - [Prerender.io](https://prerender.io/)
422 | - [SEO4Ajax](https://www.seo4ajax.com/)
423 | - [Prerender.cloud](https://www.prerender.cloud/)
424 | - [SEO.js](http://getseojs.com/)
425 | - [BromBone](https://www.brombone.com/)
426 |
427 | ##### Libraries
428 |
429 | - [Prerender.io Node Server](https://github.com/prerender/prerender#readme) - The prerender.io Node Server is open source.
430 |
431 | #### Static Pre-Rendering
432 |
433 | *Some static pre-renderers, instead of generating HTML upon a generated DOM, directly render your pages to HTML.*
434 |
435 | - [Prerender SPA Plugin](https://github.com/chrisvfritz/prerender-spa-plugin#readme) - Uses Puppeteer to crawl & render your pages.
436 | - [react-snap](https://github.com/stereobooster/react-snap#readme) - Uses Puppeteer to crawl & render your pages.
437 | - [prep](https://github.com/prismagraphql/prep#readme) - Uses Chromeless to crawl & render your pages.
438 | - [SSG webpack plugin](https://github.com/markdalgleish/static-site-generator-webpack-plugin#readme) - Directly render your pages to HTML. You provide render functions and routes. All routes are rendered at build-time using the render functions you provided. Also has a crawl mode to use a headless browser to automatically discover your website's URLs.
439 |
440 |
441 |
518 |
--------------------------------------------------------------------------------
/readme.template.md:
--------------------------------------------------------------------------------
1 | # Awesome Universal Rendering [](https://awesome.re)
2 |
3 | Awesome resources about universal rendering:
4 | - **Introduction**
5 |
6 | Explains why universal rendering is beneficial,
7 | the different techniques of doing universal rendering (SSR, SSG, pre-rendering)
8 | and when to use what technique.
9 | - **Learning Material**
10 | - SEO benefits of universal rendering
11 | - Performance benefits of SSR
12 | - How to implement SSR
13 | - **Tools**
14 | - SSR frameworks & libraries
15 | - Pre-rendering services & tools
16 | - Static site generators
17 |
18 |
19 |
20 | #### Contents
21 |
22 | - [Introduction](#introduction)
23 | - [Learning Material](#learning-material)
24 | - [Tools](#tools)
25 |
26 |
27 |
28 | ## Introduction
29 |
30 | Modern view libraries (React, Vue, Angular, etc.) render views to the DOM in the browser but they can as well render views to HTML on the server.
31 | This capability can be used to render the same view twice:
32 | First to HTML then again to the DOM. (Re-rendering the view in the browser is called *hydrating*.)
33 | This practice is called *universal rendering* (aka isomorphic rendering).
34 |
35 | Universal rendering leads to improvements in SEO, SMO and performance.
36 |
37 | There are several techniques to achieve universal rendering:
38 |
39 | - Server-Side Rendering (SSR)
40 | - Static Site Generators (SSG)
41 | - Pre-Rendering
42 |
43 | In the following we explain these techniques and the benefits of universal rendering.
44 |
45 | - [Benefits](#benefits)
46 | - [Techniques](#techniques)
47 |
48 | ### Benefits
49 |
50 | #### SEO
51 |
52 | Modern frontends (React, Vue, Angular, ...) use JavaScript to load and display content.
53 | Such JavaScript-generated-content is invisible to crawlers that don't execute JavaScript.
54 | Most crawlers (search engines and social sites) don't execute JavaScript.
55 |
56 | The Google crawler is
57 | the only one that can successfully index JavaScript-generated-content.
58 | But it has limitations.
59 | (Mainly around delayed indexing and client-side routing,
60 | see [Learning Material](#learning-material).)
61 |
62 | If you want your content to be crawled by all other search engines (Bing, Baidu, DuckDuckGo, etc.), then your content needs to be included in your website's HTML.
63 |
64 | #### SMO
65 |
66 | The crawler of social media sites (Facebook, Twitter, ...) don't execute JavaScript and rely on HTML exclusively.
67 |
68 | If you want your website to be correctly previewed when a user shares your website, then the corresponding information needs to be included in your website's HTML.
69 |
70 | (SMO means "Social Media Optimization".)
71 |
72 | #### Performance
73 |
74 | Rendering your website's pages to HTML decreases the perceived loading time:
75 | Once the HTML is loaded, content can already be displayed before any JavaScript is loaded/executed.
76 |
77 | The improvement is considerable on mobile
78 | where loading and executing JavaScript is much slower.
79 |
80 | ### Techniques
81 |
82 | Server-Side Rendering (SSR), Pre-Rendering, and Static Site Generators (SSG) are techniques to render JavaScript-generated-content to HTML.
83 | Making the content visible to crawlers and improving performance.
84 |
85 | There are two ways to render JavaScript-generated-content to HTML:
86 |
87 | - **Directly render to HTML**
88 |
89 | Modern view libraries (React, Vue, Angular, ...) can render views to HTML (in addition to be able to render views to the DOM).
90 | (E.g. a React component can be rendered to HTML with `require('react-dom/server').renderToStaticMarkup()`.)
91 | - **Render to HTML via headless browser**
92 |
93 | A headless browser runs your website's JavaScript,
94 | the website's pages are rendered to the DOM of the headless browser,
95 | and HTML is automatically generated from the resulting DOM.
96 |
97 | Leading to the following techniques:
98 |
99 | - **Server-Side Rendering (SSR)**
100 |
101 | Directly render your website's pages to HTML at request-time:
102 | Every time a user requests a page, the server renders the page directly to HTML.
103 |
104 | SSR is the most reliable option if your HTML changes frequently.
105 | (If your website's content may change after deploy-time,
106 | e.g. if you website's content is generated by users.)
107 | - **Pre-Rendering**
108 |
109 | A headless browser crawls your website, executes the website's JavaScript, and generates HTML upon the resulting DOM.
110 | - **Static Site Generators (SSG)**
111 |
112 | A static site is a website that doesn't have any server code:
113 | The website is composed of static browser assets only (HTML, CSS, JavaScript, images, fonts, etc.).
114 | Some SSG are able to render your views to HTML at build-time:
115 | When your website is built, each page is rendered to a HTML file that includes your page's content.
116 |
117 | If your content only changes at deploy-time, then using a SSG is an option.
118 |
119 |
120 |
121 |
122 |
123 |
124 | ## Learning Material
125 |
126 | ### SEO/SMO
127 |
128 | - [Hacker News Comment](https://news.ycombinator.com/item?id=12759605) - This HN comment explains the problem with SEO and search engines other than Google.
129 | - [Tweet from Google employee](https://twitter.com/Paul_Kinlan/status/1039852756113080320) - Tweet about delayed Google indexing for pure client-side.
130 | - [What's Server Side Rendering and do I need it?](https://medium.com/@baphemot/whats-server-side-rendering-and-do-i-need-it-cb42dc059b38) - Good summary about the issues of JavaScript-generated-content.
131 | - [Deliver search-friendly JavaScript-powered websites (Google I/O '18)](https://www.youtube.com/watch?v=PFwUbgvpdaQ) - Talk that mentions how the Google crawler executes JavaScript. Main take away: Google does index JavaScript-generated-content but with a delay.
132 |
133 | ### How to implement SSR
134 |
135 | - [The Complete Guide for SSR with Vue](https://ssr.vuejs.org/) - Official guide.
136 | - [Reactjs SSR Tips and Tricks](https://medium.com/@atahani/reactjs-ssr-tips-and-tricks-be9edff5b7bb)
137 | - [Server-side rendering with create-react-app, code-splitting, preloaded data, React Router, Helmet, Redux, and Thunk](https://medium.com/@cereallarceny/server-side-rendering-in-create-react-app-with-all-the-goodies-without-ejecting-4c889d7db25e) - Walkthrough of implementing a SSR app based on CRA (without having ejected).
138 |
139 | ### General discussion
140 |
141 | - [The Benefits of Server Side Rendering Over Client Side Rendering](https://medium.com/walmartlabs/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8)
142 |
143 |
144 |
145 |
146 |
147 |
148 | ## Tools
149 |
150 | #### Contents
151 |
152 | - [React](#react)
153 | - [SSR](#ssr)
154 | - [SSG](#ssg)
155 | - [Pre-Rendering](#pre-rendering)
156 | - [Vue](#vue)
157 | - [SSR](#ssr-1)
158 | - [SSG](#ssg-1)
159 | - [Pre-Rendering](#pre-rendering-1)
160 | - [Angular](#angular)
161 | - [SSR](#ssr-2)
162 | - [Pre-Rendering](#pre-rendering-2)
163 | - [View Library Agnostic](#view-library-agnostic)
164 | - [SSG](#ssg-2)
165 | - [Pre-Rendering](#pre-rendering-3)
166 |
167 |
168 |
169 |
170 |
171 |
172 | ### React
173 |
174 | #### SSR
175 |
176 | ##### Frameworks
177 |
178 | - [Next.js](https://github.com/zeit/next.js#readme) - The most popular SSR tool.
179 | - [After.js](https://github.com/jaredpalmer/after.js#readme) - Similar to Next.js but with routing based on React Router.
180 | - [React Server](https://github.com/redfin/react-server#readme)
181 | !INLINE ./reframe.md --hide-source-path
182 | - [Fusion.js](https://github.com/fusionjs) - Plugin-based universal web framework maintained by Uber.
183 |
184 | ##### Libraries
185 |
186 | - [Goldpage](https://github.com/reframejs/goldpage) - A do-one-thing-do-it-well library that supports all app types; "SPA", "SSR", "Static Website", etc.
187 | - [Razzle](https://github.com/jaredpalmer/razzle#readme) - Handles the building. You do the rest.
188 | - [React Universal Component](https://github.com/faceyspacey/react-universal-component#readme) - Utility to code split your SSR app.
189 | - [Rogue.js](https://github.com/alidcastano/rogue.js#readme) - SSR utilities focused on flexibility. First-class support for React Router, Apollo GraphQL, Redux, Emotion, and Styled-Components. The build step is up to you (but you can use Razzle.)
190 |
191 | ##### Boilerplates
192 |
193 | - [cra-ssr](https://github.com/cereallarceny/cra-ssr#readme) - SSR app boilerplate based on CRA (without having ejected).
194 |
195 | #### SSG
196 |
197 | - [Gatsby.js](https://github.com/gatsbyjs/gatsby#readme) - SSG based on React and GraphQL.
198 | - [React Static](https://github.com/nozzle/react-static#readme) - SSG based on React and focused on simplicity.
199 | - [Goldpage](https://github.com/reframejs/goldpage) - A do-one-thing-do-it-well library that supports all app types; "SPA", "SSR", "Static Website", etc.
200 | - [Phenomic](https://github.com/phenomic/phenomic#readme) - SSG based on a flexible plugin system.
201 | - [Next.js](https://github.com/zeit/next.js#readme) - Although primarily focused on SSR, Next.js can also generate static sites.
202 | !INLINE ./reframe.md --hide-source-path
203 |
204 | #### Pre-Rendering
205 |
206 | !INLINE ./prerender-dynamic.md --hide-source-path
207 |
208 | !INLINE ./prerender-static.md --hide-source-path
209 | - [React Snapshot](https://github.com/geelen/react-snapshot#readme) - Pre-renders React apps at build-time. Uses `require('react-dom/server').renderToString` to directly render the HTML. Uses JSDOM as headless browser to automatically discover your app's URLs.
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 | ### Vue
218 |
219 | #### SSR
220 |
221 | ##### Frameworks
222 |
223 | - [Nuxt](https://github.com/nuxt/nuxt.js#readme) - Similar to Next.js but for Vue.
224 | !INLINE ./reframe.md --hide-source-path
225 |
226 | ##### Libraries
227 |
228 | - [vue-server-renderer](https://www.npmjs.com/package/vue-server-renderer) - Official library for SSR with Vue.
229 | - [Goldpage](https://github.com/reframejs/goldpage) - A do-one-thing-do-it-well library that supports all app types; "SPA", "SSR", "Static Website", etc.
230 |
231 | #### SSG
232 |
233 | - [Phenomic](https://github.com/phenomic/phenomic#readme) - SSG based on a flexible plugin system.
234 | !INLINE ./reframe.md --hide-source-path
235 |
236 | #### Pre-Rendering
237 |
238 | !INLINE ./prerender-dynamic.md --hide-source-path
239 |
240 | !INLINE ./prerender-static.md --hide-source-path
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 | ### Angular
250 |
251 | #### SSR
252 |
253 | - [Angular Universal](https://github.com/angular/universal#readme) - Official packages for SSR with Angular.
254 |
255 | #### Pre-Rendering
256 |
257 | !INLINE ./prerender-dynamic.md --hide-source-path
258 |
259 | !INLINE ./prerender-static.md --hide-source-path
260 |
261 |
262 |
263 |
264 |
265 |
266 | ### View Library Agnostic
267 |
268 | #### SSG
269 |
270 | - [Phenomic](https://github.com/phenomic/phenomic#readme) - SSG based on a flexible plugin system.
271 | !INLINE ./reframe.md --hide-source-path
272 |
273 | #### Pre-Rendering
274 |
275 | !INLINE ./prerender-dynamic.md --hide-source-path
276 |
277 | !INLINE ./prerender-static.md --hide-source-path
278 |
279 |
--------------------------------------------------------------------------------
/reframe.md:
--------------------------------------------------------------------------------
1 | - [Reframe](https://github.com/reframejs/reframe#readme) - Flexible web framework. It does SSR by default and can be used as SSG.
2 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@brillout/find-package-files@^0.1.0":
6 | version "0.1.1"
7 | resolved "https://registry.yarnpkg.com/@brillout/find-package-files/-/find-package-files-0.1.1.tgz#ee4e971af549b7bd4ab248c88c6b042b37aa4487"
8 | dependencies:
9 | find-up "^2.1.0"
10 | glob-gitignore "^1.0.6"
11 | ignore "^3.3.7"
12 | reassert "^1.1.8"
13 |
14 | "@brillout/format-text@^0.1.0":
15 | version "0.1.1"
16 | resolved "https://registry.yarnpkg.com/@brillout/format-text/-/format-text-0.1.1.tgz#13cd49bf966fc82727c0c62e003fcdc05fb052f8"
17 |
18 | "@brillout/mdocs@^0.1.20":
19 | version "0.1.20"
20 | resolved "https://registry.yarnpkg.com/@brillout/mdocs/-/mdocs-0.1.20.tgz#d04f74139b93876350d8137662a89bf8b756e7ae"
21 | dependencies:
22 | "@brillout/find-package-files" "^0.1.0"
23 | find-up "^2.1.0"
24 | reassert "^1.1.8"
25 |
26 | babel-runtime@^6.26.0:
27 | version "6.26.0"
28 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
29 | dependencies:
30 | core-js "^2.4.0"
31 | regenerator-runtime "^0.11.0"
32 |
33 | balanced-match@^1.0.0:
34 | version "1.0.0"
35 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
36 |
37 | brace-expansion@^1.1.7:
38 | version "1.1.11"
39 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
40 | dependencies:
41 | balanced-match "^1.0.0"
42 | concat-map "0.0.1"
43 |
44 | concat-map@0.0.1:
45 | version "0.0.1"
46 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
47 |
48 | core-js@^2.4.0:
49 | version "2.5.7"
50 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
51 |
52 | find-up@^2.1.0:
53 | version "2.1.0"
54 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
55 | dependencies:
56 | locate-path "^2.0.0"
57 |
58 | fs.realpath@^1.0.0:
59 | version "1.0.0"
60 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
61 |
62 | glob-gitignore@^1.0.6:
63 | version "1.0.6"
64 | resolved "https://registry.yarnpkg.com/glob-gitignore/-/glob-gitignore-1.0.6.tgz#70e3554a257f1381df22ec56c77fe88075930d3a"
65 | dependencies:
66 | babel-runtime "^6.26.0"
67 | glob "^7.1.2"
68 | ignore "^3.3.7"
69 | lodash.difference "^4.5.0"
70 | lodash.union "^4.6.0"
71 | make-array "^1.0.2"
72 | util.inherits "^1.0.3"
73 |
74 | glob@^7.1.2:
75 | version "7.1.2"
76 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
77 | dependencies:
78 | fs.realpath "^1.0.0"
79 | inflight "^1.0.4"
80 | inherits "2"
81 | minimatch "^3.0.4"
82 | once "^1.3.0"
83 | path-is-absolute "^1.0.0"
84 |
85 | ignore@^3.3.7:
86 | version "3.3.10"
87 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
88 |
89 | inflight@^1.0.4:
90 | version "1.0.6"
91 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
92 | dependencies:
93 | once "^1.3.0"
94 | wrappy "1"
95 |
96 | inherits@2:
97 | version "2.0.3"
98 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
99 |
100 | locate-path@^2.0.0:
101 | version "2.0.0"
102 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
103 | dependencies:
104 | p-locate "^2.0.0"
105 | path-exists "^3.0.0"
106 |
107 | lodash.difference@^4.5.0:
108 | version "4.5.0"
109 | resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
110 |
111 | lodash.union@^4.6.0:
112 | version "4.6.0"
113 | resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
114 |
115 | make-array@^1.0.2:
116 | version "1.0.5"
117 | resolved "https://registry.yarnpkg.com/make-array/-/make-array-1.0.5.tgz#326a7635c756a9f61ce0b2a6fdd5cc3460419bcb"
118 |
119 | minimatch@^3.0.4:
120 | version "3.0.4"
121 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
122 | dependencies:
123 | brace-expansion "^1.1.7"
124 |
125 | once@^1.3.0:
126 | version "1.4.0"
127 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
128 | dependencies:
129 | wrappy "1"
130 |
131 | p-limit@^1.1.0:
132 | version "1.3.0"
133 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
134 | dependencies:
135 | p-try "^1.0.0"
136 |
137 | p-locate@^2.0.0:
138 | version "2.0.0"
139 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
140 | dependencies:
141 | p-limit "^1.1.0"
142 |
143 | p-try@^1.0.0:
144 | version "1.0.0"
145 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
146 |
147 | path-exists@^3.0.0:
148 | version "3.0.0"
149 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
150 |
151 | path-is-absolute@^1.0.0:
152 | version "1.0.1"
153 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
154 |
155 | reassert@^1.1.8:
156 | version "1.1.13"
157 | resolved "https://registry.yarnpkg.com/reassert/-/reassert-1.1.13.tgz#0c65d70a80310ae63e172bef1781b714fa3906d6"
158 | dependencies:
159 | "@brillout/format-text" "^0.1.0"
160 |
161 | regenerator-runtime@^0.11.0:
162 | version "0.11.1"
163 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
164 |
165 | util.inherits@^1.0.3:
166 | version "1.0.3"
167 | resolved "https://registry.yarnpkg.com/util.inherits/-/util.inherits-1.0.3.tgz#a9c626a0d06d34829d47ba56cab1278d745f9ce6"
168 |
169 | wrappy@1:
170 | version "1.0.2"
171 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
172 |
--------------------------------------------------------------------------------