Как мы обсуждали в прошлый раз, удручающее ожирение сайтов и софта вернуло моду на простые, маленькие проекты. И сейчас происходит своеобразный ренессанс веба 90-х, вплоть до стиля Geocities (такой был бесплатный хостинг) и веб-страниц в виде PDF. Таковы примеры самореализации. У каждого человека — уникальный сайт, который отличается от остальных и отражает его личность.

Статический сайт можно выполнить в одном файле HTML, а динамический — в одном бинарнике (под катом). Тенденция видна везде. Современные фреймворки даже хвалятся «0кБ JavaScript» по дефолту, а браузеры внедрили технические усовершенствования, которые во многом аннулируют преимущества использования SPA.

Сайт в одном бинарнике


Сайт в исполняемом файле — ещё более интересная идея, чем в одном HTML, о котором мы рассказывали в прошлый раз. Если в двух словах, на сервере постоянно запущена программа на Go, которая отслеживает входящие запросы и выдаёт эмбеды изнутри себя.

В каком-то смысле это полная противоположность сайту в одном файле HTML, потому что в данном случае у нас формально не статичные странички, а динамически генерируемый контент. Более того, это полноценная система CI/CD, если так можно сказать, потому что программа постоянно обновляется из репозитория, куда удобно коммитить.

Скрипт для деплоя на сервере:

 #!/bin/sh -eu
#
# deploy my website

cd /home/j3s/code/j3s.sh
git fetch origin
if git status | grep -q behind; then
git merge origin/main
go build
mv j3s.sh /usr/local/bin/j3s.sh
service j3s.sh restart
fi

Скрипт на сервере каждую минуту проверяет изменения в репозитории. В этом смысле деплой автоматический. Автор тестирует код локально, а коммиты отражаются на сайте в течение минуты. Минимум зависимостей.

Такую систему внедрил американский разработчик Джес Олсон (Jes Olson) для своего личного сайта-бинарника j3s.sh. Он руководствовался несколькими принципами, которые можно назвать универсальными.

  1. Простой, понятный код.
  2. Быстрая разработка (логично вытекает из первого пункта), простая итерабельность.
  3. Надёжность и долговечность.
  4. Минимальные усилия в поддержке. При этом максимальная простота в устранении неполадок. Один человек способен тривиально поддерживать все системы без чужой помощи. В идеале вещи должны быть настолько простыми и надёжными, что будут ломаться крайне редко. Если какая-то неприятность всё же случилась, способ исправления проблемы должен быть очевидным.

Автор начал по классике: попробовал генераторы статических сайтов типа Hugo, а также Ghost, Jekyll, SourceHut + tarball и редактирование html вручную, но ни один вариант его не удовлетворил. Даже самая очевидная связка из генератора Hugo и хостинга на Github Pages ему не понравилась из-за множества зависимостей от конкретных программ, компаний, проектов и экосистем.

Он написал странички на старом добром HTML — и захостил на машине, которая находится под его контролем (кстати, Джес работает в известной компании, которая занимается хостингом). Казалось бы, в любой момент можно открыть vim и отредактировать любую страничку, что мгновенно отразится на сайте.

В этот момент пришла идея: если сайт написан на одном языке, то его может генерировать один бинарник. В данном случае на Go, хотя такой же бинарник можно написать на Rust, на C или любом другом языке. Суть одна и та же: это динамически обновляемый генератор статических страничек.

В этом есть свои преимущества. Например, чтобы посмотреть IP-адрес посетителя, достаточно написать функцию в четыре строчки:

 func ipHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    fmt.Fprintf(w, r.Header.Get("X-Forwarded-For")+"\n")
}

В случае необходимости можно вызвать эту функцию в любой момент:

 http.HandleFunc("/ip", ipHandler)

То есть автор отказался от генератора Hugo, а вместо него написал свою программу Go, которая постоянно работает на сервере, принимает соединения — и выдаёт клиентам контент в нужном формате по их запросам. Все статические файлы переносятся внутрь бинарника, например, с помощью пакета go-bindata или stdlib embed.

Вы можете запустить программу на любом сервере — и вот ваш «сайт» автоматически переехал на новый хостинг. Если пофантазировать, то каждый пользователь может запускать «сайт» на своём компьютере, генерировать и просматривать контент локально, каждый сам у себя (как делает Redbean).

Генератор статических HTML и CSS типа Hugo Свой бинарник
Зависимости Обновления Hugo, плагины, Docker (если зафиксировать текущую версию Hugo в контейнере) Linux, стандартная библиотека Go
Долговечность стека текущих зависимостей (прогноз) 10 лет 20–30 лет



Конечно, с личными сайтами можно экспериментировать как душе угодно. Кажется, они снова входят в моду, параллельно с возрождением RSS.

Вообще, в начале 2000-х у нас даже проходили национальные конкурсы личных сайтов. А в наши дни даже авторы с тысячами читателей предпочитают публиковаться на чужих платформах, чтобы не потерять читателей. Мало у кого есть личный домен, кроме Экслера и ещё парочки титанов.

Минимализм становится стандартом


Выше был упомянут SourceHut — это набор опенсорсных инструментов для веб-разработки, без использования JavaScript, без трекинга и прочих излишеств. Только самые быстрые и лёгкие инструменты. Набор создан в мае 2022 года специально по запросам общественности (сейчас в публичной альфе).

Современные фреймворки типа Astro, Qwik и Elder.js тоже по умолчанию начали предлагать опцию «0кБ JavaScript». Таким образом, баланс постепенно смещается от тяжеловесных SPA в сторону радикально оптимизированных MPA без JS, с бюджетом 30–50 кБ.



В идеале новый сайт пишут с нуля. Но в реальной жизни приходится иногда разбирать и старые завалы, в том числе решать задачи по оптимизации. Если требуется оптимизировать раздутый сайт, оттуда можно вырезать только полезный контент — текст и графику, и выкинуть всё остальное. Или обойтись мелкими оптимизациями, которые дают быстрый и заметный эффект.

Что касается изображений, мы получаем чистый выигрыш места за счёт простой конвертации старых JPEG и PNG в более современный формат, такой как WebP, AVIF или JPEG XL. Из этих трёх форматов только WebP поддерживается во всех браузерах (кроме IE 11). Его можно использовать смело, в то время как AVIF пока не реализовали в Safari, а самый продвинутый JPEG XL вообще нигде не поддерживается. То есть JPEG XL — это пока формат не для веба, а для личного фотоархива.

Простое преобразование из PNG в WebP одной командой convert в ImageMagick иногда даёт результат, особенно если фотографии занимают основную часть места на хостинге, как часто бывает в статических сайтах.

По степени сжатия WebP с потерями выигрывает у обычного JPEG примерно 10%:



Cжатие без потерь в WebP тоже вне конкуренции (там используется отдельный кодек):



Апгрейд браузеров убивает SPA


В последние годы в браузерах реализован ряд технических усовершенствований, которые аннулируют главные преимущества использования одностраничных приложений (SPA) вместо нормальных многостраничных сайтов (MPA):

  1. Chrome реализовал удержание заливки (paint holding) — больше нет «белой вспышки» при переходе между страницами (Safari сделал это в 2019 г).
  2. Chrome внедрил кэширование «назад-вперёд» (back-forward caching) — теперь эта оптимизация реализована во всех основных браузерах, так что навигация вперёд-назад между страницами MPA стала практически мгновенной.
  3. Service Workers — когда-то экспериментальная функция теперь стала практически на 100% доступной во всех браузерах. Она позволяет внедрить автономную навигацию по страницам без маршрутизации на стороне клиента (и связанных с этим сложностей).
  4. Если Shared Element Transitions будут приняты и реализованы в браузерах, появится возможность анимировать переходы между страницами MPA, что ранее было возможно (хотя и сложно) только в SPA.

Если вас это не убедило отказаться от толстых одностраничных приложений, оцените такой аргумент от «защитников SPA».

Возможно, в будущем SPA останутся только в специфических нишах, где без них действительно не обойтись. Например, если хотите сохранить на экране определённый объект (окно плеера или виджет чата) во время навигации по сайту. Это модная концепция transitional apps.

Похоже, что SPA повторяют судьбу библиотеки jQuery. Она предоставляла уникальные и удобные API, которые не поддерживались в браузерах. Но когда браузеры реализовали стандартно querySelector, fetch и другие вызовы, необходимость использования jQuery стала уже не такой очевидной.

Крошечный образ Docker для раздачи статики


Если рассуждать логически, то для обслуживания статического сайта не требуется особая вычислительная мощность. Нужно всего лишь изредка отдавать маленькие файлы в ответ на входящие запросы. Кажется излишеством использовать для этого Docker с тяжеловесным движком типа nginx.

Однако, фанаты-докеры с этим не согласны. Один из них поставил задачу сделать образ минимального размера для раздачи статики. Он протестировал подходящие файл-серверы и остановился на минимальном thttpd:

thttpd -D -h 0.0.0.0 -p 3000 -d /static-website -u static-user -l - -M 60

Затем нашёл маленький дистрибутив Alpine, в состав которого уже входит thttpd. Получился докер-образ 7,77 МБ.

Затем использовал докеровский инструмент scratch для минификации образа. Эта программа оставляет внутри только ядро и скрипт для загрузки всего необходимого, после запуска скачивает и устанавливает Alpine (130 МБ), берёт снаружи файлы веб-сайта — и начинает работать:

FROM alpine:3.13.2 AS builder

ARG THTTPD_VERSION=2.29

# Install all dependencies required for compiling thttpd
RUN apk add gcc musl-dev make

# Download thttpd sources
RUN wget http://www.acme.com/software/thttpd/thttpd-${THTTPD_VERSION}.tar.gz \
&& tar xzf thttpd-${THTTPD_VERSION}.tar.gz \
&& mv /thttpd-${THTTPD_VERSION} /thttpd

# Compile thttpd to a static binary which we can copy around
RUN cd /thttpd \
&& ./configure \
&& make CCOPT='-O2 -s -static' thttpd

# Create a non-root user to own the files and run our server
RUN adduser -D static

# Switch to the scratch image
FROM scratch

EXPOSE 3000

# Copy over the user
COPY --from=builder /etc/passwd /etc/passwd

# Copy the thttpd static binary
COPY --from=builder /thttpd/thttpd /

# Use our non-root user
USER static
WORKDIR /home/static

# Copy the static website
# Use the .dockerignore file to control what ends up inside the image!
COPY . .

# Run thttpd
CMD ["/thttpd", "-D", "-h", "0.0.0.0", "-p", "3000", "-d", "/home/static", "-u", "static", "-l", "-", "-M", "60"]

В итоге сам образ занимает минимальный размер:

> docker images | grep static
static latest ab0699ed2690 About a minute ago 186kB

Всего 186 КБ. Плюс файлы веб-сайта, вот и всё, что нужно носить с собой.

Код лежит на docker-static-website.

Веб-сервер с нашими файлами внутри бинарника


Не менее элегантный трюк — взять веб-сервер Redbean и внедрить внутрь бинарника свои статические файлы. В результате получится файл .com, который нативно запускается под следующими системами: Linux, Mac, Windows, FreeBSD, OpenBSD, NetBSD и BIOS. То есть этот веб-сервер работает на любом компьютере и выдаёт ваш контент в офлайне. Автор программы Redbean и кросс-платформенного формата αcτµαlly pδrταblε εxεcµταblε — известная хакерша Джастин Танни.

Минимализм и сжигание лишних слоёв абстракции — похвальная тенденция не только во фронтенде, но вообще в любом софте. Например, в десктопных ОС ожирение вообще приобрело хроническую форму. Разработчики добавляют новые функции, а не убирают лишние. Почти никто не ставит главной целью разработки увеличение производительности за счёт удаления кода.

Для серверов тоже иногда приходится искать облегчённые версии инструментов. Например, TinySSH — отличный SSH-сервер без лишних функций.

Как вариант, для древнего железа можно использовать старые версии программ. Например, веб-сервер mTCP (HTTPServ) для старых IBM PC раздаёт сайт serentty.com (копия) с сервера 386 SX 25 МГц и 4 МБ оперативки по каналу 38400 бод:

 HTTP/1.1 200 OK
Server: mTCP HTTPServ Mar 7 2020
Date: Sun, 17 Apr 2022 00:30:00 GMT
Content-Type: text/html
Content-Length: 5355
Expires: Fri, 14 Oct 2022 00:30:00 GMT
Last-Modified: Sun, 17 Apr 2022 00:02:00 GMT
Connection: keep-alive

Хотя сегодня опять упадёт, наверное…

Основная польза таких экспериментов — они поощряют креативность и возвращают любовь к разработке, немножко приближая его к искусству. Мы вспоминаем о главном: ведь мы не просто точим одинаковые гайки на станке, чтобы купить еду и оплатить ипотеку, а создаём творческие работы для самореализации.


НЛО прилетело и оставило здесь промокод для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.

Комментарии (67)


  1. F0iL
    13.06.2022 11:46
    +9

    появится возможность анимировать переходы между страницами MPA, что ранее было возможно

    Было возможно еще аж в IE 4 :)

    Не менее элегантный трюк — взять веб-сервер Redbean и внедрить внутрь бинарника свои статические файлы

    Тоже очень старая идея - такое еще с конца девяностых было в Allegro RomPager. Правда, и страданий это принесло немало.


  1. dimuska139
    13.06.2022 11:47
    -1

    аннулируют главные преимущества использования одностраничных приложений (SPA) вместо нормальных многостраничных сайтов (MPA):

    Т.е., по-вашему, SPA - это не нормально?


    1. vedenin1980
      13.06.2022 12:01
      +24

      SPA это нормально для своей области (огромные медийные или корпоративные порталы), для обычных сайтов обычных компаний это скорее попытка забивать гвозди микроскопом.


    1. maximw
      13.06.2022 13:06
      +24

      Если нормальность определять количеством, то да, SPA это не нормально. SPA нишевая штука. Если нет какого-то сложного интерфейса пользователя на странице, то многостраничные сайты удобнее.


    1. DistortNeo
      13.06.2022 16:11
      +29

      Да, с моей точки зрения, SPA — это ненормально, потому что ломают привычный инструментарий работы с сайтом, а именно возможность для пользователя открыть столько окон, сколько ему нужно. Например, Gmail: как я могу открыть несколько писем, каждое в своём окне? А никак, SPA этого не позволяет. Можно только создать несколько инстансов этого SPA. Или Google Maps: как я могу открыть информацию о нескольких объектах одновременно, чтобы сравнить их?

      В итоге пользователь начинает работать с SPA так, как если бы это был MPA, но при этом страдает от тяжеловесности SPA.


      1. daggert
        14.06.2022 01:12
        +3

        А никак, SPA этого не позволяет.

        SPA это позволяет. Точней не запрещает никак. Вопрос в реализации. У меня весьма сложная интерпрайз система в виде SPA-приложения и роутинг обрабатывает такие моменты, схожие с открытием нового письма в новой вкладке/окне или нажатие средней кнопкой мышки на вкладки. Открывается просто новое окно и в нем можно работать полноценно. При этом не загружается все приложение целиком (около 11% кода). Вопрос конечно в синхронизации между вкладками встает остро, но т.к. это локалка - можно спамить кучей xhr.

        Конечно открыть в новой вкладке кнопку "сохранить" не выйдет, однако открыть пару окон и вкладок с разными "рабочими пространствами"- можно.

        Но за это конечно платишь оооочень дорого, и я тут даже не про деньги. Время разработки растет в десятки раз.


      1. DevAdv
        14.06.2022 06:13
        +1

        Например, Gmail: как я могу открыть несколько писем, каждое в своём окне? А никак, SPA этого не позволяет.

        Хм,

        позволяет

        Ну или просто Command + Click, думаю Alt в другой системе тоже сработает.


        1. dikey_0ficial
          14.06.2022 09:15
          +1

          скорее Ctrl


        1. DistortNeo
          14.06.2022 10:01
          +5

          Спасибо, не знал. Я привык открывать ссылки в новых окнах через Middle Click, а этот функционал не работает в Gmail. Через меню открывает в новом окне, а не вкладке. К слову, папки (там, где входящие, отправленные) по среднему клику открываются в новом окне, а через Ctrl — наоборот, нет.


          1. khajiit
            14.06.2022 13:00

            Папки это ссылки, а письма это переход в другую часть SPA. Если включена строка состояния, то видны таргеты при наведении на папки.


        1. maximw
          14.06.2022 14:52
          +1

          Возможность переопределять стандартное контекстное меню браузера вообще зло само по себе.


      1. ZoomLS
        14.06.2022 13:33
        +4

        В Gmail можно использовать html версию, тогда никаких проблем с этим. Постоянно её использую, очень удобно, грузится шустро, можно открывать кучу вкладок и ничего не будет тормозить, сжирать память гигабайтами и т.д.


  1. vedenin1980
    13.06.2022 11:56
    +21

    Сайт в исполняемом файле

    Очень старая идея, наверное ей уже лет 30, я помню как такие сайты писали на Perl, потом на C++, потом Java сервлеты и Java аплеты. Там свои проблемы, получается мешанина html и обычного кода и со временем это становится болью.


    1. iShrimp
      13.06.2022 21:07
      +5

      Примечательно, что всё те же этапы развития повторяет сфера IoT. Прошивка - это такой же бинарник с интегрированными кусками HTML-кода в виде констант.


      1. iig
        13.06.2022 23:04
        +5

        Если железо позволяет - внутри появляется файловая система с html файлами.


        1. randomsimplenumber
          14.06.2022 11:07
          +2

          Никто не мешает при сборке приложения преобразовать исходники в формате html в любую структуру данных, хоть образ squahsfs, хоть дерево/словарь/массив строк. Вся файловая система, с кластерами/правами/контрольными суммами/кешированием - не всегда нужна.


    1. olku
      13.06.2022 22:54
      +6

      PHP же - скрипт и шаблонизатор вместе.


    1. garbagecollected
      13.06.2022 23:19
      +4

      И нигде на странице статьи нет упоминания названия этой технологии CGI.

      Сразу вспоминается Навальный. Как можно было написать статью про CGI и ни разу не употребить её названия?


      1. F0iL
        13.06.2022 23:33
        +5

        Потому что в статье речь не про CGI. CGI - это когда у нас есть веб-сервер, который на каждый запрос дёргает какой-то бинарник/интерпретатор чтобы сгенерить страницу. А здесь же идёт речь про случай, когда код, генерирующий страницы, вкомпилен непосредственно в бинарник самого веб-сервера, то есть составляет с ним единое целое (см. про вышеупомянутый RomPager, например).


        1. vedenin1980
          14.06.2022 00:31
          +1

          FastCGI? Sprint Boot + Embedded Jetty в одном jar'нике?


    1. squonk
      15.06.2022 18:54

      Ну да. В той же Java/Kotlin можно и Spring Boot и Quarkus и Ktor на выходе будет один файл.


  1. Tzimie
    13.06.2022 12:01
    +1

    У меня статический сайт на Nicepage, там css файл 1 Мег. Я пытался чистить но все время что-то ломается. Как бы это сделать автоматически? Мне их этого css нужно процентов 5...


    1. Alexufo
      13.06.2022 12:30
      +15

      Скачай расширение для лисы css usage или что то подобное. Походи по сайту и оно накопит только используемые свойства.


    1. Max_JK
      14.06.2022 09:03

      в хроме есть такая функция
      https://umaar.com/dev-tips/121-css-coverage/


    1. vilya_ya
      15.06.2022 09:20

      Посмотрите в сторону PurgeCSS .

      Если есть динамический контент (получаемый из БД, например), то необходимо будет добавить его стили в исключения.


  1. beduin01
    13.06.2022 12:12
    +2

    SourceHut - хороший образец минимализма.


  1. Ivnika
    13.06.2022 12:46
    +18

    Когда-то сохранил себе в копилку идей понравившийся сайт https://oknaludyam.ru :)


    1. MagisterAlexandr
      13.06.2022 20:07
      +2

      https://web.archive.org/web/20180506234654/http://oknaludyam.ru/ хорош, а теперь дизайн слегка подпортили в угоду повышению конверсии или как оно там называется.


  1. Mingun
    13.06.2022 14:27
    +15

    Chrome внедрил кэширование «назад-вперёд» (back-forward caching) — теперь эта оптимизация реализована во всех основных браузерах, так что навигация вперёд-назад между страницами MPA стала практически мгновенной.

    То есть, в хроме наконец реализовали то, что ещё 10 лет назад умела Opera 12?


    1. F0iL
      13.06.2022 23:41
      +4

      Opera, насколько я помню, кэшировала только сами элементы страницы и содержимое форм. В наше время так действовать не получится - сегодня сайты (особенно вышеупомянутые SPA) обскриптованы по самое не хочу, и если просто закэшировать состояние DOM-дерева, многие сайты после загрузки из кэша сломаются нафиг - нужно сохранять полностью ещё и состояние скриптов, выполняемых на странице. Opera такое не умела, а вот в новом Хроме, по заверениям разработчиков, оно действительно работает.


      1. VEG
        14.06.2022 00:15
        +1

        Не любитель старой Оперы, но только что проверил — похоже, что состояние скриптов сохраняется.


        1. F0iL
          14.06.2022 00:30

          А как конкретно проверили? Оно действительно восстанавливает js heap целиком, все таймеры, не успевшие сработать коллбэки, и все остальное из tasks queue?

          Когда в свое время, засидевшись, слезал с "классической" Оперы, помню, что уже тогда некоторые сайты начали ломаться при загрузке из кэша...


          1. VEG
            14.06.2022 07:51
            +2

            Ну как минимум таймеры и значения переменных восстанавливаются, проверил на radar.veg.by. Без восстановления состояния там бы таймер с обратным отсчётом сбрасывался бы до ближайших 30 секунд, как при перезагрузке страницы. Что-то более тяжёлое из современного вы там вряд ли заведёте уже. Возможно, в каких-то случаях оно работало плохо или с ошибками, я не знаю. Оперой как основным браузером никогда не пользовался, только тестировал в ней свои сайты. Иногда сталкивался с неприятными багами в неожиданных местах при этом. Возможно, вы тоже сталкивались с какими-то ошибками в реализации.


      1. Mingun
        14.06.2022 18:07
        +1

        Не знаю, что и как конкретно она сохраняла, но при использовании кнопки «Назад» ни один сайт никогда не ломался (а пользовался я ей довольно часто, да и сайты были типа google.ru — то есть, объём скриптов там уже тогда был приличный).


  1. baldr
    13.06.2022 14:31
    +31

    Интересно для хобби-проекта, но я лично бы не стал доверять таким решениям.

    Если хочется раздавать только статику с одного публичного сервера - то nginx "и никаких гвоздей"!

    Бинарник слушающий сокет? А забыли ли мы атаки с переполнением буфера, инжекцией параметров или просто какой-нибудь printf()?

    Как только создаешь публичный сервер с открытыми портами - в течение нескольких часов набегает толпа китайских ботов-сканеров и шлют всякую ересь в надежде использовать какой-то эксплоит.

    nginx надежен и протестирован миллионами. Не пускает куда не надо, умеет TLS, пишет логи и прекрасно справляется с тысячами HR, внезапно захотевших открыть вашу страничку с резюме в одно и то же время.


    1. 0xd34df00d
      13.06.2022 20:25

      А забыли ли мы атаки с переполнением буфера, инжекцией параметров или просто какой-нибудь printf()?

      Если использовать нормальные безопасные языки, то этого не будет.


      1. DirectoriX
        13.06.2022 20:49
        +8

        «Безопасность» языка помогает защититься только от определённого класса проблем, но против банальных недосмотров они бессильны. Пример — если в веб-сервере не проверять выход выше корневой папки, то любой Петя прочитает с диска всё, до чего дотянутся его ../../
        Ну или можно добавить интересные функции, из-за которых вообще бахнет так, что мало не покажется, привет Log4j.


        1. 0xd34df00d
          13.06.2022 20:59
          -1

          Пример — если в веб-сервере не проверять выход выше корневой папки, то любой Петя прочитает с диска всё, до чего дотянутся его ../../

          Вопрос в том, где вы это будете проверять. Если вы пишете код на C (или на go), то это надо проверять в каждой точке чтения файлов. Если вы пишете на более выразительных языках, то это достаточно проверить ровно в одном месте.


          Ну или можно добавить интересные функции, из-за которых вообще бахнет так, что мало не покажется, привет Log4j.

          Опять же, если язык достаточно выразительный, то нельзя.


          1. Oxoron
            13.06.2022 21:41
            +11

            Вопрос в том, где вы это будете проверять.

            Я не хочу этого проверять. Вот вообще.

            Не то, чтобы все эти проверки были чем-то плохим, просто я относительно слабо разбираюсь в вопросах безопасности. Так что, если условный nginx закрывает over9000 "стандартных" сценариев, пусть и ценой докер-образа в 60 МБ -- я возьму nginx.


            1. cepera_ang
              13.06.2022 22:14

              А если весь сайт — это бинарь, умеющий отдавать зашитые константы файлы (как предложено), то там и нет никаких ../../ откуда можно какие-то файлы читать, вообще ничего нет, кроме одинокого запущенного бинаря с одной фунцией route(address) -> str :)


              1. iig
                13.06.2022 23:06
                +1

                Полезность такого сайта стремится к 0 ;)


            1. 0xd34df00d
              13.06.2022 22:33
              +4

              А откуда вы знаете, что условный nginx это закрывает, и его конфиг не позволяет читать файлы откуда-то ещё? Я этого не знаю, например.


              1. Oxoron
                14.06.2022 08:30
                +5

                Вопрос резонный. Принципы работы с безопасностью (для самых маленьких):

                1. Полной защиты не дает ничто (смотрим в сторону ZeroDay уязвимости, социальной инженерии, бекдоры от спецслужб). Вывод: наша задача (как людей не особо знакомых с безопасностью) -- закрыть наиболее ходовые сценарии, с минимальными затратами.

                2. В случае малого\среднего сайта безопасник - максимум один. А посылать всякую ересь в порты сервиса будет толпа китайских ботов-сканеров. Велика вероятность, что один из толпы заюзает таки эксплоит, с которым наш безопасник не знаком.
                  Вывод: кастомные платформы рискованней поддерживаемой платформы с богатой историей.

                Как выбирать сервер/framework для интернет-магазина/платформу для блога/etc:

                1. Спросить друга безопасника. Друг не только посоветует что-то, но еще и расскажет (а то и проверит) самые критичные дыры.

                2. Если друга безопасника нет - гуглим самое популярное решение. Пентест закладываем исходя из бюджета (в 90% случаев - не закладываем).

                3. Гуглим "10 popular vulnerabilities for your-platform-name", закрываем уязвимости из списка.

                4. Ставим напоминалку на через год: "обновить nginx/magento/wordpress/etc, продлить напоминалку".

                5. Расслабляемся.

                6. Идем настраивать бекапы.

                7. Расслабляемся


                1. 0xd34df00d
                  14.06.2022 16:15
                  +1

                  Друзья, безопасники, закрываем 10 уязвимостей… Не, извините, мне проще в этом своём хаскеле типами проверить, что я нигде не вылезаю за ../../.


                  1. iig
                    14.06.2022 19:18
                    +5

                    И что unicode правильно парсится.


                    1. 0xd34df00d
                      14.06.2022 21:12
                      +1

                      А что с уникодом?


        1. Refridgerator
          14.06.2022 06:39
          +4

          Пример — если в веб-сервере не проверять выход выше корневой папки, то любой Петя прочитает с диска всё, до чего дотянутся его ../../
          Совсем не обязательно мапить веб-запрос напрямую в файловую систему, особенно при использовании своего собственного веб-сервера. Html можно генерировать на лету, а не загружать его каждый раз с диска — в этом и смысл.


  1. Sadler
    13.06.2022 16:17
    +2

    Так-то можно ещё меньше зависимостей оставить, без docker'а, Go и sh-скриптов. Просто модулем к nginx запросы обрабатывать, мне приходилось такое реализовывать. НО это максимально нишевое решение с миллионом способов отстрелить себе ногу, и непонятно, зачем могут понадобиться такие костыли основной массе разработчиков.


  1. vanyas
    13.06.2022 16:49
    +12

    Затем использовал докеровский инструмент scratch для минификации образа. Эта программа оставляет внутри только ядро и скрипт для загрузки всего необходимого, после запуска скачивает и устанавливает Alpine (130 МБ), берёт снаружи файлы веб-сайта — и начинает работать:

    Ну неправда же, в докер образе нет ядра. Ну scratch это не какая-то отдельная программа, а способ сборки докер образа. Очень похоже на кривой перевод


    1. eps
      14.06.2022 11:41
      +2

      И сама идея: скачивать при каждом запуске по 130 МБ ради того, чтобы уменьшить образ на 7 МБ?


      Как-то не очень. И плохо сходится с идеей статьи о «минимуме зависимостей» и «только то, что нужно»


      1. DistortNeo
        14.06.2022 13:13
        +2

        Эти 130 мегов нужны, чтобы скомпилировать веб-сервер из исходников со статической линковкой. Дальше вы на выходе получаете образ минимального размера, с которым можете делать что угодно.


  1. vikarti
    13.06.2022 18:35
    +6

    Долговечность стека текущих зависимостей 20–30 лет?
    А как решается проблема с https? Отказаться от него — браузеры начнут говорить сайт небезопасный (уже начинают), поддерживать — так лет через десять появится TLS1.7 а в TLS1.3 найдут чтонибудь ну очень ужасное и браузеры начнут ругатся на него. Даже если не найдут — как сертификат то обновлять? Каждый раз на старте бинарника (у нас один бинарник же — только в память сохранять) дергать Let's Encrypt на предмет сертификата? а что если протокол общения с Let's Encrypt сменится? Или Let's Encrypt в конкретной стране забанят (или он забанит страну)?
    Или вешать nginx перед сервером? А нафига?


    Если у нас сайт это набор статических страниц без js — уже чем хостить — то найдется.


  1. Javian
    13.06.2022 21:08

    У знакомого статичный сайт лежит на амазоне - недавно показывал в какие копейки хост обходится в год.


    1. olku
      13.06.2022 23:01

      Oracle две виртуалки дает бесплатно. IO не очень, но крутит и Симфони, и Спринг бут с небольшими базами.


      1. spinagon
        14.06.2022 10:33
        +2

        В России уже не даёт, а кому дал тех банит


        1. olku
          14.06.2022 10:43

          Наслышан. А Амазон не банит?


          1. spinagon
            14.06.2022 13:24

            Амазон и гугл пока работают, только с оплатой проблемы, как и везде


        1. cepera_ang
          14.06.2022 18:12

          Обещали забанить, кстати, но тьфу-тьфу, виртуалка продолжает работать уже три месяца после того, как пришло письмо «мы вас отключили».


    1. alexzeed
      13.06.2022 23:11

      Небольшой статичный наверное можно на GtHub Pages совсем бесплатно положить.
      А насчет сайта-бинарника — еще никто не вспомнил про архитектуру. Конечно, сейчас «дефолтная» amd64 почти везде, но я бы не закладывался на то, что это сохранится через 30 лет. Вполне может arm ее потеснить, он энергоэффективнее — значит arm хостинг постепенно станет дешевле.
      Хотя сайт все равно как-то обновлять надо, скорее всего пересобирая из исходников при этом.


      1. F0iL
        13.06.2022 23:44

        ... можно запускать из под qemu-user :) Кстати, интересное извращение получится, можно попробовать заняться как-нибудь на выходных...


  1. 1ntrovert
    14.06.2022 10:05
    +1

    В Go кстати есть встроенные средства для embed.

    import _ "embed"
    
    //go:embed hello.txt
    var s string
    print(s)


  1. KizhiFox
    14.06.2022 11:22

    У меня есть статичный сайт без JS, который я писал на Markdown с последующей конвертацией в HTML с помощью Python-Markdown.

    Вообще, нужно было сделать справочник по своему миру для компании в Dungeons & Dragons. Какие-то существующие вики-решения по типу Fandom показались слишком сложными в управлении. Неплохим вариантом были Notion и Telegraph, но в первом было слишком много лишних функций и чужой брендинг, а во втором, наоборот, функций было слишком мало. К тому же руки чесались сделать что-то самому.

    В итоге родился небольшой проект, работающий примерно так: я пишу Markdown с несколькими самописными модулями (навигация по страницам, относительные ссылки, шаблоны для статблоков), прогоняю его через конвертер и заливаю на Github Pages. Также на случай, если захочется хостить самому (на практиже же просто смотреть результат в процессе написания), есть простенький Bash скрипт для питоновского http.server, который ещё и обновления в MD исходниках смотрит и HTML страницы пересобирает.

    На выходе получается что-то эдакое: https://kizhifox.github.io/dnd-shard-wiki/

    P.s.: Спасибо за абзац про WebP, возможно ещё пикчи в него перегоню, а то об этом как-то сам забыл :)


  1. Pavel1114
    14.06.2022 12:49
    +5

    ну не знаю. Вот глиняные таблички были норм — ты их мог хотя бы пощупать. А что с этими байтами делать? только лишние слои абстракции


    1. Sau
      14.06.2022 15:50
      +2

      Вся нужная информация - в генах. А таблички всего несколько тысяч лет пока протянули.


  1. nmrulin
    14.06.2022 14:20

    В своё время вот пытались делать сайты на IntraWeb -там тоже всё делает бинарник. Не взлетело.


  1. Color
    14.06.2022 16:19
    -1

    По сути, автор сделал аналог GitOps, только для статического сайта. Правда, я не очень понял претензию к чужим сервисам - что автору мешает хостить статику со своего же сервера, ну и билдить при деплое (если не нравится гитхаб, можно хоть на сервер пушить, а можно и по ftp заливать, коли совсем дело плохо).

    На поиграться интересно, но это же 100% велосипед.


  1. GothicJS
    15.06.2022 09:18

    Так я не понял, теперь што js и react не нужОн чтоли? Што за жизнь, учишь сначала mvc-шный фреймворк с родным шаблонизатором и узнаешь, что такое давно не модно и все хотят отдельный фронт в виде SPA. Потом учишь фронт и вот оказывается, что SPA то и не нормально вовсе и снова взад к многостраничной статике.....вот это поворот! Нет, в чем то тут должен быть подвох!