Use Synchronous Data Fetching to Speed Up My Gallery Page

Use Synchronous Data Fetching to Speed Up My Gallery Page

I have a gallery page in my blog directory, hosted by Plesk. Built from vite + react boilerplate.

Why

Before this, my gallery page works like this:

It’s a SPA, so runtime files need to load and initiate first. When page document was downloaded and parsed, the browser started loading <link> files and after needed JavaScript files were downloaded and executed.

I have the data fetching logic like this:

index.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const [list, setList] = useState([]);
const [loaded, setLoaded] = useState(false);

const getData = async () => {
const response = await (
await fetch("https://api.lynan.cn/gallery-list")
).json();
const data = response.data.list;
setList(data);
setLoaded(true);
};

useEffect(() => {
getData();
}, []);

This process could take a lot of time (due to the very limited resources the CMS service can use).

Besides, I want to make minimum adjustments to make it faster.

How

To address this issue and improve the performance of the gallery page, I made the following adjustments:

  1. Generated a static JSON data file to store the photos data. This file is created or updated whenever a CRUD operation happened.
src/api/photo/content-types/photo/lifecycles.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const generateJSON = async () => {
try {
const list = await strapi.db.query("api::photo.photo").findMany({
orderBy: { id: "desc" },
});
fs.writeFileSync(
"./public/photos.js",
`var photos = ${JSON.stringify(list)}`
);
} catch (error) {}
};

module.exports = {
afterUpdate(event) {
generateJSON();
},
afterCreate(event) {
generateJSON();
},
};
  1. Loaded the JSON file using a <script> tag in the HTML head, making the data easily accessible as a global variable on the window object.
index.html
1
2
3
4
<head>
...
<script src="https://nextcms.lynan.cn/public/photos.js"></script>
</head>
  1. Updated the data fetching logic in the React component to directly use the referenced JSON data.
index.jsx
1
const [list, setList] = useState(window.photos || []);

By implementing these adjustments, the need for the getData function and useEffect hook was eliminated, resulting in a noticeable improvement in the page loading speed. Additionally, the gallery page can now still be hosted by a static files server (like NGINX) without requiring an extra runtime environment (like Node.js).

Why Not

use JSON-P

JSONP, or JSON-P (JSON with Padding), is a historical JavaScript technique for requesting data by loading a <script> element, which is an element intended to load ordinary JavaScript.

To use JSON-P, we need to wrap our data into a callback function, and declare our callback function before loading the data file.

index.html
1
2
3
4
5
6
<script>
function fetchDataCallback(data) {
console.log(data);
}
</script>
<script src="https://api.lynan.cn/test-jsonp.js"></script>
testjsonp.js
1
2
3
4
5
6
fetchDataCallback([
{
id: 182,
title: null,
},
]);

It’s no better than just putting the data into a global variable in this case.

use SSR

Follow the guide from next.js, then we still need a Node.js environment to run next.js service.

use SSG

We can also use next.js to do SSG (Static Site Generation). Use getStaticProps to insert data into a page template.

We need to rebuild static files when data updates.

To use SSR or SSG both require some extra modifications on the gallery project, so they are not my first consideration. But in different cases, SSR/SSG might be a good option.

And

Potential Disadvantages

It’s important to note that the approach of using a global variable to store the data may expose the data file and could potentially lead to a security risk.

Conclusion

The adjustments made to optimize the gallery page have significantly improved its performance, and while the alternative approaches seems not so good for me, the current solution works great.

Use Synchronous Data Fetching to Speed Up My Gallery Page

https://lynan.cn/synchronous-data-fetching-practice/

Author

Lynan

Posted on

2024-01-10

Updated on

2024-02-21

Licensed under

Comments