initial commit
- ID
b28df68- date
2022-09-04 00:47:29+00:00- author
Alex Chan <alex@alexwlchan.net>- parent
fb9072a- message
initial commit- changed files
3 files, 76 additions
Changed files
.gitignore (0) → .gitignore (5)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c1d18d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+_out
README.md (0) → README.md (1463)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0797a5e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# nextjs-pageweight-analyser
+
+This is a simple script I wrote for analysing page weight of a site built using [Next.js], which I what I use [at work].
+
+When we use Next.js, we send data to the page using [getServerSideProps].
+These props get rendered as JSON and stuffed inside a `<script>` tag, like so:
+
+```html
+<!DOCTYPE html>
+<html lang="en" class="is-keyboard">
+ <body>
+ ...
+ <!--
+ This includes `getServerSideProps` in the `pageProps` key.
+ -->
+ <script id="__NEXT_DATA__" type="application/json">
+ {"props":{"pageProps":{"now":"2022-09-04T00:39:10.494Z"},"__N_SSP":true},"page":"/now","query":{},"buildId":"development","runtimeConfig":{"apmConfig":{"serviceName":"content-webapp","active":true,"centralConfig":true}},"isFallback":false,"gssp":true,"customServer":true,"appGip":true,"scriptLoader":[]}
+ </script>
+ </body>
+</html>
+```
+
+Sending unnecessary data in these props can bloat the size of the page.
+
+This script:
+
+* fetches the page
+* reports the size of the HTML and the `__NEXT_DATA__` specifically
+* saves the `__NEXT_DATA__` to a pretty-printed JSON file for easy analysis
+
+I use this script to analyse the props, to identity ways we can reduce the size of the Next.js data, and to measure the impact of changes.
+
+[Next.js]: https://nextjs.org
+[at work]: https://github.com/wellcomecollection/wellcomecollection.org
+[getServerSideProps]: https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props
measure.py (0) → measure.py (1235)
diff --git a/measure.py b/measure.py
new file mode 100755
index 0000000..aeaa733
--- /dev/null
+++ b/measure.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+import urllib.request
+
+
+def naturalsize(bytes):
+ return "%.2f kB" % (bytes / 1024)
+
+
+def analyse(*, url, name):
+ os.makedirs("_out", exist_ok=True)
+ urllib.request.urlretrieve(url, f"_out/{name}.html")
+
+ html = open(f"_out/{name}.html").read()
+
+ next_data = html.split('<script id="__NEXT_DATA__" type="application/json">')[
+ 1
+ ].split("</script>")[0]
+
+ with open(f'_out/{name}.json', 'w') as outfile:
+ outfile.write(json.dumps(next_data, indent=2, sort_keys=True))
+
+ print(url, name)
+ print(f"html = {naturalsize(len(html))}")
+ print(f"next_data = {naturalsize(len(next_data))}")
+ print("")
+
+
+if __name__ == "__main__":
+ for url, name in [
+ ("http://localhost:3000/stories", "stories"),
+ ("http://localhost:3000/", "homepage"),
+ ("http://localhost:3000/articles/Yp3GthEAACIAwRi9", "article"),
+ # ("http://localhost:3000/whats-on", "whats-on"),
+ # ("http://localhost:3000/works", "works"),
+ # ("http://localhost:3000/images", "images"),
+ # ("http://localhost:3000/works/a222wwjt", "a222wwjt"),
+ # ("http://localhost:3000/works?query=fish", "search-fish"),
+ ]:
+ analyse(url=url, name=name)