Виды веб-приложений
Разбираем основные способы организации веб-приложения и чем они отличаются.
Время чтения: 9 мин
Открыть/закрыть навигацию по статье
- Кратко
- Многостраничные приложения
- Готовые веб-страницы
- Динамическая генерация HTML
- Client Side Rendering (CSR)
- Server side rendering (SSR)
- Static site generation (SSG)
Обновлено 14 октября 2022
Кратко
Все веб-приложения делаются с помощью одних и тех же технологий: HTML, CSS и JavaScript. Однако есть много способов организации работы приложения. Выбор способа зависит от цели приложения и пользовательского опыта, которого мы хотим добиться. Хотя основных подхода всего два: многостраничные приложения и Single Page Applications, каждый из них делится на подвиды.
Статические многостраничные приложения состоят из набора статичных страниц. Их просто разрабатывать, но если страниц становится много (сотни и тысячи), или данные на странице меняются, то придётся генерировать их на лету. Для этого нужно подключать сервер и писать дополнительный код. На каждый переход нужно генерировать и загружать новую страницу, а это занимает время.
Одностраничные приложения (SPA) дают возможность разрабатывать клиентские приложения со сложной логикой с помощью JavaScript. В этом подходе отрисовкой содержимого на странице управляет JavaScript. Переходы между экранами будут мгновенными, и пользователь сразу увидит результат своих действий. Однако такой подход создаёт новые проблемы. Как не загружать в браузер слишком много кода? Как обеспечить хорошую производительность? Где рендерить приложение: только на клиенте или на сервере?
Разработка таких приложений часто сложнее, так как может потребовать знания различных инструментов и фреймворков.Многостраничные приложения
Многостраничные приложения – это набор статичных веб-страниц, которые связаны между собой с помощью ссылок. При клике на ссылки происходит переход между страницами, что ведёт к полному обновлению страницы в браузере. Это одно из наиболее значимых отличий от SPA, о нем поговорим отдельно.
Для начала выделим два основных вида многостраничных приложений:
- Набор готовых свёрстанных страниц, которые лежат на сервере и вместе с ними находятся и другие статичные файлы (CSS, JavaScript и картинки). Сервер отдаёт эти файлы по заранее настроенным путям.
- Динамическая генерация HTML на сервере. Чаще всего такое решение можно встретить на языках программирования PHP, Python и Ruby. При каждом запросе сервер запускает скрипт генерации HTML-страницы. Скрипт может взять данные из базы данных, произвести вычисления и собрать готовый HTML-код страницы.
Готовые веб-страницы
Подходят, если нужно собрать несколько связанных страниц, которые, по большей части, будут содержать статичную информацию, с которой пользователь может мало взаимодействовать. Например, лендинг – это веб-сайт, который представляет информацию о компании, товарах или продукте.
Разработка при таком подходе обычно самая простая. Рядом складываются несколько html-файлов, в которых содержится вся необходимая вёрстка и дополнительные CSS/JavaScript файлы, подключённые к странице. В продвинутом варианте можно переиспользовать части кода с помощью шаблонизаторов (например, Pug) и собрать сайт по кусочкам используя сборщики (Gulp, Rollup, Webpack и др.). В результате на сервер попадёт набор статичных файлов, которые будут раздаваться с помощью веб-сервера (Nginx, Apache).
Преимущество такого подхода — это отличная производительность. Статичные страницы и файлы легко кэшировать с помощью браузера, CDN или Service Worker.
Динамическая генерация HTML
Динамическая генерация HTML страницы часто использовалась до изобретения Single Page подхода. Так до сих пор работает большинство форумов, интернет-магазинов, а так же большие приложения, как Facebook или ВКонтакте.
Особенность этого подхода в использовании серверных языков программирования (например, PHP или Ruby), чтобы генерировать итоговый HTML страницы, собирая его из разных частей и обогащая данными.
Например, пользователь перешёл на страничку со списком друзей:
- Сервер получает запрос.
- Идёт в базу данных, выбирает список друзей и вспомогательные данные.
- По шаблону собирает HTML.
- Отправляет HTML в виде ответа на запрос.
Пользователь сразу получает сгенерированную страницу со списком друзей. Если добавить новых друзей и зайти на страничку ещё раз, то результат будет другой, ведь список друзей изменился.
Использование сервера для генерации содержимого позволяет не нагружать клиентский код сложной логикой, а значит итоговый размер страницы будет меньше. При этом статичные части приложения и целые куски страниц можно так же легко кэшировать.

При всех плюсах многостраничных приложений, все они страдают от одного главного недостатка: при переходе между страницами браузер полностью обновляет содержимое, из-за чего нельзя создать полноценный опыт взаимодействия «как в приложении»: незакэшированным страницам нужно время для загрузки, а значит не будет мгновенного перехода; будет сбиваться положение полосы прокрутки и т.д.
В стремлении решить эти проблемы и создать полноценный опыт приложений веб-разработчики изобрели одностраничные приложения.
Single page applications (SPA)
Одностраничные приложения (сокращённо SPA) состоят из одной страницы, а всю остальную работу (создание содержимого, переход между экранами и получение данных) выполняет JavaScript. Такой подход позволяет создать полноценный опыт приложения: переходы между экранами происходят мгновенно, можно давать пользователю визуальный ответ, пока данные загружаются асинхронно с помощью API.
Разработка одностраничных приложений имеет богатую экосистему: фреймворки и библиотеки для создания интерфейсов, подходы к разработке, архитектурные паттерны. Одностраничные приложения делятся по месту начальной отрисовки страницы: в браузере (client side rendering) или на сервере (server side rendering).
Client Side Rendering (CSR)
В таком приложении вся отрисовка содержимого страницы, включая первую, происходит в браузере. Пользователь должен сначала загрузить весь JavaScript, и только после этого что-то сможет отрисоваться. До этого момента страница будет либо пустой, либо будет содержать статическую заглушку-лоадер.
Это самым простой способ отображения SPA. Он подходит для небольших приложений, так как оно быстро загружается и запускается. Если кода много и приложение получается большим, пользователи со слабыми устройствами или медленным интернетом могут не дождаться загрузки и уйти.
SPA не работает без JavaScript. Если по какой-то причине пользователь отключил его в своём браузере, то одностраничное приложение не запустится вовсе.
Это требование особенно важно в контексте того, как поисковые сервисы индексируют SPA. Раньше поисковики не умели выполнять JavaScript и потому одностраничные приложения не попадали в результаты поиска. Сейчас ситуация изменилась, поисковые сервисы умеют исполнять JavaScript, но статические сайты до сих пор индексируются лучше.

Server side rendering (SSR)
Чтобы пользователь не смотрел на пустую страницу в ожидании загрузки приложения, можно отдавать ему сгенерированный сервером HTML. Таким образом пользователь сразу получит ожидаемую страничку и начнёт её просматривать, пока основное приложение загружается и запускается.
Такой подход называется серверным рендерингом. Он помогает улучшить и пользовательский опыт, и позицию сайта в поисковиках. Поиск Google и Яндекса умеет исполнять JavaScript, но сайтам со статическим контентом отдаётся предпочтение.
Главное отличие такого подхода от рендеринга на клиенте — это сервер, который занимается рендерингом. Чаще всего это готовое решение на базе Node.js. Многие SPA-фреймворки имеют проверенные решения для быстрого старта приложения с серверным рендерингом. Например, Next.js для React или Nuxt для Vue.
Своё решение для SSR — непростая задача. Приходится учитывать множество факторов: как и куда сходить за данными, как правильно отрисовать приложение и много других деталей.
Дополнительная серверная часть может потребовать и дополнительной инфраструктуры, из-за чего разработка приложения с server side rendering будет сложнее.

Static site generation (SSG)
Статические генераторы сайтов позволяют создать приложение, используя статические данные и шаблонизатор. На выходе получается многостраничный сайт. Отличие от классического многостраничного сайта в том, что большинство инструментов для статической генерации поддерживают SPA-фреймворки. Это позволяет объединить плюсы статического и SPA мира.
Самый распространённый пример SSG — это персональный блог. У нас есть тексты статей, а с помощью шаблонизатора эти статьи превращаются в готовые html-странички. Эта страничка и сама Дока, которую вы сейчас читаете, разработана с помощью статической генерации.
Когда говорят об SSG, то часто упоминают Jamstack. Слово Jamstack — это объединение первых букв от слов JavaScript, API, Markdown и слова stack, что в данном случае означает «набор технологий». Технически Jamstack это подход к разработке сайтов и приложений основанный на перечисленных технологиях. Источником данных выступает Markdown (например текст статей блога), JavaScript вместе с React «оживляет» приложение, а с помощью API можно запрашивать наши данные.
Jamstack хорошо подходит для создания сайтов, наполненных статичным контентом, а SPA-фреймворки помогают создать хороший пользовательский опыт, получая при этом плюсы статических сайтов.

Progressive Web Applications (PWA)
PWA это набор технологий, который позволяет превратить сайт в полноценное приложение. Такое приложение можно установить из браузера себе на компьютер или на телефон. Эта трансформация позволяет веб-приложениям функционировать почти как нативные, например, работать в офлайне или присылать уведомления.
В PWA можно превратить практически любой сайт, главное чтобы он соответствовал требованиям и поддерживал необходимые технологии (Service Worker, HTTPS и так далее).
Конечно такое приложение нельзя считать полноценно нативным, здесь имеются все те же ограничения в веб-технологиях, но это отличная возможность превратить свой сайт в устанавливаемое приложение.
Заключение
Мы рассмотрели самые распространённые виды веб-приложений, не углубляясь в детали их реализации. Каждый из описанных подходов имеет свои особенности, и потому выбор стоит делать исходя из целей, которые хочется достичь.
Например, переход между многостраничным может быть затруднён если есть проблемы с сетью, при этом одностраничное приложение может продолжать работать и переходить по страницам. Но одностраничные приложения так же могут страдать от проблем с производительностью.
Эти знания должны стать хорошим путеводителем в выборе подходящего типа приложения.
Разработка простых современных JavaScript-приложений с использованием Webpack и прогрессивных веб-технологий
Думали ли вы о том, чтобы воспользоваться при разработке своего очередного веб-проекта простейшим из существующих набором технологий? Если это так — значит материал, перевод которого мы публикуем сегодня, написан специально для вас.
JavaScript-фреймворки существуют для того чтобы помочь нам создавать приложения, обладающие сходными возможностями, используя обобщённый подход. Однако многим приложениям вся та мощь, которую дают фреймворки, не нужна. Использование какого-нибудь фреймворка в проекте небольшого или среднего масштаба, к которому предъявляются некие специфические требования, вполне может оказаться ненужной тратой сил и времени.

В этой статье мы поговорим о применении современных технологий при разработке веб-приложений, возможности которых не ограничены возможностями фреймворков. Кстати, если вам это нужно, то вы, с использованием описываемых здесь технологий, сможете создать собственный узкоспециализированный фреймворк. Чистый JavaScript и другие базовые веб-технологии дают разработчикам возможность делать то, что им нужно, не ограничивая себя рамками применяемых ими инструментов.
Обзор
Прежде чем мы приступим к делу, давайте обсудим средства, которые нам понадобятся.
▍Архитектура приложения
Для того чтобы обеспечить высокую скорость загрузки приложения и удобство работы с ним, мы будем пользоваться следующими шаблонами проектирования:
- Архитектура App Shell.
- Паттерн PRPL (Push, Render, Pre-cache, Lazy loading).
▍Система сборки проекта
В нашем проекте понадобится качественная, настроенная в соответствии с нашими нуждами, система сборки. Здесь мы будем использовать Webpack, предъявляя к системе сборки проекта следующие требования:
- Поддержка ES6 и возможностей динамического импорта ресурсов.
- Поддержка SASS и CSS.
- Раздельная настройка режимов разработки и реальной работы приложения.
- Возможность автоматической настройки сервис-воркеров.
▍Современные возможности JavaScript
Мы будем пользоваться минимальным набором современных возможностей JavaScript, позволяющим нам разработать то, что нам нужно. Вот о каких возможностях идёт речь:
- Модули.
- Разные способы создания объектов (объектные литералы, классы).
- Динамический импорт ресурсов.
- Стрелочные функции.
- Шаблонные литералы.
Архитектура приложения
Появление прогрессивных веб-приложений (Progressive Web Application, PWA) способствовало и приходу в веб-разработку новых архитектурных решений. Это позволило веб-приложениям быстрее загружаться и выводиться на экран. Комбинация архитектуры App Shell и паттерна PRPL может привести к тому, что веб-приложение будет быстрым и отзывчивым, похожим на обычное приложение.
▍Что такое App Shell и PRPL?
App Shell — это архитектурный паттерн, применяемый для разработки PWA, при использовании которого в браузер пользователя, при загрузке сайта, отправляют минимальный объём критически важных для работы сайта ресурсов. В состав этих материалов обычно входят все ресурсы, необходимые для первого вывода приложения на экран. Подобные ресурсы можно и кэшировать с использованием сервис-воркера.
Аббревиатура PRPL расшифровывается следующим образом:
- Push — отправка клиенту критически важных ресурсов для исходного маршрута (в частности, с использованием HTTP/2).
- Render — вывод исходного маршрута.
- Pre-cache — заблаговременное кэширование оставшихся маршрутов или ресурсов.
- Lazy load — «ленивая» загрузка частей приложения по мере того, как в них возникает необходимость (в частности — по запросу пользователя).
▍Реализация App Shell и PRPL в коде
Паттерны App Shepp и PRPL используются совместно. Это позволяет реализовывать передовые подходы к разработке веб-проектов. Вот как выглядит паттерн App Shell в коде:
html < box-sizing: border-box; >*, *:after, *:before < box-sizing: inherit; >body < margin: 0; padding: 0; font: 18px 'Oxygen', Helvetica; background: #ececec; >header < height: 60px; background: #512DA8; color: #fff; display: flex; align-items: center; padding: 0 40px; box-shadow: 1px 2px 6px 0px #777; >h1 < margin: 0; >.banner < text-decoration: none; color: #fff; cursor: pointer; >main < display: flex; justify-content: center; height: calc(100vh - 140px); padding: 20px 40px; overflow-y: auto; >button < background: #512DA8; border: 2px solid #512DA8; cursor: pointer; box-shadow: 1px 1px 3px 0px #777; color: #fff; padding: 10px 15px; border-radius: 20px; >.button < display: flex; justify-content: center; >button:hover < box-shadow: none; >footerVanilla Todos PWA ▍ Vanilla Todos PWA
Изучив этот код, можно понять, что шаблон App Shell предусматривает создание «оболочки» приложения, которая представляет собой его «скелет», содержащий минимум разметки. Разберём этот код (здесь и далее фрагменты кода, на которые мы будем ссылаться при разборе, отмечены комментариями, наподобие ).
- Фрагмент №1. Важнейшие стили встроены в разметку, а не представлены в виде отдельных файлов. Сделано это для того чтобы CSS-код был бы обработан непосредственно при загрузке HTML-страницы.
- Фрагмент №2. Здесь представлена «оболочка» приложения. Этими областями позже будет управлять JavaScript-код. Особенно это относится к тому, что будет находиться в теге main с идентификатором app ( ).
- Фрагмент №3. Тут в дело вступают скрипты. Атрибут async позволяет не блокировать парсер во время загрузки скриптов.
Однако если мы не используем сервис-воркер для кэширования «оболочки» приложения, то мы не получим выигрыша в производительности, например, при повторных загрузках страницы.
Ниже показан код сервис-воркера, кэширующего «скелет» и все статические ресурсы приложения.
var staticAssetsCacheName = 'todo-assets-v3'; var dynamicCacheName = 'todo-dynamic-v3'; // Начало фрагмента №1 self.addEventListener('install', function (event) < self.skipWaiting(); event.waitUntil( caches.open(staticAssetsCacheName).then(function (cache) < cache.addAll([ '/', "chunks/todo.d41d8cd98f00b204e980.js","index.html","main.d41d8cd98f00b204e980.js" ] ); >).catch((error) => < console.log('Error caching static assets:', error); >) ); >); // Конец фрагмента №1 // Начало фрагмента №2 self.addEventListener('activate', function (event) < if (self.clients && clients.claim) < clients.claim(); >event.waitUntil( caches.keys().then(function (cacheNames) < return Promise.all( cacheNames.filter(function (cacheName) < return (cacheName.startsWith('todo-')) && cacheName !== staticAssetsCacheName; >) .map(function (cacheName) < return caches.delete(cacheName); >) ).catch((error) => < console.log('Some error occurred while removing existing cache:', error); >); >).catch((error) => < console.log('Some error occurred while removing existing cache:', error); >)); >); // Конец фрагмента №2 // Начало фрагмента №3 self.addEventListener('fetch', (event) => < event.respondWith( caches.match(event.request).then((response) => < return response || fetch(event.request) .then((fetchResponse) =>< return cacheDynamicRequestData(dynamicCacheName, event.request.url, fetchResponse.clone()); >).catch((error) => < console.log(error); >); >).catch((error) => < console.log(error); >) ); >); // Конец фрагмента №3 function cacheDynamicRequestData(dynamicCacheName, url, fetchResponse) < return caches.open(dynamicCacheName) .then((cache) =>< cache.put(url, fetchResponse.clone()); return fetchResponse; >).catch((error) => < console.log(error); >); >Разберём этот код.
- Фрагмент №1. Обработка события install сервис-воркера помогает кэшировать статические ресурсы. Здесь можно поместить в кэш ресурсы «скелета» приложения (CSS, JavaScript, изображения, и так далее) для первого маршрута (в соответствии с наполнением «скелета»). Кроме того, можно загрузить и другие ресурсы приложения, сделав так, чтобы оно могло бы работать без подключения к интернету. Кэширование ресурсов, помимо кэширования «скелета», соответствует шагу Pre-cache паттерна PRPL.
- Фрагмент №2. При обработке события activate выполняется очистка неиспользуемых кэшей.
- Фрагмент №3. В этих строках кода выполняется загрузка ресурсов из кэша в том случае, если они там есть. В противном случае выполняются сетевые запросы. Кроме того, если сделан сетевой запрос на получение ресурса, это означает, что этот ресурс ещё не кэширован. Такой ресурс помещают в новый отдельный кэш. Этот сценарий помогает кэшировать динамические данные приложения.
Система сборки проекта
Одной только хорошей архитектуры, без достойной системы сборки проекта, недостаточно для создания качественного приложения. Тут нам и пригодится Webpack. Существуют и другие средства для сборки проектов (бандлеры), например — Parcel и Rollup. Но то, что мы будем реализовывать на базе Webpack, можно сделать и с использованием других средств.
Здесь мы поговорим о том, как интересующие нас возможности связаны с плагинами для Webpack. Это позволит вам быстро ухватить суть создаваемой нами системы сборки. Подбор плагинов для бандлера и его правильная настройка — это важнейший шаг на пути к качественной системе сборки проекта. Вы, освоив эти принципы, сможете пользоваться ими и в будущем, при работе над собственными приложениями.
Непросто настраивать инструменты наподобие Webpack с нуля. В таких случаях полезно иметь под рукой какое-нибудь хорошее справочное руководство. Таким руководством, с использованием которого написана соответствующая часть данного материала, стала эта статья. Если у вас возникнут какие-то сложности с Webpack — обращайтесь к ней. Теперь давайте вспомним и реализуем те требования к системе сборки проекта, о которых мы говорили в самом начале.
▍Поддержка ES6 и возможностей динамического импорта ресурсов
Для реализации этих возможностей нам пригодится Babel — популярный транспилятор, который позволяет преобразовывать код, написанный с использованием возможностей ES6, в код, который может выполняться в ES5-средах. Для того чтобы наладить работу Babel с Webpack, мы можем воспользоваться следующими пакетами:
- @babel/core
- @babel/plugin-syntax-dynamic-import
- @babel/preset-env
- babel-core
- babel-loader
- babel-preset-env
В ходе настройки Babel строка presets этого файла используется для настройки Babel на транспиляцию ES6 в ES5, а строка plugins — для того, чтобы в Webpack можно было бы пользоваться динамическим импортом.
Вот как Babel используется с Webpack (тут приведён фрагмент файла настроек Webpack — webpack.config.js ):
module.exports = < entry: < // Входные файлы >, output: < // Выходные файлы >, module: < rules: [ < test: /\.js$/, exclude: /node_modules/, use: < loader: 'babel-loader' >> ] >, plugins: [ // Плагины ] >;В разделе rules этого файла описывается использование загрузчика babel-loader для настройки процесса транспиляции. Остальные части этого файла, ради краткости, опущены.
▍Поддержка SASS и CSS
Для обеспечения поддержки нашей системой сборки проектов SASS и CSS нам понадобятся следующие плагины:
- sass-loader
- css-loader
- style-loader
- MiniCssExtractPlugin
module.exports = < entry: < // Входные файлы >, output: < // Выходные файлы >, module: < rules: [ < test: /\.js$/, exclude: /node_modules/, use: < loader: 'babel-loader' >>, < test: /\.scss$/, use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ] >] >, plugins: [ new MiniCssExtractPlugin(< filename: '[name].css' >), ] >;Загрузчики регистрируются в разделе rules . Так как мы используем плагин для извлечения CSS-стилей, в раздел plugins вносится соответствующая запись.
▍Раздельная настройка режимов разработки и реальной работы приложения
Это — чрезвычайно важная часть процесса сборки приложения. Всем известно, что при создании приложения одни настройки применяются для сборки той его версии, которая используется при разработке, а другие — для его продакшн-версии. Вот перечень пакетов, которые нам здесь пригодятся:
- clean-webpack-plugin : для очистки содержимого папки dist .
- compression-webpack-plugin : для сжатия содержимого папки dist .
- copy-webpack-plugin : для копирования статических ресурсов, например — файлов, из папок с исходными данными приложения в папку dist .
- html-webpack-plugin : для создания файла index.html в папке dist .
- webpack-md5-hash : для хэширования файлов приложения в папке dist .
- webpack-dev-server : для запуска локального сервера, используемого в ходе разработки.
const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const WebpackMd5Hash = require('webpack-md5-hash'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin'); module.exports = (env, argv) => (< entry: < main: './src/main.js' >, devtool: argv.mode === 'production' ? false : 'source-map', output: < path: path.resolve(__dirname, 'dist'), chunkFilename: argv.mode === 'production' ? 'chunks/[name].[chunkhash].js' : 'chunks/[name].js', filename: argv.mode === 'production' ? '[name].[chunkhash].js' : '[name].js' >, module: < rules: [ < test: /\.js$/, exclude: /node_modules/, use: < loader: 'babel-loader' >>, < test: /\.scss$/, use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ] >] >, plugins: [ new CleanWebpackPlugin('dist', <>), new MiniCssExtractPlugin(< filename: argv.mode === 'production' ? '[name].[contenthash].css' : '[name].css' >), new HtmlWebpackPlugin(< inject: false, hash: true, template: './index.html', filename: 'index.html' >), new WebpackMd5Hash(), new CopyWebpackPlugin([ // < // from: './src/assets', // to: './assets' // >, // < // from: 'manifest.json', // to: 'manifest.json' // >]), new CompressionPlugin(< algorithm: 'gzip' >) ], devServer: < contentBase: 'dist', watchContentBase: true, port: 1000 >>);Вся конфигурация Webpack представлена в виде функции, которая принимает два аргумента. Здесь использован аргумент argv , который представляет аргументы, передаваемые этой функции при выполнении команд webpack или webpack-dev-server . Вот как описание этих команд выглядит в файле проекта package.json :
"scripts": < "build": "webpack --mode production && node build-sw", "serve": "webpack-dev-server --mode=development --hot", >,В результате, если мы выполним команду npm run build , будет выполнена сборка продакшн-версии приложения. Если выполнить команду npm run serve , будет запущен сервер разработки, поддерживающий процесс работы над приложением.
В разделах plugins и devServer вышеприведённого файла показана настройка плагинов и сервера разработки.
В разделе, который начинается со строи new CopyWebpackPlugin , задают ресурсы, которые нужно скопировать из исходных материалов приложения.
▍Настройка сервис-воркера
Все мы знаем о том, что ручное составление списков файлов, например, предназначенных для кэширования, довольно-таки скучное занятие. Поэтому здесь мы воспользуемся специальным скриптом сборки сервис-воркера, который находит файлы в папке dist и добавляет их в качестве содержимого кэша в шаблоне сервис-воркера. После этого файл сервис-воркера будет записан в папку dist . Те концепции, о которых мы говорили в применении к сервис-воркерам, не меняются. Вот код скрипта build-sw.js :
const glob = require('glob'); const fs = require('fs'); const dest = 'dist/sw.js'; const staticAssetsCacheName = 'todo-assets-v1'; const dynamicCacheName = 'todo-dynamic-v1'; // Начало фрагмента №1 let staticAssetsCacheFiles = glob .sync('dist/**/*') .map((path) => < return path.slice(5); >) .filter((file) => < if (/\.gz$/.test(file)) return false; if (/sw\.js$/.test(file)) return false; if (!/\.+/.test(file)) return false; return true; >); // Конец фрагмента №1 const stringFileCachesArray = JSON.stringify(staticAssetsCacheFiles); // Начало фрагмента №2 const serviceWorkerScript = `var staticAssetsCacheName = '$'; var dynamicCacheName = '$'; self.addEventListener('install', function (event) < self.skipWaiting(); event.waitUntil( caches.open(staticAssetsCacheName).then(function (cache) < cache.addAll([ '/', $] ); >).catch((error) => < console.log('Error caching static assets:', error); >) ); >); self.addEventListener('activate', function (event) < if (self.clients && clients.claim) < clients.claim(); >event.waitUntil( caches.keys().then(function (cacheNames) < return Promise.all( cacheNames.filter(function (cacheName) < return (cacheName.startsWith('todo-')) && cacheName !== staticAssetsCacheName; >) .map(function (cacheName) < return caches.delete(cacheName); >) ).catch((error) => < console.log('Some error occurred while removing existing cache:', error); >); >).catch((error) => < console.log('Some error occurred while removing existing cache:', error); >)); >); self.addEventListener('fetch', (event) => < event.respondWith( caches.match(event.request).then((response) => < return response || fetch(event.request) .then((fetchResponse) =>< return cacheDynamicRequestData(dynamicCacheName, event.request.url, fetchResponse.clone()); >).catch((error) => < console.log(error); >); >).catch((error) => < console.log(error); >) ); >); function cacheDynamicRequestData(dynamicCacheName, url, fetchResponse) < return caches.open(dynamicCacheName) .then((cache) =>< cache.put(url, fetchResponse.clone()); return fetchResponse; >).catch((error) => < console.log(error); >); > `; // Конец фрагмента №2 // Начало фрагмента №3 fs.writeFile(dest, serviceWorkerScript, function(error) < if (error) return; console.log('Service Worker Write success'); >); // Конец фрагмента №3 Разберём этот код.
- Фрагмент №1. Здесь список файлов из папки dist помещается в массив staticAssetsCacheFiles .
- Фрагмент №2. Это — шаблон сервис-воркера, о котором мы говорили. При формировании готового кода используются переменные. Это делает шаблон универсальным, позволяя использовать его в будущем, в ходе развития проекта. Шаблон нам, кроме того, нужен из-за того, что в него мы добавляем сведения о содержимом папки dist , которое может со временем меняться. Для этого используется константа stringFileCachesArray .
- Фрагмент №3. Здесь только что сформированный код сервис-воркера, хранящийся в константе serviceWorkerScript , записывается в файл, находящийся по адресу dist/sw.js .
Представленный здесь скрипт для сборки сервис-воркера значительно облегчает задачу организации кэширования файлов. Надо отметить, что этот скрипт уже нашёл применение в реальном проекте.
Если вы хотите воспользоваться специальной библиотекой, предназначенной для решения задачи работы прогрессивных веб-приложений в оффлайн-режиме — взгляните на Workbox. Она отличается очень интересными возможностями, поддающимися настройке.
▍Обзор пакетов, используемых в проекте
Вот файл package.json нашего проекта, в котором можно найти сведения о пакетах, используемых в этом проекте:
< "name": "vanilla-todos-pwa", "version": "1.0.0", "description": "A simple todo application using ES6 and Webpack", "main": "src/main.js", "scripts": < "build": "webpack --mode production && node build-sw", "serve": "webpack-dev-server --mode=development --hot" >, "keywords": [], "author": "Anurag Majumdar", "license": "MIT", "devDependencies": < "@babel/core": "^7.2.2", "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/preset-env": "^7.2.3", "autoprefixer": "^9.4.5", "babel-core": "^6.26.3", "babel-loader": "^8.0.4", "babel-preset-env": "^1.7.0", "clean-webpack-plugin": "^1.0.0", "compression-webpack-plugin": "^2.0.0", "copy-webpack-plugin": "^4.6.0", "css-loader": "^2.1.0", "html-webpack-plugin": "^3.2.0", "mini-css-extract-plugin": "^0.5.0", "node-sass": "^4.11.0", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "terser": "^3.14.1", "webpack": "^4.28.4", "webpack-cli": "^3.2.1", "webpack-dev-server": "^3.1.14", "webpack-md5-hash": "0.0.6" >>Если говорить о поддержке подобных проектов, то надо отметить, что инструменты в экосистеме Webpack обновляются довольно часто. Нередко случается так, что существующие плагины заменяются новыми. Поэтому важно, принимая решения о том, нужно ли, вместо каких-то пакетов использовать более новые, ориентироваться не на сами пакеты, а на те возможности, которые они должны реализовывать. Собственно говоря, именно поэтому выше мы и говорили о том, какую роль играет тот или иной пакет.
Современные возможности JavaScript
В ходе разработки веб-приложения у программиста есть выбор — писать ли собственные реализации таких возможностей, как обнаружение изменений, маршрутизация, хранение данных, или пользоваться существующими пакетами.
Сейчас мы поговорим о минимальном наборе технологий, необходимых для обеспечения работы нашего проекта. При необходимости этот набор технологий можно расширить с использованием существующих фреймворков или пакетов.
▍Модули
Мы будем пользоваться возможностями ES6 по импорту и экспорту модулей, рассматривая каждый файл в виде ES6-модуля. Эта возможность часто встречается в популярных фреймворках, вроде Angular и React, пользоваться ей очень удобно. Благодаря имеющейся у нас конфигурации Webpack мы можем пользоваться выражениями импорта и экспорта ресурсов. Вот как это выглядит в файле app.js :
import < appTemplate >from './app.template'; import < AppModel >from './app.model'; export const AppComponent = < // Код компонента App. >;▍Разные способы создания объектов
Создание компонентов — это важная часть процесса разработки нашего приложения. Тут вполне можно воспользоваться каким-нибудь современным средством, наподобие веб-компонентов, но мы, для того, чтобы не усложнять проект, будем пользоваться обычными объектами JavaScript, создавать которые можно либо с использованием объектных литералов, либо используя синтаксис классов, появившийся в стандарте ES6.
Особенность использования классов для создания объектов заключается в том, что после описания класса нужно создать на его основе экземпляр объекта, а после этого экспортировать этот объект. Для того чтобы упростить всё ещё сильнее, мы будем пользоваться здесь обычными объектами, создаваемыми с помощью объектных литералов. Вот код файла app.js , в котором можно видеть их применение.
import < appTemplate >from './app.template'; import < AppModel >from './app.model'; export const AppComponent = < init() < this.appElement = document.querySelector('#app'); this.initEvents(); this.render(); >, initEvents() < this.appElement.addEventListener('click', event => < if (event.target.className === 'btn-todo') < import( /* webpackChunkName: "todo" */ './todo/todo.module') .then(lazyModule =>< lazyModule.TodoModule.init(); >) .catch(error => 'An error occurred while loading Module'); > >); document.querySelector('.banner').addEventListener('click', event => < event.preventDefault(); this.render(); >); >, render() < this.appElement.innerHTML = appTemplate(AppModel); >>;Здесь мы формируем и экспортируем компонент AppComponent , которым сразу же можно пользоваться в других частях приложения.
Вы вполне можете использовать в подобных ситуациях классы ES6 или веб-компоненты, разрабатывая проект в стиле, который ближе к декларативному, чем тот, который используется здесь. Здесь же, для того чтобы не усложнять учебный проект, используется императивный подход.
▍Динамический импорт ресурсов
Помните о том, что мы, говоря о паттерне PRPL, ещё не разобрались с той его частью, которая представлена буквой L (Lazy loading)? Динамический импорт ресурсов — это то, что поможет нам организовать ленивую загрузку компонентов или модулей. Так как мы совместно используем архитектуру App Shell и паттерн PRPL для кэширования «скелета» приложения и его ресурсов, в ходе динамического импорта производится загрузка ресурсов из кэша, а не из сети.
Обратите внимание на то, что если бы мы использовали лишь архитектуру App Shell, то оставшиеся ресурсы приложения, то есть, содержимое папки chunks , не были бы кэшированы.
Пример динамического импорта ресурсов можно увидеть в вышеприведённом фрагменте кода компонента AppComponent , в частности, там, где настраивается обработчик события щелчка по кнопке (речь идёт о методе объекта initEvents() ). А именно, если пользователь приложения щёлкнет по кнопке btn-todo , будет загружен модуль todo.module . Этот модуль представляет собой обычный JavaScript-файл, который содержит набор компонентов, представленных в виде объектов.
▍Стрелочные функции и шаблонные литералы
Стрелочные функции особенно полезны в тех случаях, когда нужно, чтобы ключевое слово this в таких функциях указывало бы на контекст, в котором объявлена функция. Помимо этого стрелочные функции позволяют писать код, который оказывается компактнее, чем при использовании обычных функций. Вот пример такой функции:
export const appTemplate = model => ` `;▍ $
Стрелочная функция appTemplate принимает модель (параметр model ) и возвращает HTML-строку, содержащую данные, взятые из модели. Формирование строки выполняется с использованием технологии шаблонных литералов. Ими удобно пользоваться для представления многострочных конструкций, в которые нужно добавлять какие-либо данные.
Вот небольшой совет, касающийся шаблонизации компонентов и создания компонентов, которые подходят для повторного использования. Он заключается в использовании метода массива reduce() для сборки HTML-строк:
const WorkModel = [ < id: 1, src: '', alt: '', designation: '', period: '', description: '' >, < id: 2, src: '', alt: '', designation: '', period: '', description: '' >, //. ]; const workCardTemplate = (cardModel) => `$ $ `; export const workTemplate = (model) => `$ `;Work This area signifies work experience
$ html + workCardTemplate(card), '')> На самом деле, в этом фрагменте кода выполняется серьёзный объём работы. При этом он устроен просто и понятен на интуитивном уровне. Надо отметить, что здесь используются те же приёмы, которые характерны для современных фреймворков.
- В начале файла находится команда объявления массива model . Это — пример массива с данными модели, который можно обработать с помощью метода reduce() для того чтобы реализовать шаблон, подходящий для повторного использования.
- В конце файла можно найти команду model.reduce , которая помогает формировать HTML-строку, содержащую множество компонентов, подходящих для повторного использования. Эта функция принимает, в качестве первого аргумента, аккумулятор, а в качестве второго — значения массива.
Демонстрационное приложение
Рассмотрим демонстрационное Todo-приложение, которое создано с использованием рассмотренных технологий. Вот как выглядит работа с ним.
Демонстрационное приложение
Поэкспериментировать с ним самостоятельно можно здесь. Вот репозиторий с кодом приложения. Можете его клонировать и, чтобы лучше разобраться в том, что мы обсуждали, как следует проанализировать его код.
Пример продакшн-приложения
Продакшн-приложение, о котором идёт речь, представляет собой сайт-портфолио, созданный с нуля с использованием разобранных здесь технологий. Одностраничное приложение, которым является этот проект, собрано из модулей и компонентов. Те возможности и та гибкость, которые доступны разработчику при использовании чистого JavaScript и базовых веб-технологий, позволяют добиваться замечательных результатов.
Вот как выглядит работа с сайтом, о котором идёт речь.
Сайт-портфолио
Вот ссылка на сайт. А вот результаты анализа производительности этого сайта с помощью Lighthouse.

Анализ производительности сайта
Итоги
Некоторые проекты, ради быстрого достижения желаемого результата, имеет смысл создавать на чистом JavaScript, без использования фреймворков. Такой подход открывает перед программистом свободу самовыражения, позволяя ему создавать именно то, что ему нужно, не ограничивая себя возможностями и особенностями фреймворков.
Уважаемые читатели! Планируете ли вы использовать подход к разработке веб-приложений, предложенный в этом материале?

- Блог компании RUVDS.com
- Веб-разработка
- JavaScript
Создание приложений на JavaScript
Когда речь заходит о языках программирования, главная специализация которых заключается в удобстве и интерактивности веб-страниц, первым делом вспоминается JavaScript.
Преимущества разработки приложений на JavaScript
Популярнейшее применение JS-языка — веб-программирование и наполнение сайта интерактивным контентом, однако на этом его использование не ограничивается. Для проработки бэкенда (бэкенд отвечает за осуществление правильной работы внутренней части сайта) JS также подходит. Преимуществ использования JS масса:
- Создание анимированных подсказок, всплывающих объявлений и других анимаций с помощью JS упрощено до интуитивно понятного уровня;
- Так как часто код в браузерах выполняет именно JS, проработкой виджетов и расширений для них можно заниматься через JS;
- Распространенность и поддержка яваскрипт большинством ОС не требует от разработчика выпуска специальных версий под каждую систему;
- Обучение языку также можно отнести к его плюсам. Самостоятельное изучение и запуск программ на JS доступно каждому.
Основное распространение JS получил за счет возникшей необходимости информационных сайтов компаний и брендов. У каждой крупной фирмы сейчас есть свой сайт с описанием услуг, контактными данными и полезными статьями. Обширный функционал ЯваСкрипт серьезно упростил создание подобного веб-контента для сайтов.
Недостатки у JS также присутствуют (бесполезность компилятора в качестве инструмента проверки кода на ошибки; недостаточная безопасность; нужда в использовании сторонних библиотек и др.), однако за счет функционала в плане верстки веб-страниц функционал этого инструментария востребован у программистов.
Особенности разработки веб-приложений с javascript
Распространенность языка программирования привела к интересу к нему со стороны программистов. Сегодня даже начинающий программист с базовым представлением об особенностях работы по написанию кода на языке JS. В кратком виде к особенностям разработки веб-контента на JavaScript отнесем следующие моменты:
- Скорость работы и обработки веб-страниц за счет отсутствия необходимости в обращении к серверам. За счет этого удается экономить трафик и время;
- Легкий доступ к программированию настроек интерфейса сайта;
- Обилие фреймворков и готовых библиотек — особенность языка, за счет которой разработка понятна и доступна.
Полная интеграция HTML и CSS делает JavaScript удобным языком программирования для веб-приложений и страниц.
Возможности JavaScript
В плане разработки веб-содержимого для браузеров возможности яваскрипта практически безграничны. Понятно, что возможности этого языка зависят от окружающего его программного обеспечения, но по факту любая задача по разработке веб-контента для страниц невозможна без использования JS.
К отличительным моментам инструментария отнесем следующее:
- Добавление анимаций и эффектов;
- Обработка и реакция на перемещения курсора мыши и нажатий клавиш;
- Низкая вероятность выполнения вредоносного кода (у JS нет доступа к внутренним файлам компьютера);
- Смена стилей и замена тегов в содержимом HTML-элементов.
Легкость изучения делает этот инструмент программирования одним из популярнейших у начинающих программистов. Несмотря на всю простоту конструкций в яваскрипт имеются все фундаментальные моменты написания кода: структуры с данными и алгоритмы.
Создание интернет-магазинов без использования инструментария яваскрипт сегодня невозможно. Т.к. у JSнет серьезных конкурентов, он используется в подавляющем большинстве работ по запуску сайтов для онлайн-магазинов. Для получения максимальной пользы от работы использовать его следует в разных средах написания кода, а именно с помощью следующих библиотек и фреймворков:
Большая часть из них довольно сложно поддается изучению, но повсеместное распространение продуктов на ЯС позволило разработчикам создать отдельное приложение для работы с кодом — AngularJS. Фреймворк AngularJS считается неотъемлемой составляющей при работе с кодом яваскрипт. Главная задача AngularJS — разработка одностраничных приложений. Расширение браузерных программ и упрощение тестирования и разработки также считается целями AngularJS-фреймворка. Уроков по изучению данного инструментария в сети множество, поэтому яваскрипт получает все большее распространение на фоне того факта, что конкурентов у него по-прежнему нет.
Создание и наполнение веб-сайтов необходимо для упрощенного восприятия посетителем ресурса. Внедрение на страницы анимаций, графики, всплывающих подсказок и рекомендаций – все это при правильном подходе серьезно упрощает процесс навигации по сайту. Понятно, что каждый онлайн-магазин задачей ставит привлечение клиентов, поэтому наличие информативного и интерактивного сайта повышает вероятность покупки услуги или товара.
Программирование сайтов ЯваСкриптом повышает вероятность успеха, т.к. нет другого подходящего инструментария для выполнения этой задачи попросту нет и не предвидится в ближайшем будущем.
Самостоятельно без опыта заниматься написанием кода для запуска онлайн-магазина сложно, поэтому стоит доверить это занятие профессиональным программистам. Процесс создания интернет-магазина включает ряд работ: создание прототипа, написание кода, заполнение контентом, интеграция, тестирование и др.
Разработка веб-приложений: основные этапы
В обиходе всё, что мы открываем в браузере, называют сайтами, но это не совсем корректно. Сайт — это место, где люди получают информацию: читают, слушают и смотрят. Но есть еще веб-приложения: с ними человек взаимодействует — скажем, вносит оплату, оформляет бронь или играет в игру. То, что появляется в веб-приложении, зависит от запроса пользователя.
Разберемся, как проходит разработка веб-приложений, для чего такие приложения нужны бизнесу и как их создают.
Время чтения: 8 минут

Зачем нужны веб-приложения
Интернет-магазины, социальные сети, образовательные продукты, фото-, видео- и текстовые редакторы, игры, системы бронирования — все это и есть веб-приложения. Они устроены сложнее, чем обычные информационные сайты. Пользователь — не пассивный читатель, а участник бизнес-процесса, он взаимодействует с компанией. Информационные сайты без интерактивности бизнесу, конечно, тоже нужны, но их возможности ограничены. Например, это просто сайт-визитка.
Веб-приложения могут пригодиться, чтобы:
- Оказывать услуги пользователю в режиме онлайн: продавать товар, записывать на мероприятие, проводить курсы и вебинары.
- Решать внутренние задачи компании. Большим организациям веб-приложение может понадобиться, чтобы координировать сотрудников, выстраивать внутреннюю логистику. Например, с помощью веб-приложений можно проводить онбординг новых сотрудников и налаживать рабочие процессы с подрядчиками.
Разработка сайта для компании без интерактивности не дает всего этого спектра возможностей. Кроме того, именно интерактивность позволяет добавить геймификацию, делать опции для комментирования и общения пользователей. Все это помогает растить комьюнити вокруг бренда и повышать лояльность к компании. Через сайт можно рассказать пользователю о своей компании, но нельзя получить фидбек или оказать полезную услугу. Поскольку бизнес за последние годы стремительно переходит в онлайн-формат, веб-приложения становятся все более популярными. Для многих компаний именно цифровой сервис — основной источник монетизации.
Веб-приложения, которые человек открывает с браузера, как сайты, конкурируют с мобильными приложениями. Возможности и там, и там схожие. Какой вариант выбрать — нужно смотреть в каждом отдельном случае. Например, корпоративным таск-трекером удобнее пользоваться в вебе, а для сервиса доставки еды более актуальна будет разработка мобильного приложения . Есть и технология, которая совмещает два варианта: человек скачивает приложение на телефон, а работает оно из окна браузера — подробнее мы рассмотрим такую архитектуру в следующем разделе.
Виды веб-приложений
Способов разработки приложений много. От выбранного типа приложения будет зависеть цена, сроки и функциональность. Давайте рассмотрим каждый вид и определим, для каких задач будет оптимальна та или иная архитектура.
Прежде всего, приложения можно разделить на кастомные (написанные кодом) и ноукод (собранные в конструкторах). Современные ноукод-редакторы, скажем, Webflow или Bubble позволяют создавать интерактивные решения — к ним можно подключить платежную систему и сделать работающий интернет-магазин. Ноукод выбирают, потому что это быстро и дешево. Но такие решения подходят разве что для MVP или простых задач — например, лендингов или джоб-бордов с информацией о вакансиях и контактами рекрутёра. Функциональность получается очень ограниченной, потому что ноукод-инструменты — это конструктор с фиксированным набором элементов. Производительность таких приложений тоже ниже, чем у кастомных — большой трафик они не выдержат. Поэтому если вам нужен полноценный сервис, с прицелом на большую аудиторию, стоит остановиться на кастомных решениях.
Хотите больше узнать о специфике ноукод-решений и их отличия от классической разработки? Можете прочитать нашу статью: мы подробно разобрали специфику работы с конструкторами.
READ MORE Что такое «No-code»: простой способ сделать MVP или пустая трата времени и денег?
Приложения, написанные кодом, тоже различаются между собой — по своей архитектуре или системе организации программы. Давайте рассмотрим, какие они бывают.
Single Page Application — это одностраничное приложение. Для разработки таких приложений используют HTML и JavaScript. По сути, это разработка лендинга , только интерактивного. Но SPA могут быть достаточно сложными. Суть одностраничных приложений в том, что на сервере хранится одна HTML-страница, контент на которой обновляется по мере прокрутки или переходов по ссылкам. То есть когда вы нажимаете на кнопку, вы не переходите на новую страницу — элементы добавляются к уже загруженной. Например, по этому принципу работает Gmail.
- Разрабатывать такие приложения проще, чем многостраничные.
- Приложения работают быстро: контент на странице просто меняется по мере движения пользователя, его загрузка не требует много ресурсов.
- На одной странице проще сделать однообразный дизайн, а пользователь точно не потеряется и не запутается.
- Настройка SEO-оптимизации для SPA будет более трудоемкой, чем для других вариантов.
- Трудно гарантировать безопасность таких страниц: они больше подвержены взломам и утечкам, чем MPA и PWA, которые мы рассмотрим ниже.
Multi Page Application — это многостраничные приложения. Они позволяют пользователю не просто скроллить окно браузера, а переходить между отдельными страницами. И загрузка контента в таких приложениях происходит целыми страницами. Это значит, например, что если пользователь совершил оплату, в SPA подгрузится окошко с подтверждением, а в MPA страница оплаты полностью обновится. Пример многостраничного приложения — интернет-магазин Amazon.
- Простая SEO-оптимизация.
- Более привычный вариант для большинства пользователей, которые привыкли переходить между страницами.
- Если приложение сложное, с большим количеством функций, оно точно должно быть многостраничным. Переход по страницам позволяет пользователю легко попадать на нужные разделы. Скроллить огромное одностраничное приложение в начало, когда внезапно потребовалась какая-то информация оттуда, никому не захочется.
- Сложная и более дорогостоящая разработка и дизайн, чем для SPA.
Progressive Web Application — прогрессивные веб-приложения. Это что-то среднее между разработкой мобильного приложения и вебсайта. PWA можно сразу из браузера установить на главный экран смартфона в обход магазинов приложений. А ещё такие приложения работают офлайн и отправляют push-уведомления, но при этом открываются в браузере. Это возможно благодаря технологии Service Worker — скрипту, через который проходят все взаимодействия между фронтэндом и бэкендом. У этого скрипта есть доступ к кэшу и данным. По сути к большинству сайтов можно дописать Service Worker — и получится PWA. Поэтому часто на эту технологию переходят СМИ — например, The Washington Post.
- Сочетание офлайн- и онлайн- режима удобно для пользователя.
- Такие приложения можно сравнительно быстро разработать.
— Приложение быстро работает
Мы работаем на платформе Node.js для разработки бэкенда и React — для фронтенда.
С помощью такого стека можно реализовать любой вид архитектуры, который мы рассмотрели: от разработки лендингов до многостраничных и прогрессивных приложений. Дальнейшая работа зависит от конкретных бизнес-задач.
Кто занимается разработкой
Нанимать свою команду для разработки приложения — долго и дорого. По данным Indeed.com , расходы на найм одного сотрудника начинаются от $4000 без учёта зарплат. Чтобы сэкономить, можно обратиться за веб-приложениями к фрилансерам. Но зачастую это не лучшее решение. Для полноценного приложения нужна команда из аналитиков, дизайнеров и программистов, и вряд ли один человек будет обладать всеми знаниями сразу. А если вы нанимаете нескольких фрилансеров, вам придётся брать на себя работу менеджера проектов. Так что самый простой способ разработать сайт для компании — обратиться в студию, где над проектом будет работать опытная и слаженная команда.
В процессе создания веб-приложения участвуют:
- Аналитики — они помогают лучше изучить нишу, определить целевую аудиторию и понять, какая функциональность необходима для успеха на рынке.
- UX/UI-дизайнеры. Продумывают пользовательский путь и создают прототипы. Потом отрисовывают непосредственно дизайн сайта : кнопки, иконки и другие элементы интерфейса.
- Фронтенд-разработчики. Превращают дизайн сайта (макет) в работающий сайт: оживляют кнопки и блоки с помощью кода.
- Бэкенд-разработчики. Отвечают за функциональность: подключают базы данных, платежные системы, выстраивают внутреннюю логику приложения.
- Тестировщики. Проверяют приложение на баги и помогают выпустить на рынок продукт, который работает без ошибок.
Этапы разработки
Каждый специалист отвечает за свой этап в разработке веб-приложения. Тем не менее, этапы и их последовательность в разных студиях могут незначительно различаться. Мы расскажем о том, как устроен процесс в Purrweb и какое участие владельцу бизнеса нужно будет принимать в процессе.
В студию стоит идти, когда у вас уже есть готовая идея приложения и примерное понимание того, как оно будет функционировать. Для этого у предпринимателя должна быть экспертиза в выбранной отрасли. А вот изучение рынка можно делегировать специалистам. Аналитики разберутся, какую нишу может занять ваш продукт на рынке, на какую целевую аудиторию выгоднее ориентироваться, какая функциональность нужна этим людям и какую модель монетизации выбрать.
Результат: после работы с аналитиком вы будете четко понимать, для кого делаете приложение, какие задачи пользователей оно будет решать и как на этом зарабатывать.
Современные пользователи привыкли к продуманным и качественным интерфейсам. В условиях высокой конкуренции брендов, если что-то в приложении покажется человеку неудобным или непонятным, он просто перейдет по другой ссылке в поисковике. Поэтому важно продумать путь пользователя: какую последовательность действий он будет совершать и как элементы сайта будут отзываться на эти действия. UX-дизайнер создает прототип — на нем обозначены основные блоки и элементы, показано взаимодействие между ними.
Результат: Готовая схема приложения, в которой показаны блоки интерфейса и взаимосвязи между ними. По прототипу вы сможете оценить функциональность приложения и его доступность.

Задача дизайнера интерфейса — визуализировать блоки, которые придумал UX-дизайнер. UI-дизайн — это отрисовка иконок и кнопок, вёрстка экранов, подбор цветов и шрифтов и подготовка руководства по стилю UI для дальнейшей разработки. Если вы хотите узнать больше о работе UI-дизайнера, прочитайте наши статьи — о дизайн-процессе и о том, как мы делаем руководства по стилю для наших проектов.
Результат: вы увидите почти готовое приложение, только еще не работающее. Именно после этапа дизайна сайта можно утверждать точную стоимость и сроки разработки. Они будут зависеть от сложности проекта и пожеланий клиента по функциям и дизайну.

Разработчик фронтенда отвечает за внешнюю часть сайта, которую видят пользователи. Но фронтенд — это не только вёрстка макетов. Фронтенд-разработчик отвечает за адаптивный и отзывчивый дизайн — то есть чтобы сайт корректно отображался на разных устройствах и в браузерах разных версий. На этом этапе определяется процесс загрузки элементов, их кликабельность, анимация и другие микровзаимодействия.
Результат: дизайн становится интерактивным: можно нажимать кнопки, переходить по ссылкам. Но свои функции приложение ещё не выполняет.
Следующий этап — это разработка внутренней части: как приложение будет работать с базами данных, каким образом будет происходить оплата, бронь и другие процессы. Бэкенд-разработчик отвечает за корректную работу сайта, связь между компонентами приложения, хранение и структуру данных, логику алгоритмов и вычислений, и интеграцию с внешними сервисами — например, с платёжными системами и социальными сетями.
Результат: полностью работающее приложение.
Тестирование
Это необходимый этап, чтобы финальное приложение работало так, как было задумано. Главная задача тестировщика — проверить работу приложения перед релизом, чтобы команда вышла на рынок с качественным продуктом. Тестировщики изучают документацию продукта и составляют тест-кейсы — список функций, которые надо проверить, и их последовательность. Затем они вручную имитируют действия пользователя в разных сценариях или пишут скрипты для автоматического тестирования. После этого разработчики получают отчёт со списком ошибок и рекомендациями по исправлению.
Результат: приложение работает без ошибок, риск их появления сведён к минимуму.
После этого приложение можно запускать для пользователей. Но команда не прекращает над ним работать — она выходит на этап поддержки . После релиза разработчики обеспечивают стабильную работу приложения и чинят баги, найденные пользователями. А ещё на поддержке команда может специально собирать обратную связь от пользователей и улучшать качество продукта — например, добавлять новые фичи или менять дизайн уже готовых разделов приложения.
Стоимость разработки
Стоимость разработки веб-приложения зависит от его функциональности. Давайте рассмотрим самые популярные типы веб-приложений. В конце мы приведем подробную оценку этапов работы над каждым из них.
☝Разумеется, мы приводим только приблизительные цифры: итоговая цена приложения зависит от множества нюансов. Если нужно будет больше или, наоборот, меньше функций, то и стоимость изменится. Обычно финальную сумму можно назвать, когда готов дизайн: тогда уже точно понятно, как будет выглядеть приложение и что в нем будет.
Социальная сеть, в которой реализованы:
- чат;
- лента новостей с комментариями;
- публичные страницы или форумы;
- профиль пользователя.
Это приложение будет стоить у нас около 10 182 000 рублей.
Сервис-агрегатор для путешественников: с бронированием отелей, ж/д или авиабилетов. В нем должны быть:
- личный кабинет;
- поиск с фильтрами;
- блог с рекомендациями по турам;
- оплата
- рассылка.
Такое веб-приложение будет стоить примерно 7 845 000 рублей.
Вот подробная таблица, в которой расписаны все этапы разработки с количеством часов и стоимостью:
Вид работы Стоимость для соцсети Стоимость для агрегатора Аналитика 120 часов / 300.000 р. 120 часов / 300.000 р. UX-дизайн 260 часов / 910.000 р. 150 часов / 525.000 р. UI-дизайн Фронтенд 1600 часов / 5.600.000 р. 1200 часов / 4.200.000 р. Бэкенд 800 часов / 2.800.000 р. 600 часов / 2.100.000 Тестирование 540 часов / 972.000 р. 400 часов / 720.000 р. Создание веб-приложения — комплексный процесс, который требует сотрудничества с профессиональной командой. У нас в Purrweb есть большой опыт создания интернет-магазинов и других видов приложений в разных сферах. Например, недавно мы разрабатывали маркетплейс видеоконтента и веб-приложение для фитнеса .
Есть бизнес-идея? Обращайтесь к нам за консультацией!
Насколько публикация полезна?
Оцени эту статью!
15 оценок, среднее 4.8 из 5.
Оценок пока нет. Поставьте оценку первым.
Так как вы нашли эту публикацию полезной.
Подписывайтесь на нас в соцсетях!
