Эта статья представляет собой небольшой анализ и понимание архитектуры внешнего интерфейса веб-сайта с точки зрения стажера.
последовательность
Когда я впервые столкнулся с интерфейсом, он начался с простых html, css и js.В то время преобладающей концепцией WEB было разделение структуры, стиля и поведения, то есть html, css и js были разделены, разрабатывались независимо и общались друг с другом через ссылки и скрипты.
В начале небольшие проекты, с которыми я столкнулся, заключались в прямом развертывании html, css, js и других статических ресурсов на сервере, а затем в ответ на разные html-файлы в соответствии с маршрутизацией запросов.
Даже после изучения веб-пакета я все еще думаю, что роль веб-пакета заключается в сжатии файлов js и css, повышении скорости ответа сервера и оптимизации взаимодействия с пользователем, в то время как сжатые файлы min.css и min.js все еще развертываются на сервере.
Позже, после поступления на стажировку в компанию А, это действительно такой режим разработки.В то время, когда мы разрабатывали страницы h5, мы напрямую писали файлы html, css и js, а затем разворачивали их на сервер для прямого доступа к html.
Позже, поработав в компании Б, я постепенно соприкоснулся с тем, как выглядит настоящий фронтенд-инжиниринг.
Разделение передней и задней части
Часть бизнес-интерфейса некоторых традиционных крупномасштабных веб-сайтов для ПК использует архитектуру MVC, то есть после того, как каждый проект установлен, интерфейс и серверная часть согласовывают интерфейс и разрабатывают его отдельно (Java или PHP), а затем бэкэнд отвечает на запросы клиентов и возвращает определенные html-страницы.
Недостатком этого режима разработки состоит в том, что оно потребляет трудоемкость и трудоемкий, стоимость коммуникации и оригинальная копия совместной корректировки очень высоки, а небольшое изменение передней части необходимо совместно отрегулировать и изменять онлайн Передний конец и задний конец, который значительно увеличивает общую рабочую нагрузку.
Таким образом, современные крупномасштабные веб-сайты для ПК обычно используют архитектуру, которая разделяет интерфейс и серверную часть.Бизнес-функции клиентской и серверной частей конвергентны и могут разрабатываться и запускаться отдельно, не влияя друг на друга. что может значительно повысить эффективность работы.
Внешнее и внутреннее разделение обычно делятся на два типа:
- В среднем слое нет разделения на интерфейс и сервер;
- Существует переднее и заднее разделение среднего слоя. Здесь мы представим React, один из трех самых популярных фреймворков.
без промежуточного слоя Разделение интерфейса и сервера без промежуточного веб-слоя является относительно простым типом.Мы размещаем унифицированный шаблон html/pug и другие статические ресурсы, такие как css и js, на cdn.Каждый раз при доступе к странице шаблон напрямую возвращается пользователю. , а затем все узлы dom и другие данные в нем генерируются js.
Однако такое разделение переднего и заднего концов без промежуточного слоя имеет много недостатков:
- Время рендеринга первого экрана слишком велико;
- Не оптимизировано для SEO.
- со средним слоем
Разделение интерфейса и сервера с промежуточным слоем — это метод разделения интерфейса и сервера, используемый в общих крупномасштабных проектах.
С момента появления Node в 2009 г. клиентская часть постепенно занялась серверной частью, однако из-за собственных ограничений надежности Node не подходит в качестве внутреннего сервера для крупномасштабных проектов. традиционный интерфейс и серверная часть, мы также называем эту архитектуру внешнего интерфейса + узла «большой интерфейс».
Назад к шаблону На уровне узлов мы можем делать много вещей, самая основная из которых — возвращать различные шаблоны внешнего интерфейса.
Я использовал несколько интерфейсных шаблонов, и тот, который мне больше всего понравился, — это шаблон pug (ранее известный как jade).
Синтаксис в PUG - это синтаксис JS, который очень дружелюбна для инженеров передней стороны, а функция мопса очень мощна. Его можно использовать в качестве HTML-промежуточного программного обеспечения и идеально поддерживается узлом. Рекомендуется научиться использовать его здесь.Get Started.
сшивание данных
Во-вторых, когда веб-сайт становится все больше и больше, объем данных становится все больше и больше, когда сервисный слой разделен, будет много сервисных модулей, или когда наши данные разбросаны по разным серверам баз данных, или когда наши некоторые API-интерфейсы сторонние рекламные объявления должны быть встроены в интерфейсную страницу, узел может помочь нам завершить работу по объединению данных.
Поскольку скорость доступа сервера к интерфейсу на много порядков выше, чем у браузера, очень эффективно получить доступ к нескольким интерфейсам в узле и склеить их вместе.Склеенные данные можно напрямую передать в шаблон для js. использовать.
Но в целом более целесообразно обращаться к базовым сервисам или обращаться к данным с серверов данных на бэкенде, но всегда есть исключения.В крайнем случае мы можем выполнить сплайсинг данных на среднем уровне узла.
Этот режим, как правило, не рекомендуется, потому что ремонтопригодность слишком плохая, а безопасность также очень низкая.Как правило, в бэкэнде есть специальный модуль данных для доступа к базе данных и сервисам, а затем сшивание данных вместе.Мы только необходимо. Вызывая API на бэкэнде в узле, мы можем получить нужные нам данные.
Служба мониторинга
уровень узла может фиксировать некоторые необычные запросы или события, о которых сообщается на нашу стороннюю платформу мониторинга, такую как Sentry и т. д., и данные узла также могут нести часть статистической работы, некоторые пользователи будут затронуты сторонней платформой статистики данных для pm и аналитики данных для просмотра.
Узел также может взять на себя ответственность за мониторинг всего экземпляра.Когда аномалия приводит к тому, что загрузка ЦП или использование памяти превышают пороговое значение, механизм тревоги может быть запущен вовремя.
Но точно так же добавление уровня узла означает, что на веб-сайте есть еще один уровень мониторинга серверной части и вызова, и сложность работы значительно возрастет.
Рендеринг на стороне сервера
Можно сказать, что SSR (server-side-render) является одной из очень важных функций, она может помочь нам решить упомянутые выше проблемы, связанные со слишком большим временем рендеринга первого экрана и низкой поддержкой SEO.
Современные поисковые роботы обычно делятся на два типа:
- Количество краулеров, поддерживающих синтаксический анализ js, относительно невелико, представлено Google;
- Большинство краулеров, которые не поддерживают синтаксический анализ js, относятся к этому типу, и они в основном являются краулерами поисковых систем, отличных от Google. Для поисковых роботов Google не имеет значения, используется ли SSR в SEO, потому что в конечном итоге они могут сканировать обычные страницы.
Для поисковых систем, отличных от Google, нам нужно использовать SSR для отображения определенных узлов DOM для сканирования сканером.
И в этом тоже есть преимущество: пользователь может видеть содержимое страницы в процессе загрузки страницы, а не пустую страницу. Если вы не используете SSR, в процессе загрузки ресурсов на веб-странице она всегда будет для пользователя пустой, что может привести к потере пользователей.
Это картина, которую я вижу в первую секунду посещения станции B при скорости сети 50 кбит/с.Если станция B не использует технологию SSR, время может пройти после того, как пользователь увидит контент на первом экране.Пять или шесть секунд.
Вот простой код уровня узла, использующий SSR:
// 代码中使用了es6语法,不懂的可以先学习一下阮一峰老师的《ES6入门》
// 这个地方node如果没有使用babel的话,import会报错,可以直接使用require方法替换
import { renderToString } from 'react-dom/server';
import DemoContainer from 'containers/demo';
// 以koa2框架为例
module.exports = (ctx) => {
const props = {...};
// 这里的html就存放着我们组件render完之后的dom节点。
const html = renderToString(<Demo >);
// 这里以返回pug模板为例,第二个参数是要传入pug模板中的数据
ctx.render('demo.pug', {
__props: JSON.stringify(props),
html
});
};
Вот фрагмент кода от мопса:
// pug代码片段
body
#root
!{ html }
script.
window.__props = '!{ __props }'
При использовании SSR не забудьте убедиться, что интерфейсные и серверные компонентыpropsБудьте последовательны, так что здесь моя привычка ставить слой узлаpropsпрямой входящийwindowобъекта, а затем интерфейсные компоненты непосредственно изwindowприобретение объектаpropsВот и все.
Во время SSR компонент React будет выполняться толькоcomponentWillMount和renderДля создания структуры купола используются два жизненных цикла, а другие жизненные циклы и монтирование методов выполняются во внешнем интерфейсе.
Функции уровня узла не ограничиваются вышеперечисленными, поэтому я не буду подробно о них рассказывать.
Хотя SSR имеет много преимуществ, у него все же есть свои недостатки. Использование SSR означает, что вы заменяете некоторые функции, изначально принадлежащие пользовательскому клиенту, собственным сервером, что снизит производительность сервера и увеличит затраты.По сравнению с небольшими командами или командами с недостатком средств, вам следует тщательно выбирать, использовать ли SSR.
Внешний и внутренний изоморфизм
Говоря о SSR, мы должны упомянуть проблему изоморфизма интерфейсов и серверов. Изоморфизм означает, что интерфейс и нода используют один и тот же набор кода, первый экран рендерится сервером, а отрендеренный html напрямую передается браузеру для рендеринга, клиент отвечает за загрузку js, выполнение остальных жизненный цикл компонента и его монтирование из событий Define и т. д. Хороший набор внешнего и внутреннего изоморфного кода может значительно снизить нагрузку на обслуживание нашего кода и имеет очень эффективную эффективность выполнения.Как элегантно написать внешний и внутренний изоморфный код, также является технической задачей. и нам нужно планировать набор заранее.Внешняя архитектура.
例如:
import React, { Component } from "react";
import { Provider } from "react-redux";
import ReactDOM from "react-dom";
import Loadable from "react-loadable";
import { BrowserRouter, StaticRouter } from "react-router-dom";
// server side render
const SSR = App =>
class SSR extends Component<{
store: any;
url: string;
}> {
render() {
const context = {};
return (
<Provider store={this.props.store} context={context}>
<StaticRouter location={this.props.url}>
<App />
</StaticRouter>
</Provider>
);
}
};
// client side render
const CLIENT = configureState => Component => {
const initStates = window.__INIT_STATES__;
const store = configureState(initStates);
Loadable.preloadReady().then(() => {
ReactDOM.hydrate(
<Provider store={store}>
<BrowserRouter>
<Component />
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
});
};
export default function entry(configureState) {
return IS_NODE ? SSR : CLIENT(configureState);
}
А с точки зрения изоморфизма у Али есть набор стратегий понижения. Когда нагрузка на сервер нормальная, сервер выполняет SSR для улучшения взаимодействия с пользователем. Когда пользовательский трафик резко возрастает, например, Double Eleven, сервер автоматически выполняет обработку понижения. Узел не выполняет SSR, и все конвертируются в клиент- боковой рендеринг для снижения нагрузки на сервер. .
выбрать кадр
После понимания разделения передней и задней части нам нужно выбрать структуру для уровня узла.
В настоящее время существует три основных фреймворка: Express, koa1.0 и koa2.0.
Новичкам рекомендуется использовать koa2.0 непосредственно для обучения и развития среднего слоя.
Недостатки экспресса:
-
Слишком тяжелый, есть много модулей, которые мы можем не использовать; Ад обратных вызовов, даже использование Promises может только облегчить его. Недостатками koa1.0 являются:
-
должны сотрудничать
coбиблиотека иgeneratorДля использования конфигурация сложна. Поскольку узел был обновлен до версии 7.6 или выше, увеличениеasync/awaitПосле синтаксического сахара мы можем использовать синтаксис KOA2 непосредственно в родном узле без какой-либо сторонней библиотеки.
koa2 — это модернизированный фреймворк экспресса, многие модули в нем перенесены напрямую из экспресса, но модули, которые раньше редко использовались, удалены, только разработчики могут вводить такие модули, когда им нужно их использовать.
и koa2 используетasync/awaitПосле синтаксического сахара код как бы выполняется синхронно, что очень подходит для логического мышления фронтендеров.
Вот пример кода для экспресс, обещание, koa2:
// express版本
module.exports = (req, res) => {
const data1 = request.get('/api/demo1', (err, res) => {
const data2 = request.get('/api/demo2', (err, res) => {
const data3 = request.get('/api/demo3', (err, res) => {
res.send(data1 + data2 + data3);
})
})
})
}
// promise版本
module.exports = (req, res) => {
new Promise((resolve, reject) => {
request.get('/api/demo1', (err, res) => {
resolve(res);
}).then(res => {
request.get('/api/demo2', (err, res2) => res + res2 );
}).then(res2 => {
request.get('/api/demo3', (err, res3) => res2 + res3)
}).then((data) => {
res.send(data);
});
})
}
Хотя он выглядит аккуратнее, он все еще очень громоздкий.
// koa1和koa2在写法上基本相同,区别在于koa1在使用之前要对co库和generator进行繁琐的配置。
// 每一个await的时候最好加上try-catch,防止因为一个异步请求失败而导致node进程崩溃,这里简化了写法。
module.exports = async (ctx) => {
const data1 = await request.get('/api/demo1');
const data2 = await request.get('/api/demo2');
const data3 = await request.get('api/demo3');
ctx.body = {
data: data1 + data2 + data3
};
}
koa2 очень удобен в использовании и очень подходит для логики мышления фронтенд-инженеров.
Хотя код koa2 выглядит так, как будто он выполняется синхронно, на самом деле он просто становится функцией промиса после компиляции, а весь код после await помещается в обратный вызов промиса и выполняется.
структура развития
После выбора фреймворка все остальное — разработка.Общий слой узлов имеет следующую структуру каталогов:
node
- lib // хранить сторонние плагины
- util // Сохраняем свои собственные служебные функции
- промежуточное ПО // хранить промежуточное ПО
- маршруты // сохраняем маршруты
- контроллер // храним функцию обработчика маршрута
- app.js // файл записи уровня узла Базовая архитектура нодового слоя здесь практически представлена, а остальные части фронтенда в целом всем знакомы. Структура каталогов внешнего интерфейса:
public
- static
- src
- js
- components
- containers
- routes
- stores
- actions
- reducers
- pages
- css/scss/less
- статический Здесь вы можете следовать обычной логике разработки React.
Наконец, есть некоторые другие папки, которые можно свободно использовать, например, templates для хранения шаблонов, scripts для хранения обычно написанных сценариев и так далее.
настроить
Онлайн-проект должен иметь два режима — режим производства и режим разработки.
Производственный режим — это наша онлайн-операционная среда.
Режим разработки — это наша обычная локальная среда разработки.
При необходимости можно настроить еще больше сред.
Требования этих двух сред различаются, поэтому у нас будет два набора файлов конфигурации.Передавая разные файлы конфигурации в узел и веб-пакет, мы можем запускать разные среды в соответствии с разными конфигурациями.
автоматизированный тест
Автоматическое тестирование необходимо для полноценного крупного веб-сайта.
Хотя в настоящее время из-за быстрого роста клиентской области автоматизированное тестирование бизнес-уровня также стало нестабильным из-за быстрой итерации бизнеса, но некоторые базовые тесты все же необходимы.
В обычной разработке необходимо автоматизировать модульное тестирование библиотеки классов и модульное тестирование компонентов пользовательского интерфейса.
Эти тестовые файлы лучше всего хранятся в отдельном тестовом каталоге или добавляют файл компонента. Test.js в каждый файл компонента базового пользовательского интерфейса, так что файл .test будет автоматически найден для тестирования при запуске теста.
Прежде чем каждый проект будет запущен в сеть, необходимо выполнить интеграционный тест, чтобы проверить, нормальная ли маршрутизация, нормальная ли упаковка веб-пакета и установка модуля узла, а также нормальный ли имитируемый доступ пользователя для входа в систему.
Иногда нам также необходимо проводить стресс-тестирование и тестирование аварийного восстановления.
Для новичков тестирование — очень важная концепция и привычка, и обычно следует писать больше модульных тестов.