Веб-программирование
Веб-программирование · 16 лекций
Всё, что разберём сегодня, работает в этих продуктах прямо сейчас
16 лекций · 7 лабораторных · свой проект в конце
Первые лабораторные пишем руками, без конструкторов и генераторов.
Не из вредности: когда через месяц что-то сломается внутри React, чинить придётся именно на этом уровне.
Поднимите руку
Memex → Server Components
Считаем до трёх и все называем вслух
1945
Инженер Ванневар Буш описывает машину, где документы связаны перекрёстными ссылками, а читатель ходит по ним произвольными тропами.
До первого сайта оставалось 44 года.
Vannevar Bush, «As We May Think»1965
Тед Нельсон придумывает термин и начинает проект Xanadu — всемирную библиотеку связанных документов.
Xanadu разрабатывали 54 года и выпустили в 2014-м. К тому времени веб уже победил.
1969
Два компьютера, 600 километров между ними. Оператор набирает слово
LOGIN, чтобы войти на удалённую машину.
Система рухнула после второй буквы.
Первое, что одна машина сказала другой
1983
ARPANET переходит на протоколы TCP/IP — правила, по которым разные сети научились понимать друг друга.
1989
Тим Бернерс-Ли, программист ЦЕРН, подаёт начальнику документ «Information Management: A Proposal» — как связать разрозненные документы лаборатории.
Начальник пишет на полях резолюцию.
Оригинал предложения на сайте W3C1990
Бернерс-Ли пишет WorldWideWeb на компьютере NeXT. Он умел
не только показывать страницы, но и редактировать их.
Эту способность браузеры потеряли на тридцать лет.
1991
info.cern.ch — страница о том, что такое World Wide Web.
Ни картинок, ни стилей. Только заголовки, абзацы и ссылки — всё то, что мы разберём во второй половине пары.
Он до сих пор открывается. Сейчас проверим.
1993
ЦЕРН объявляет веб общественным достоянием: без патентов, без лицензий, бесплатно для всех и навсегда.
Конкурирующие сети — Gopher, AOL, Minitel — брали деньги за использование. Их больше нет.
1993
Браузер, который показывал изображения прямо в тексте, а не отдельным окном. Плюс понятный интерфейс и установка в один клик.
За два года число сайтов выросло с 130 до 23 500.
1995
<blink>
Мигающий текст
</blink>
<marquee>
Бегущая строка
</marquee>
Каждый добавлял свои теги, не спрашивая никого. Сайт, работавший в одном браузере, ломался в другом.
<table>, вложенных друг в друга по пять уровней.
Плюс счётчики посещений, гостевые книги и фоновая музыка.
2004
W3C ведёт веб в сторону строгого XHTML 2.0, несовместимого со всем написанным раньше. Apple, Mozilla и Opera с этим не согласны и создают свою группу.
Их принцип победил: не ломать существующие сайты. Сегодня HTML развивает именно WHATWG.
2005
Google Maps показывает: страница может подгружать данные без перезагрузки. Карту можно таскать мышкой.
Веб перестаёт быть библиотекой документов и становится платформой для приложений.
2008
Google выпускает браузер с движком V8, который компилирует JavaScript в машинный код. Скорость выполнения растёт в разы.
Позже тот же V8 вынесут из браузера и назовут Node.js — так JavaScript попадёт на сервер.
2010
Стив Джобс публикует «Thoughts on Flash» и объявляет: на iPhone Flash не будет никогда. Причины — батарея, безопасность и закрытость технологии.
Adobe окончательно похоронила Flash 31 декабря 2020 года.
Steve Jobs, «Thoughts on Flash»2014
Выходит HTML5: видео, аудио, графика и семантические теги — без плагинов, силами самого браузера.
Сервер отдаёт готовый HTML, браузер показывает.
Сервер отдаёт пустую страницу, всё рисует JavaScript.
DNS · HTTP · рендеринг
Физическая сеть: провода, спутники, маршрутизаторы, IP-адреса. Способ доставить пакет данных из точки А в точку Б.
Один из сервисов поверх интернета: страницы, ссылки, протокол HTTP. Рядом живут почта, торренты, игры, мессенджеры.
Разговор всегда начинает клиент. Сервер сам к вам не постучится.
Люди помнят слова, компьютеры работают с числами. За перевод отвечает DNS — телефонная книга интернета.
example.com → 93.184.216.34
Ответ кэшируется на всех уровнях — от вашей операционной системы до провайдера. Поэтому второй раз сайт открывается быстрее.
URLUniform Resource Locator
https:// — протокол, по которому говорим? идут параметры: фильтры, страница, поиск# — якорь, он не уходит на сервер80 и 443 подставляются самиHTTPязык, на котором клиент говорит с сервером
GET /catalog/books HTTP/1.1
Host: example.com
Accept: text/html
Accept-Language: ru-RU
Никакой магии: строка запроса, набор заголовков, пустая строка, иногда тело. Это можно набрать руками в консоли.
200 OK, 201 Created
301 навсегда,
302 временно
404 нет страницы,
403 нельзя, 401 представьтесь
500 упал код,
503 перегружен
RFC 2324 — первоапрельская шутка 1998 года про протокол управления
кофейником. Код 418 означает: «я чайник, кофе сварить не
могу».
В 2017-м его попытались убрать из стандарта. Поднялась такая волна возмущения, что код вернули.
RFC 2324, Hyper Text Coffee Pot Control Protocols?HTTPS — тот же HTTP, но внутри шифрованного канала. Провайдер, сосед по Wi-Fi и админ сети видят только, с каким сайтом вы общаетесь, но не о чём.
Сегодня это не опция: без HTTPS браузер поставит в адресной строке предупреждение, а половина возможностей веба просто не включится.
Ваши версии
И на каждом шаге что-то может пойти не так. Половина работы фронтендера — понимать, на каком именно шаге сломалось.
Инструмент для этого встроен в браузер: вкладка Network в DevTools. Откроем её прямо сейчас на любом сайте.
Смешивать их в кучу можно — так делали в девяностых. Мы уже видели, чем это закончилось.
Из чего собрана любая страница
Кто считает, что да — поднимите руку
В нём нет переменных, условий и циклов. Он ничего не вычисляет. Он размечает текст: вот это заголовок, вот это список, а вот это ссылка.
Привет
Это абзац
Ссылка на MDN
<h1>Привет</h1>
<p>Это абзац</p>
<a href="...">Ссылка</a>
Слева машина видит буквы. Справа — понимает, что перед ней.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Моя страница</title>
</head>
<body>
<h1>Привет!</h1>
</body>
</html>
Скелет, с которого начинается каждый файл.
<head><meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<title>Лекция 1 — Веб-программирование</title>
<meta name="description" content="Как устроен веб">
<link rel="stylesheet" href="style.css">
Вот так выглядит страница без <meta charset="utf-8">
<a href="page.html" title="Подсказка">Текст</a>
<a> — начало элемента
href, title — настройки,
всегда в открывающем теге
</a> — конец, со слэшем
<p>Абзац</p>
<h1>Заголовок</h1>
<div>Блок</div>
<img src="cat.jpg" alt="Кот">
<br>
<hr>
<input type="text">
Одиночным закрывать нечего — внутри них не бывает содержимого.
<p>
Текст со
<strong>
<em>вложением</em>
</strong>
</p>
<p>
Текст со
<strong>
<em>вложением
</strong>
</em>
</p>
Кто открылся последним — закрывается первым.
<div class=card>
<h2>Заголовок</h3>
<p>Текст карточки</p>
<img src="pic.jpg">
</div>
Полминуты, обсуждаем вслух
<div class=card> ← 1. значение без кавычек
<h2>Заголовок</h3> ← 2. открыли h2, закрыли h3
<p>Текст карточки</p>
<img src="pic.jpg"> ← 3. нет alt
</div>
<!-- Это комментарий, на странице его не видно -->
<!-- <p>Временно отключённый блок</p> -->
Но помните: «не видно» ≠ «нет». Любой посетитель откроет исходный код страницы и прочитает всё, что вы там написали.
DOM — Document Object Model — то самое дерево. Именно с ним будет работать весь ваш JavaScript и вся библиотека React.
<h1>Название страницы</h1>
<h2>Крупный раздел</h2>
<h3>Подраздел</h3>
<h4>Совсем мелкий</h4>
h1 — один на страницу. Уровни идут по порядку, без
перепрыгивания через ступеньку.
<h4>Главный заголовок</h4>
<h1>Мелкая подпись</h1>
<h1>Главный заголовок</h1>
<p class="note">Мелкая подпись</p>
Первая мысль<br><br>
Вторая мысль<br><br>
Третья мысль
<p>Первая мысль</p>
<p>Вторая мысль</p>
<p>Третья мысль</p>
<br> уместен там, где перенос — часть содержимого: в
стихах, адресе, телефоне. Расстояние между абзацами — работа CSS.
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<ol>
<li>Скачать</li>
<li>Установить</li>
<li>Запустить</li>
</ol>
Прямо внутри списка может лежать только <li>. А вот
внутри <li> — что угодно, включая другой список.
<blockquote>
<p>Vague but exciting</p>
</blockquote>
<p>Функция <code>fetch()</code> делает запрос.</p>
<p>Нажмите <kbd>Ctrl</kbd> + <kbd>S</kbd></p>
<pre>текст, где важны
пробелы и переносы</pre>
<b> — просто нарисуй жирнее, смысла никакого
<strong> — это важно, обрати внимание
То же самое с <i> и <em>: первое —
просто наклон, второе — смысловое ударение.
Скринридер выделяет strong и em голосом —
меняет интонацию, как это сделал бы человек. b и
i он произносит ровно.
<a href="https://developer.mozilla.org">
Документация MDN
</a>
Без href это не ссылка, а просто текст. Именно связи между
документами превратили набор файлов во всемирную паутину.
href<a href="https://example.com/page">абсолютный адрес</a>
<a href="/catalog/books">от корня сайта</a>
<a href="about.html">рядом с этим файлом</a>
<a href="../index.html">на папку выше</a>
<a href="#contacts">к якорю на этой же странице</a>
<a href="mailto:kaf@univer.by">написать письмо</a>
<a href="https://example.com"
target="_blank"
rel="noopener">Внешний сайт</a>
rel="noopener" закрывает старую дыру в безопасности, когда
открытая страница получала доступ к вашей. Современные браузеры это
чинят сами, но в чужом коде вы увидите атрибут часто.
<img src="cat.jpg" alt="Рыжий кот спит на клавиатуре">
alt, если картинка видна
Что слышит человек, когда вы забыли alt
altalt="картинка"
alt="фото"
alt="IMG_2847.jpg"
alt="График роста
посещаемости
за 2026 год"
alt="". Пустой alt говорит скринридеру: «пропусти, здесь
нет информации». Это правильно, а вот отсутствие атрибута —
ошибка.
<figure>
<img src="scheme.png" alt="Схема клиент-сервер">
<figcaption>
Рис. 1. Как браузер общается с сервером
</figcaption>
</figure>
figure связывает изображение и подпись в одно целое.
Работает не только с картинками — ещё с кодом, схемами и таблицами.
<table>
<caption>Расписание лабораторных</caption>
<thead>
<tr><th>Номер</th><th>Тема</th></tr>
</thead>
<tbody>
<tr><td>ЛР 1</td><td>HTML</td></tr>
</tbody>
</table>
th — заголовок ячейки, td — обычная.
У браузера есть <div> — универсальная безымянная
коробка. В неё можно положить что угодно, и всё будет работать.
А есть теги, которые сообщают смысл: это шапка, это навигация, это главное содержимое.
<div class="header">
<div class="nav">…</div>
</div>
<div class="main">
<div class="article">…</div>
</div>
<div class="footer">…</div>
<header>
<nav>…</nav>
</header>
<main>
<article>…</article>
</main>
<footer>…</footer>
На экране — ровно одно и то же. Разница только внутри.
main,
минуя меню. С div-супом такой навигации нет.
<footer> понятнее, чем
<div class="f2">.
<div>Ваши варианты
<div> — не врагОн нужен, когда элементы надо сгруппировать только ради вёрстки, и никакого смысла в этой группе нет.
div и спокойно живём дальше.
validator.w3.org — официальный валидатор. Загружаете файл или адрес, получаете список ошибок.
Напомню: браузер вам про ошибки не скажет. Он молча починит разметку как сумеет — и вы узнаете о проблеме, только когда что-то поедет.
Как страница разговаривает с сервером
Логин, поисковый запрос, комментарий, заказ пиццы, заявление в деканат —
всё это ушло через <form>.
Формы — единственный способ отправить данные на сервер, не написав ни строчки JavaScript.
<form action="/apply" method="post">
<label for="name">Имя</label>
<input type="text" id="name" name="name">
<button type="submit">Отправить</button>
</form>
Данные в адресе после ?. Видно в строке браузера,
попадает в историю, длина ограничена.
Поиск, фильтры, сортировка — то, чем можно поделиться ссылкой.
Данные в теле запроса. В адресе не видно, размер не ограничен.
Пароли, файлы, всё, что меняет данные на сервере.
GET
input typetype — это бесплатно
Поставили type="email" — на телефоне появилась клавиатура с
собачкой, а браузер сам проверит формат.
Поставили type="date" — получили календарь, который кто-то
уже написал и отладил за вас.
<label><p>Имя</p>
<input type="text">
<label for="name">Имя</label>
<input type="text" id="name">
<textarea name="about">Многострочный текст</textarea>
<select name="year">
<option value="3" selected>3 курс</option>
</select>
<fieldset>
<legend>Что уже знаете</legend>
<label>
<input type="checkbox" name="skills" value="html">
HTML
</label>
</fieldset>
type у кнопки<button>Показать</button>
По умолчанию это type="submit". Форма отправится,
страница перезагрузится.
<button type="button">Показать</button>
Теперь кнопка просто кнопка.
На этом спотыкаются все. Считайте, что вас предупредили.
name —
id нужен, чтобы связать поле с label
и найти его из CSS и JavaScript.
name — это
имя, под которым значение приедет на сервер. Поле без
name форма просто не отправит.
name="email" → сервер получит
email=ivan@univer.by
<input type="email" required>
<input type="text" minlength="2" maxlength="30">
<input type="number" min="1" max="4">
<input type="text" pattern="[А-Яа-я]{2}-\d{2}"
title="Например: ПО-31">
Браузер сам покажет подсказку. Но на сервере проверяйте ещё раз: эту проверку обходят за десять секунд через DevTools.
ul>li*3
<ul>
<li></li>
<li></li>
<li></li>
</ul>
Уже встроен в VS Code. Наберите ! и нажмите Tab — получите
весь скелет документа.
divaltlabelНикакого CSS — он будет на следующей паре.
Основы CSS: каскад, наследование, специфичность, селекторы
Слайды и все демо — в репозитории курса