Skip to content

Commit 694a644

Browse files
WebServer: serve gzipped HTML to reduce total build size by 60KiB
1 parent 1061347 commit 694a644

6 files changed

Lines changed: 75 additions & 89 deletions

File tree

internal_filesystem/builtin/html/webrepl_inlined_minified.html

Lines changed: 0 additions & 52 deletions
This file was deleted.
Binary file not shown.

internal_filesystem/lib/mpos/webserver/webrepl_http.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from mpos.ui.display_metrics import DisplayMetrics
1212

13-
WEBREPL_HTML_PATH = "builtin/html/webrepl_inlined_minified.html" # built by MicroPythonOS/webrepl/inline_minify_webrepl.py
13+
WEBREPL_HTML_PATH = "builtin/html/webrepl_inlined_minified.html.gz" # built by MicroPythonOS/webrepl/inline_minify_webrepl.py
1414

1515
WEBREPL_ASSETS = {
1616
b"/": (WEBREPL_HTML_PATH, b"text/html"),
@@ -63,10 +63,13 @@ def _is_websocket_request(headers):
6363
return b"upgrade" in connection and upgrade == b"websocket"
6464

6565

66-
def _send_response(cl, status, content_type, body):
66+
def _send_response(cl, status, content_type, body, extra_headers=None):
6767
cl.send(b"HTTP/1.0 " + status + b"\r\n")
6868
cl.send(b"Server: MicroPythonOS\r\n")
6969
cl.send(b"Content-Type: " + content_type + b"\r\n")
70+
if extra_headers:
71+
for header in extra_headers:
72+
cl.send(header + b"\r\n")
7073
cl.send(b"Content-Length: %d\r\n\r\n" % len(body))
7174
cl.send(body)
7275
cl.close()
@@ -122,15 +125,15 @@ def _snapshot_to_bmp():
122125
return bmp
123126

124127

125-
def _send_file_response(cl, path, content_type):
128+
def _send_file_response(cl, path, content_type, extra_headers=None):
126129
try:
127130
with open(path, "rb") as handle:
128131
body = handle.read()
129132
except OSError:
130133
_send_response(cl, b"404 Not Found", b"text/plain", b"Not Found")
131134
return False
132135

133-
_send_response(cl, b"200 OK", content_type, body)
136+
_send_response(cl, b"200 OK", content_type, body, extra_headers=extra_headers)
134137
return False
135138

136139

@@ -165,7 +168,10 @@ def accept_handler(listen_sock):
165168

166169
if path in WEBREPL_ASSETS:
167170
asset_path, content_type = WEBREPL_ASSETS[path]
168-
return _send_file_response(cl, asset_path, content_type)
171+
extra_headers = None
172+
if asset_path.endswith(".gz"):
173+
extra_headers = [b"Content-Encoding: gzip"]
174+
return _send_file_response(cl, asset_path, content_type, extra_headers=extra_headers)
169175

170176
if path == b"/screenshot.bmp":
171177
bmp = _snapshot_to_bmp()

scripts/build_mpos.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ result=$0
116116
if [ $? -ne 0 ]; then
117117
echo "ERROR: webrepl/inline_minify_webrepl.py failed with exit code $result, webrepl won't work"
118118
else
119-
mv webrepl_inlined_minified.html ../internal_filesystem/builtin/html/
119+
mv webrepl_inlined_minified.html.gz ../internal_filesystem/builtin/html/
120120
fi
121121
popd
122122

webrepl/inline_minify_webrepl.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/usr/bin/env python3
2-
"""Minify and inline WebREPL assets into webrepl_inlined_minified.html."""
2+
"""Minify and inline WebREPL assets into webrepl_inlined_minified.html.gz."""
33
from __future__ import annotations
44

5+
import gzip
56
import re
67
from pathlib import Path
78

@@ -122,7 +123,7 @@ def cssmin(css: str) -> str:
122123
def inline_assets() -> None:
123124
base_dir = Path(__file__).parent
124125
html_path = base_dir / "webrepl.html"
125-
out_path = base_dir / "webrepl_inlined_minified.html"
126+
out_path = base_dir / "webrepl_inlined_minified.html.gz"
126127

127128
html = html_path.read_text(encoding="utf-8")
128129
css = cssmin((base_dir / "webrepl.css").read_text(encoding="utf-8"))
@@ -152,7 +153,8 @@ def inline_assets() -> None:
152153
)
153154
html = new_html
154155

155-
out_path.write_text(html, encoding="utf-8")
156+
with gzip.open(out_path, "wt", encoding="utf-8") as gzip_file:
157+
gzip_file.write(html)
156158

157159

158160
if __name__ == "__main__":

webrepl/webrepl_tweaks.js

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,43 @@
11
// Set terminal height dynamically, without modifying webrepl.js
22
(function() {
3-
var maxReadyAttempts = 90;
3+
var maxReadyAttempts = 60;
44
var readyAttempts = 0;
5-
var resizeScheduled = false;
65
var resizeDebounce = null;
76

87
function get_term_container() {
9-
return document.getElementById('term');
8+
return document.getElementById("term");
109
}
1110

12-
// Wrapper keeps a fixed height; rows are derived from its rendered height.
1311
function get_term_wrapper() {
14-
return document.getElementById('term-wrapper') || get_term_container();
12+
return document.getElementById("term-wrapper") || get_term_container();
1513
}
1614

17-
// Compute rows once on load/resize using wrapper height and terminal padding.
18-
function calculate_dynamic_rows() {
15+
function log_debug(message, data) {
16+
if (data) {
17+
console.debug("[webrepl_tweaks] " + message, data);
18+
return;
19+
}
20+
console.debug("[webrepl_tweaks] " + message);
21+
}
22+
23+
function get_cell_height(term) {
24+
var core = term && term._core && term._core._renderService;
25+
var dimensions = core && core.dimensions;
26+
var cellHeight = dimensions && dimensions.actualCellHeight;
27+
if (cellHeight) {
28+
return cellHeight;
29+
}
30+
return 16;
31+
}
32+
33+
function calculate_dynamic_rows(term) {
1934
var wrapper = get_term_wrapper();
2035
var termContainer = get_term_container();
2136
if (!wrapper || !termContainer) {
37+
log_debug("missing wrapper or term container", {
38+
wrapper: !!wrapper,
39+
termContainer: !!termContainer
40+
});
2241
return null;
2342
}
2443
var rect = wrapper.getBoundingClientRect();
@@ -27,65 +46,76 @@
2746
var paddingTop = parseFloat(style.paddingTop) || 0;
2847
var paddingBottom = parseFloat(style.paddingBottom) || 0;
2948
var contentHeight = height - paddingTop - paddingBottom;
30-
return Math.max(24, Math.min(80, (contentHeight - 20) / 12)) | 0;
49+
var cellHeight = get_cell_height(term);
50+
var rows = Math.floor(contentHeight / cellHeight) - 2;
51+
log_debug("row calculation", {
52+
wrapperHeight: height,
53+
paddingTop: paddingTop,
54+
paddingBottom: paddingBottom,
55+
contentHeight: contentHeight,
56+
cellHeight: cellHeight,
57+
calculatedRows: rows,
58+
safetyRows: 2
59+
});
60+
if (!rows || rows < 2) {
61+
return null;
62+
}
63+
return rows;
3164
}
3265

3366
function resize_term_rows() {
3467
if (!window.term || !window.term.resize) {
68+
log_debug("term not ready");
3569
return false;
3670
}
37-
var rows = calculate_dynamic_rows();
71+
var rows = calculate_dynamic_rows(window.term);
3872
if (rows === null) {
73+
log_debug("skip resize (rows null)");
3974
return false;
4075
}
4176
var cols = window.term.cols || 80;
4277
if (window.term.rows !== rows) {
78+
log_debug("resize term", { cols: cols, rows: rows });
4379
window.term.resize(cols, rows);
80+
} else {
81+
log_debug("rows unchanged", { rows: rows });
4482
}
4583
return true;
4684
}
4785

48-
function schedule_resize() {
49-
if (resizeScheduled) {
50-
return;
51-
}
52-
resizeScheduled = true;
53-
window.requestAnimationFrame(function() {
54-
resizeScheduled = false;
55-
resize_term_rows();
56-
});
57-
}
58-
59-
function schedule_resize_debounced() {
86+
function schedule_resize_debounced(reason) {
6087
if (resizeDebounce) {
6188
window.clearTimeout(resizeDebounce);
6289
}
6390
resizeDebounce = window.setTimeout(function() {
6491
resizeDebounce = null;
65-
schedule_resize();
66-
}, 80);
92+
log_debug("resize tick", { reason: reason || "unknown" });
93+
resize_term_rows();
94+
}, 100);
6795
}
6896

6997
function wait_for_term_ready() {
7098
if (window.term && window.term.resize) {
71-
schedule_resize_debounced();
99+
schedule_resize_debounced("term-ready");
72100
if (resize_term_rows()) {
73101
return;
74102
}
75103
}
76104
if (readyAttempts >= maxReadyAttempts) {
105+
log_debug("giving up waiting for term");
77106
return;
78107
}
79108
readyAttempts += 1;
80109
window.requestAnimationFrame(wait_for_term_ready);
81110
}
82111

83-
window.addEventListener('load', function() {
112+
window.addEventListener("load", function() {
113+
log_debug("window load");
84114
wait_for_term_ready();
85-
schedule_resize_debounced();
115+
schedule_resize_debounced("load");
86116
});
87117

88-
window.addEventListener('resize', function() {
89-
schedule_resize_debounced();
118+
window.addEventListener("resize", function() {
119+
schedule_resize_debounced("window-resize");
90120
});
91121
}).call(this);

0 commit comments

Comments
 (0)