Skip to main content

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)