From d1b5567007acb141435d9a82969b2785c1461cfd Mon Sep 17 00:00:00 2001
From: Kewal Rathod <43823249+Kewal89@users.noreply.github.com>
Date: Sat, 19 Nov 2022 13:44:23 +0530
Subject: [PATCH 1/8] feat: Added Support For URL Parameters for A/B Testing.
---
index.js | 19 ++++++++++---------
utils/normalizeRspOptions.js | 1 +
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/index.js b/index.js
index 5b8e180..74c9c09 100644
--- a/index.js
+++ b/index.js
@@ -28,7 +28,7 @@ async function readOptionsFromFile() {
* @param {string} dir
* @returns {string|boolean}
*/
-async function runStaticServer(port, routes, dir) {
+async function runStaticServer(port, routes, params, dir) {
try {
app = express();
const resolvedPath = resolve(dir);
@@ -41,7 +41,7 @@ async function runStaticServer(port, routes, dir) {
await app.listen(port);
return `http://localhost:${port}`;
- } catch(err) {
+ } catch (err) {
throw new Error(`Error: Failed to run puppeteer server on port ${port}.\nMessage: ${err}`);
}
}
@@ -61,7 +61,7 @@ async function createNewHTMLPage(route, html, dir) {
const fileName = getValidatedFileName(route);
- await fs.writeFileSync(`${dir}${fileName}`, html, {encoding: 'utf-8', flag: 'w'});
+ await fs.writeFileSync(`${dir}${fileName}`, html, { encoding: 'utf-8', flag: 'w' });
console.log(`Created ${fileName}`);
} catch (err) {
throw new Error(`Error: Failed to create HTML page for ${route}.\nMessage: ${err}`);
@@ -78,13 +78,13 @@ async function getHTMLfromPuppeteerPage(browser, pageUrl, options) {
try {
const page = await browser.newPage();
- await page.goto(pageUrl, Object.assign({waitUntil: 'networkidle0'}, options));
+ await page.goto(pageUrl, Object.assign({ waitUntil: 'networkidle0' }, options));
const html = await page.content();
if (!html) return 0;
return html;
- } catch(err) {
+ } catch (err) {
throw new Error(`Error: Failed to build HTML for ${pageUrl}.\nMessage: ${err}`);
}
}
@@ -96,12 +96,13 @@ async function getHTMLfromPuppeteerPage(browser, pageUrl, options) {
* @param {object} engine
* @returns {number|undefined}
*/
-async function runPuppeteer(baseUrl, routes, dir, engine) {
+async function runPuppeteer(baseUrl, routes, params, dir, engine) {
const browser = await puppeteer.launch(engine.launchOptions);
for (let i = 0; i < routes.length; i++) {
try {
console.log(`Processing route "${routes[i]}"`);
- const html = await getHTMLfromPuppeteerPage(browser, `${baseUrl}${routes[i]}`, engine.gotoOptions);
+ const parameters = params[i] || "";
+ const html = await getHTMLfromPuppeteerPage(browser, `${baseUrl}${routes[i]}${parameters}`, engine.gotoOptions);
if (html) createNewHTMLPage(routes[i], html, dir);
else return 0;
} catch (err) {
@@ -115,11 +116,11 @@ async function runPuppeteer(baseUrl, routes, dir, engine) {
async function run(config) {
const options = config || await readOptionsFromFile();
- const staticServerURL = await runStaticServer(options.port, options.routes, options.buildDirectory);
+ const staticServerURL = await runStaticServer(options.port, options.routes, options.urlParameter, options.buildDirectory);
if (!staticServerURL) return 0;
- await runPuppeteer(staticServerURL, options.routes, options.buildDirectory, options.engine);
+ await runPuppeteer(staticServerURL, options.routes, options.urlParameter, options.buildDirectory, options.engine);
console.log('Finish react-spa-prerender tasks!');
process.exit();
}
diff --git a/utils/normalizeRspOptions.js b/utils/normalizeRspOptions.js
index 9b9ff06..76a321e 100644
--- a/utils/normalizeRspOptions.js
+++ b/utils/normalizeRspOptions.js
@@ -11,6 +11,7 @@ module.exports = function (options) {
return {
routes: options.routes || [],
+ urlParameter: options.urlParameter || [],
port: options.port || 3000,
buildDirectory: options.buildDirectory || './build',
engine
From 390a77d5fd64b77483367cbe537d2d66b58c26ca Mon Sep 17 00:00:00 2001
From: Kewal Rathod <43823249+Kewal89@users.noreply.github.com>
Date: Sat, 19 Nov 2022 13:49:22 +0530
Subject: [PATCH 2/8] update: Bumped Version to Alpha2.
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 190679d..1185284 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-spa-prerender",
- "version": "1.0.14",
+ "version": "1.0.15.alpha2",
"description": "React library for prerendering static pages, optimize SEO and web performance",
"main": "index.js",
"scripts": {
From 1b8a59a28b9804a85bab1ac3586e20e4c1aa79fb Mon Sep 17 00:00:00 2001
From: Kewal Rathod <43823249+Kewal89@users.noreply.github.com>
Date: Sat, 19 Nov 2022 13:53:09 +0530
Subject: [PATCH 3/8] fix: Incorrect Package Name.
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 1185284..56817b9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-spa-prerender",
- "version": "1.0.15.alpha2",
+ "version": "1.0.15",
"description": "React library for prerendering static pages, optimize SEO and web performance",
"main": "index.js",
"scripts": {
From 1079385b801378b194962d36b7c15c18e0edf612 Mon Sep 17 00:00:00 2001
From: Kewal Rathod <43823249+Kewal89@users.noreply.github.com>
Date: Sat, 19 Nov 2022 14:22:28 +0530
Subject: [PATCH 4/8] update: URL Parameter Options in Document.
---
README.md | 56 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 40 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 4d4d795..c891380 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,36 @@
# react-spa-prerender
+
The easiest way to prerender static pages, optimize SEO and build high performance for your React SPA.
Build production-ready code just by adding few lines of code.
-* [Example of usage with create-react-app](https://github.com/sPavl0v/react-spa-prenderer/tree/master/examples/cra)
-* [create-react-app + lazy loading](https://github.com/sPavl0v/react-spa-prenderer/tree/master/examples/cra-lazy)
+
+- [Example of usage with create-react-app](https://github.com/sPavl0v/react-spa-prenderer/tree/master/examples/cra)
+- [create-react-app + lazy loading](https://github.com/sPavl0v/react-spa-prenderer/tree/master/examples/cra-lazy)
### Upcoming features
-* Auto sitemap generation
-* Prebuilding pages with dynamic routes
+
+- Auto sitemap generation
+- Prebuilding pages with dynamic routes
Follow the steps below:
## Install
+
With npm
+
```
npm install react-spa-prerender --save-dev
```
+
With yarn
+
```
yarn add react-spa-prerender --dev
```
## Add as postbuild script
+
In your package.json add the following in the scripts section:
+
```
"scripts": {
"postbuild": "react-spa-prerender",
@@ -29,9 +38,11 @@ In your package.json add the following in the scripts section:
```
## Add .rsp.json file
-__.rsp.json__ is the configuration file for `react-spa-prerender`. Create this file in your __application root folder__.
-The minimum configuration requires the __routes__ you want to be parsed.
+
+**.rsp.json** is the configuration file for `react-spa-prerender`. Create this file in your **application root folder**.
+The minimum configuration requires the **routes** you want to be parsed.
Example:
+
```
{
routes: [
@@ -43,6 +54,7 @@ Example:
]
}
```
+
From example above:
Your "/" route will transform into "index.html" page.
"/about" -> "about.html"
@@ -50,17 +62,21 @@ Your "/" route will transform into "index.html" page.
"/blog/article1" -> create blog directory with file "article1.html" ("/blog/article1.html")
and so on...
-__The rest of the .rsp.json options described below__
+**The rest of the .rsp.json options described below**
## Add ReactDOM.hydrate in your index.js
+
In your index.js(main app file) change the ReactDOM.render logic:
+
```
import ReactDOM from 'react-dom';
const rootElement = document.getElementById("root");
ReactDOM.render(, rootElement);
```
+
Into following:
+
```
import ReactDOM from 'react-dom';
@@ -74,24 +90,26 @@ if (rootElement.hasChildNodes()) {
```
## Voila!!!
+
That's it. After accomplishing all the steps above, run you build command and your prerendered files will be in your build directory.
## .rsp.json Options
-|option | type | default | description |
-|-----|--------|------|---------|
-| routes(Required) | Array | - | An array of routes you want to parse and prerender into static html|
-| port | Number | 3000 | port where prerendering server will be starting |
-| buildDirectory | String | './build' | a relative path to your build folder
-|engine | Object | {} | params for Puppeteer engine, list of available params described below
-
+| option | type | default | description |
+| ---------------------- | ------ | --------- | --------------------------------------------------------------------- |
+| routes(Required) | Array | - | An array of routes you want to parse and prerender into static html |
+| urlParameter(Optional) | Array | - | An array of URL Parameter you want to pass along with Route |
+| port | Number | 3000 | port where prerendering server will be starting |
+| buildDirectory | String | './build' | a relative path to your build folder |
+| engine | Object | {} | params for Puppeteer engine, list of available params described below |
### Engine options:
+
- launchOptions - object, containing properties to control **puppeteer.launch()** command. The whole list of available properties available here: [https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-puppeteerlaunchoptions](https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-puppeteerlaunchoptions)
- gotoOptions - object, navigation parameters. The whole list of available properties available here: [https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-pagegotourl-options](https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-pagegotourl-options)
-
#### Example of .rsp.json with engine options:
+
```
{
"port": 3000,
@@ -113,6 +131,12 @@ That's it. After accomplishing all the steps above, run you build command and yo
"/services",
"/blog/article1",
"/blog/article2"
+ ],
+ "urlParameter": [
+ "?type=a",
+ "?type=b",
+ "",
+ "?demo=yes"
]
}
-```
\ No newline at end of file
+```
From 51cc34e5a0f1cafaea4fc3ef99034aa0549a4abd Mon Sep 17 00:00:00 2001
From: Kewal Rathod <43823249+Kewal89@users.noreply.github.com>
Date: Sat, 19 Nov 2022 15:00:01 +0530
Subject: [PATCH 5/8] docs: Added Multi Parameter Example.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c891380..bd7c020 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ That's it. After accomplishing all the steps above, run you build command and yo
"?type=a",
"?type=b",
"",
- "?demo=yes"
+ "?demo=yes&tester=yes"
]
}
```
From 6e21072b199ce2292ec400480b8d0c0edc73add4 Mon Sep 17 00:00:00 2001
From: Kewal Rathod <43823249+Kewal89@users.noreply.github.com>
Date: Sat, 19 Nov 2022 15:01:39 +0530
Subject: [PATCH 6/8] feat: Exception for Incorrect URL Parameters.
---
index.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/index.js b/index.js
index 74c9c09..c3abf3d 100644
--- a/index.js
+++ b/index.js
@@ -96,17 +96,19 @@ async function getHTMLfromPuppeteerPage(browser, pageUrl, options) {
* @param {object} engine
* @returns {number|undefined}
*/
-async function runPuppeteer(baseUrl, routes, params, dir, engine) {
+ async function runPuppeteer(baseUrl, routes, params, dir, engine) {
const browser = await puppeteer.launch(engine.launchOptions);
for (let i = 0; i < routes.length; i++) {
+ const parameters = params[i] || "";
+ console.log(`Processing route "${routes[i]}${parameters}"`);
+ if (parameters && !parameters.startsWith("?")) throw new Error(`Error: Failed to process parameters "${routes[i]}${parameters}"\nMessage: URL Parameters can be blank or must start with "?"`);
+
try {
- console.log(`Processing route "${routes[i]}"`);
- const parameters = params[i] || "";
const html = await getHTMLfromPuppeteerPage(browser, `${baseUrl}${routes[i]}${parameters}`, engine.gotoOptions);
if (html) createNewHTMLPage(routes[i], html, dir);
else return 0;
} catch (err) {
- throw new Error(`Error: Failed to process route "${routes[i]}"\nMessage: ${err}`);
+ throw new Error(`Error: Failed to process route "${routes[i]}${parameters}"\nMessage: ${err}`);
}
}
From 0be62c33d549d50b315a4e361aa99d84a2525eb7 Mon Sep 17 00:00:00 2001
From: Kewal Rathod
Date: Sat, 7 Jan 2023 15:14:06 +0530
Subject: [PATCH 7/8] BREAKING CHANGE: Updated prop name to "urlParameters"
* Added Additional 's' to maintain naming convention.
---
README.md | 4 ++--
index.js | 4 ++--
utils/normalizeRspOptions.js | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index bd7c020..2a71a2b 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ That's it. After accomplishing all the steps above, run you build command and yo
| option | type | default | description |
| ---------------------- | ------ | --------- | --------------------------------------------------------------------- |
| routes(Required) | Array | - | An array of routes you want to parse and prerender into static html |
-| urlParameter(Optional) | Array | - | An array of URL Parameter you want to pass along with Route |
+| urlParameters(Optional) | Array | - | An array of URL Parameter you want to pass along with Route |
| port | Number | 3000 | port where prerendering server will be starting |
| buildDirectory | String | './build' | a relative path to your build folder |
| engine | Object | {} | params for Puppeteer engine, list of available params described below |
@@ -132,7 +132,7 @@ That's it. After accomplishing all the steps above, run you build command and yo
"/blog/article1",
"/blog/article2"
],
- "urlParameter": [
+ "urlParameters": [
"?type=a",
"?type=b",
"",
diff --git a/index.js b/index.js
index c3abf3d..f961289 100644
--- a/index.js
+++ b/index.js
@@ -118,11 +118,11 @@ async function getHTMLfromPuppeteerPage(browser, pageUrl, options) {
async function run(config) {
const options = config || await readOptionsFromFile();
- const staticServerURL = await runStaticServer(options.port, options.routes, options.urlParameter, options.buildDirectory);
+ const staticServerURL = await runStaticServer(options.port, options.routes, options.urlParameters, options.buildDirectory);
if (!staticServerURL) return 0;
- await runPuppeteer(staticServerURL, options.routes, options.urlParameter, options.buildDirectory, options.engine);
+ await runPuppeteer(staticServerURL, options.routes, options.urlParameters, options.buildDirectory, options.engine);
console.log('Finish react-spa-prerender tasks!');
process.exit();
}
diff --git a/utils/normalizeRspOptions.js b/utils/normalizeRspOptions.js
index 76a321e..b7f61ae 100644
--- a/utils/normalizeRspOptions.js
+++ b/utils/normalizeRspOptions.js
@@ -11,7 +11,7 @@ module.exports = function (options) {
return {
routes: options.routes || [],
- urlParameter: options.urlParameter || [],
+ urlParameters: options.urlParameters || [],
port: options.port || 3000,
buildDirectory: options.buildDirectory || './build',
engine
From 95521f19f85921b3561a7720ba2d30f884aac073 Mon Sep 17 00:00:00 2001
From: Kewal Rathod
Date: Sat, 7 Jan 2023 15:16:15 +0530
Subject: [PATCH 8/8] docs: Reformatted README.md.
---
README.md | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index 2a71a2b..3ca9d94 100644
--- a/README.md
+++ b/README.md
@@ -95,13 +95,13 @@ That's it. After accomplishing all the steps above, run you build command and yo
## .rsp.json Options
-| option | type | default | description |
-| ---------------------- | ------ | --------- | --------------------------------------------------------------------- |
-| routes(Required) | Array | - | An array of routes you want to parse and prerender into static html |
+| option | type | default | description |
+| ----------------------- | ------ | --------- | --------------------------------------------------------------------- |
+| routes(Required) | Array | - | An array of routes you want to parse and prerender into static html |
| urlParameters(Optional) | Array | - | An array of URL Parameter you want to pass along with Route |
-| port | Number | 3000 | port where prerendering server will be starting |
-| buildDirectory | String | './build' | a relative path to your build folder |
-| engine | Object | {} | params for Puppeteer engine, list of available params described below |
+| port | Number | 3000 | port where prerendering server will be starting |
+| buildDirectory | String | './build' | a relative path to your build folder |
+| engine | Object | {} | params for Puppeteer engine, list of available params described below |
### Engine options: