diff --git a/docker/appserver/entrypoint-appserver.sh b/docker/appserver/entrypoint-appserver.sh index a641cdd19..6b278bcd2 100644 --- a/docker/appserver/entrypoint-appserver.sh +++ b/docker/appserver/entrypoint-appserver.sh @@ -53,6 +53,31 @@ echo "Starting background tasks..." python src/manage.py compress -v0 --force --traceback echo " [bg] compress done." + # Prekompresja gzip wyjscia django-compressora ($STATIC_ROOT/CACHE, + # patrz COMPRESS_ROOT + COMPRESS_OUTPUT_DIR w settings/base.py). + # Reszta staticow ma `.gz` juz w obrazie (R16 w docker/bpp_base/Dockerfile), + # ale CACHE/ powstaje DOPIERO TERAZ, w runtime — build-time go nie widzial. + # To realny ruch: bare.html pakuje bundle.js (786 KB) w {% compress js %}, + # wiec przegladarka pobiera CACHE/js/output..js, a nie plik z .baked. + # + # Nieaktualny `.gz` nie grozi: compressor nazywa wyjscie content-hashem, + # wiec zmiana tresci = nowa nazwa pliku, a nie nadpisanie starej. + # + # Bledu NIE eskalujemy (skrypt leci z `sh -e`) — brak `.gz` degraduje sie + # miekko do `gzip on` w locie, a to nie powod, zeby nie wstal serwis. + # Logujemy za to glosno, bo inaczej regresja byla by niewidoczna. + if [ -d "$STATIC_ROOT/CACHE" ]; then + echo " [bg] gzip CACHE..." + if find "$STATIC_ROOT/CACHE" -type f -size +1000c \ + \( -name '*.js' -o -name '*.css' \) \ + -exec gzip -9 -k -f {} +; then + echo " [bg] gzip CACHE done." + else + echo " [bg] UWAGA: prekompresja CACHE nie powiodla sie —" + echo " [bg] nginx spadnie na gzip w locie (wolniej, ale dziala)." + fi + fi + echo " [bg] generate_500_page..." python src/manage.py generate_500_page echo " [bg] generate_500_page done." diff --git a/docker/bpp_base/Dockerfile b/docker/bpp_base/Dockerfile index a4fd72d8d..7c0117c86 100644 --- a/docker/bpp_base/Dockerfile +++ b/docker/bpp_base/Dockerfile @@ -174,6 +174,37 @@ RUN DJANGO_BPP_SECRET_KEY=build-time-only-not-used \ --noinput -v0 --traceback \ --ignore sinon --ignore qunit --ignore '*.map' +# R16: prekompresja gzip dla `gzip_static on` po stronie nginksa (bpp-deploy, +# defaults/webserver/_bpp-locations.conf). Ta dyrektywa jest tam wlaczona od +# dawna, ale BEZ plikow `.gz` jest MARTWA i nie zglasza tego niczym — nginx +# po prostu cicho spada na `gzip on` i kompresuje kazdy plik OD NOWA przy +# kazdym cache-missie. Najwieksze assety to plotly.min.js (4.4 MB), +# three-bundle.js (1.9 MB) i cytoscape-bundle.js (886 KB) — wszystkie trzy +# ladowane w szablonach przez {% static %} POZA blokami {% compress %}, +# czyli serwowane wprost stad, a nie z CACHE/ compressora. +# +# Pomiar na 202608.1399rc5: 1813 plikow, 2 s buildu, +12.5 MB do obrazu. +# +# Dlaczego build-time, a nie runtime: entrypoint-appserver.sh robi `cp -rf` +# z `.baked` do $STATIC_ROOT, wiec `.gz` powstaje w tym samym kroku co plik +# zrodlowy i JEST Z NIM ZAWSZE ZGODNY. Gdyby generowac je pozniej, na +# wolumenie, mielibysmy klasyczna pulapke `gzip_static`: nginx serwuje `x.js.gz` +# NIE POROWNUJAC mtime z `x.js`, wiec nieaktualny `.gz` = wieczne serwowanie +# starego JS-a, bez sladu w logach. +# +# `-size +1000c` odpowiada `gzip_min_length 1000` z konfiguracji nginksa. +# Kompresujemy WYLACZNIE formaty tekstowe — woff/woff2/png/jpg/webp sa juz +# skompresowane i `.gz` tylko zajalby miejsce nic nie dajac. +# Drugi `find` kasuje `.gz`, ktory wyszedl nie mniejszy od oryginalu (nginx +# serwowalby WIEKSZY plik klientom deklarujacym gzip). Na obecnym drzewie +# takich przypadkow jest 0, ale to zabezpieczenie na przyszle assety. +RUN find /app/staticroot.baked -type f -size +1000c \ + \( -name '*.js' -o -name '*.css' -o -name '*.svg' -o -name '*.json' \ + -o -name '*.xml' -o -name '*.txt' -o -name '*.html' \) \ + -exec gzip -9 -k -f {} + && \ + find /app/staticroot.baked -type f -name '*.gz' -exec sh -c \ + 'for g; do o="${g%.gz}"; if [ -f "$o" ] && [ "$(stat -c%s "$g")" -ge "$(stat -c%s "$o")" ]; then rm -f "$g"; fi; done' _ {} + + RUN rm -rf /app/node_modules # R2: testy i pytest-only fixture package nie są potrzebne w produkcji. diff --git a/src/bpp/newsfragments/prekompresja-gzip-staticow.feature.rst b/src/bpp/newsfragments/prekompresja-gzip-staticow.feature.rst new file mode 100644 index 000000000..2eefe85e2 --- /dev/null +++ b/src/bpp/newsfragments/prekompresja-gzip-staticow.feature.rst @@ -0,0 +1,6 @@ +Pliki statyczne są prekompresowane gzipem już w obrazie Dockera, a wyjście +django-compressora (``CACHE/``) przy starcie kontenera. Nginx w ``bpp-deploy`` +ma ``gzip_static on`` włączone od dawna, ale bez plików ``.gz`` dyrektywa nic +nie robiła — każde żądanie kompresowało plik od nowa. Największe assety +(``plotly.min.js`` 4,4 MB, ``three-bundle.js`` 1,9 MB) schodzą teraz z dysku +gotowe, mocniej skompresowane (poziom 9 zamiast 5) i bez narzutu CPU na brzegu.