) — это все теги, используемые в
, то есть почти все в целом, за исключением некоторых мета-тегов;Go в браузер. Создание веб-приложений с использованием Web Assembly на Go / Хабр | Веб-студия Nat.od.ua
Go в браузер. Создание веб-приложений с использованием Web Assembly на Go / Хабр
Наиболее известным набором инструментов для компиляции в wasm32 является emscripten, с его помощью можно скомпилировать приложение, написанное на C/C++ или на любом языке, имеющим frontend-компилятор для LLVM. При этом компилятор подменяет вызовы OpenGL и POSIX на соответствующие аналоги в браузере, что например используется при компиляции библиотеки skia для браузера (canvaskit) из исходного кода на C++, а также портирование существующих библиотек (например, ffmpeg или opencv). Но некоторые языки программирования поддерживают wasm32 как одну из целевых платформ, среди которых можно выделить Kotlin (Native) и Go. В этой статье мы обсудим общие вопросы о запуске приложений Go в среде браузера и использование библиотеки Vecty для создания веб-приложений на основе переиспользуемых компонентов.
Компиляция в целевую платформу wasm32 поддерживается в Go, для этого нужно указать значения переменных окружения GOOS=js и GOARCH=wasm. Начнем с самой простой программы и постепенно будет усложнять возможности нашего веб-приложения.
package main
import “fmt”
func main() {
fmt.Println(“Hello, WebAssembly World!”)
}
Выполним компиляцию исходного кода в wasm-байткод:
GOOS=js GOARCH=wasm go build -o hello.wasm
И далее создадим сценарий для загрузки и запуска wasm-файла в HTML:
index.html
Файл wasm_exec.js может быть получен, например, отсюда или из установки Go (по расположению misc/wasm). Он создает необходимый контекст для выполнения приложения на Go (например, создает реализации для syscall/js, который мы будем использовать для взаимодействия с браузером, а также регистрирует прототип Go, который будет использоваться для начальной загрузки байткода и запуска функции main.
Для обхода ограничений безопасности браузера (по умолчанию загрузка сетевых ресурсов запрещена, если страница открыта через локальную ссылку в схеме file://) запустим docker-контейнер с nginx.
docker run –name gotest -d -p 80:80 -v `pwd`:/usr/share/nginx/html nginx
После обращения к localhost можно увидеть, что сообщение выводится в консоль браузера. Теперь давайте подключимся к DOM и попробуем вызвать Javascript-функцию из нашего wasm-приложения. Для доступа к JS необходимо подключить модуль syscall/js и использовать глобальный контекст для доступа к зарегистрированным символам в js через вызов Global() для получения доступа к объекту window. Например, для получения текущего адреса можно использовать следующее выражение.
js.Global().Get(“location”).Get(“href”)
Для вызова функций из Javascript или встроенных в браузер можно использовать метод Call от объекта (или от глобального контекста). Например, для вывода диалога уведомления можно использовать вызов:
js.Global().Call(“alert”, “Hello, WASM”)
Для добавления элемента в DOM можно комбинировать вызовы, через использование объекта document:
document := js.Global().Get(“document”)
body := document.Call(“querySelector”, “body”)
div := document.Call(“createElement”, “div”)
div.Set(“innerHTML”, “Hello, WASM”)
body.Call(“appendChild”, div)
Аналогично можно вызвать JS-функции из кода на Go. В html-файле в
Давай дружить. OpenId Connect и Yarp / Хабр | Веб-студия Nat.od.ua
Давай дружить. OpenId Connect и Yarp / Хабр
Сегодня в этой статье я хочу поделиться личным опытом работы и решением конкретного кейса. Работали над ним небольшой командой, но для простоты повествования буду писать от первого лица. Собственно сам кейс: есть Windows сервер с доменом и SSL сертификатом, на нём нужно поднять сервер авторизации с протоколом OpenId Connect и ещё два приложения, которые должны авторизовываться через сервер авторизации. И да, реализовать все нужно по максимуму использовав встроенный функционал.
“Сервер авторизации должен быть вынесен отдельно!” – скажете вы – Но в реальности крутим и вертим как можем. Звучит просто, как два пальца. Как было на деле сейчас расскажу.
Общая схема Сервер авторизации
Тут все относительно просто, есть готовые примеры и описанная документация. Бери да делай! В качестве основы был использован пример у damienbod . И уже дальше доработан под себя как нужно.
YARP
YARP – обратный прокси сервер, относительно недавно выпущенный в релиз компанией Microsoft. В его настройке нет ничего сложного, есть описанная документация и примеры имплементации. Конкретно мы руководствовались вот этой статьей. Конфигурацию нашего прокси прикладываю ниже.
“ReverseProxy”: {
“Routes”: {
“minimumroute”: {
“ClusterId”: “minimumcluster”,
“Match”: {
“Path”: “{**catch-all}”
}
},
“route2”: {
“ClusterId”: “Server”,
“Match”: {
“Path”: “/Server/{*any}”
},
“Transforms”:
},
“route3”: {
“ClusterId”: “App1”,
“Match”: {
“Path”: “/App1/{*any}”
},
“Transforms”:
},
“route4”: {
“ClusterId”: “App2”,
“Match”: {
“Path”: “/App2/{*any}”
},
“Transforms”:
}
]
}
},
“Clusters”: {
“minimumcluster”: {
“Destinations”: {
“first_destination”: {
“Address”: “http://localhost:5001”
}
}
},
“Server”: {
“Destinations”: {
“first_destination”: {
“Address”: “http://localhost:5001”
}
}
},
“App1”: {
“Destinations”: {
“first_destination”: {
“Address”: “http://localhost:5002”
}
}
},
“App2”: {
“Destinations”: {
“first_destination”: {
“Address”: “http://localhost:5003”
}
}
}
}
}
Вот и всё, готово?
Начинаем все запускать локально и неужели все работает – да? Ага, значит деплоим и вот незадача – не работает. В чем же ошибка?
Дело в том, что у нашего сервера авторизации адрес http:// localhost:5001, а у приложения http:// localhost:5002. Поэтому когда, все это развернуто на сервере происходит ошибка. Для решения этой проблемы нам нужно самим указать такой параметр как RedirectUri
options.Events.OnRedirectToIdentityProvider = ctx =>
{
ctx.ProtocolMessage.RedirectUri = “https://domain/app1/signin-oidc”;
return Task.CompletedTask;
};
options.Events.OnRedirectToIdentityProviderForSignOut = ctx =>
{
ctx.ProtocolMessage.PostLogoutRedirectUri = “https://domain/app1/signout-callback-oidc”;
return Task.CompletedTask;
};
Уточнение: signin-oidc и signout-callback-oidc – это встроенные методы, который устанавливается по умолчанию как конечные точки входа и выхода в пакете Microsoft.AspNetCore.Authentication.OpenIdConnect.
С одной проблемой разобрались, теперь редирект правильный. Но встречаем тут же следующую, которая звучит как Corellation failed. Заходим в панель разработчика и начинаем пристально изучать запросы и ответы. И находим предупреждение от браузера, что файлы cookie не установлены, так, как отсутствует атрибут secure. Путей решения этой проблемы два:
Установить для наших приложений самозаверяющиеся SSL сертификаты. Как это сделать описано здесь.
Либо на наших приложениях изменить конфигурацию политики файлов cookie. Для этого нам нужно прописать следующее в program.cs:
builder.Services.Configure
{
options.Secure = CookieSecurePolicy.Always;
});app.UseCookiePolicy();
Всё, с этой проблемой справились. Заходим, пробуем, и снова тоже самое. Изучаем, значиться, дальше. И наконец находим, что файлы cookie то установились, но по неверному маршруту. Значит теперь самим вручную нужно указать маршрут установки. Делается это следующим образом, в настройках аутентификации OpenIdConnect
options.CorrelationCookie.Path = “/app1/signin-oidc”;
options.NonceCookie.Path = “/app1/signin-oidc”;
И наконец все работает! Полный код файла program.cs ниже.
var builder = WebApplication.CreateBuilder(args);
IConfiguration configuration = builder.Configuration;
builder.Services.AddHttpClient();
builder.Services.AddOptions();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = “Cookies”;
options.Authority = “https://domain.com/server”;
options.ClientId = “ClientId”;
options.ClientSecret = “ClientSecret”;
options.ResponseType = OpenIdConnectResponseType.Code;
options.UsePkce= true;
options.Scope.Add(“openid”);
options.Scope.Add(“profile”);
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.CorrelationCookie.Path = “/app1/signin-oidc”;
options.NonceCookie.Path = “/app1/signin-oidc”;
options.Events.OnRedirectToIdentityProvider = ctx =>
{
ctx.ProtocolMessage.RedirectUri = “https://domain.com/server/signin-oidc”;
return Task.CompletedTask;
};
options.Events.OnRedirectToIdentityProviderForSignOut = ctx =>
{
ctx.ProtocolMessage.PostLogoutRedirectUri = “https://domain.com/server/signout-callback-oidc”;
return Task.CompletedTask;
};
});
builder.Services.Configure
{
options.Secure = CookieSecurePolicy.Always;
});
var app = builder.Build();
IWebHostEnvironment env = app.Environment;
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseHsts();
}
app.UsePathBase(“/App1”);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile(“Index.html”);
app.Run();Небольшое послесловие
Возможно описанный мной способ решения данного кейса не на 100% верный, но разрабатывался он исходя из тех исходных данных, которые были нам предоставлены. В просторах интернета не нашел похожего решения данного кейса, или хотя бы похожего, поэтому решил поделиться. Если у вас есть, вариант как можно усовершенствовать этот способ или сделать по иному но, в тех же рамках, то прошу в комментарии.
Фронтенд-новости №5. Отказ от React, новые CSS-свойства для адаптивности и JS-контейнеры | Веб-студия Nat.od.ua
Фронтенд-новости №5. Отказ от React, новые CSS-свойства для адаптивности и JS-контейнеры
Дайджест новостей из мира фронтенд-разработки за последнюю неделю 2–8 мая.
Если работаете с
Используйте max-inline-size для гибкого центрирования контента в адаптивных интерфейсах.
CSS Zen Garden 19 лет.
Знайте, что прогрессивное улучшение дорого, но необходимо вашему пользователю. Рассмотрите примеры прогрессивного улучшения с aspect-ratio, новыми цветовыми функциями, а также focus-visible.
Веб быстро развивается и пора переосмыслить подходы к адаптации интерфейсов. Используйте CSS-свойства, функции и значения: clamp(), min-content, max-content, fit-content, auto-fit, minmax().
Научитесь переносить текст на новую строку.
В прошлом выпуске прочитали про inert? Прочитайте.
Пофантазируйте о новых псевдоклассах :removed и :finish для анимаций.
Погрузитесь в :where — ещё один логический способ найти элемент на странице.
Познакомьтесь с тем, как работают алгоритмы компоновки.
Начинайте изучать сабгриды.
Узнайте, почему height: 100vh не самый лучший вариант для адаптации мобильной версии.
В дайджесте много статей и видео на английском языке, чтобы это не стало препятствием: в Google Chrome есть функция перевода страницы с любого популярного языка, а видео можно перевести в Яндекс Браузере.
PHP Дайджест № 222/3 (26 марта – 25 апреля 2022) / Хабр | Веб-студия Nat.od.ua
PHP Дайджест № 222/3 (26 марта – 25 апреля 2022) / Хабр
Дисклеймер: Нет, это не дайджест авторства Романа Пронского. К сожалению, у меня нет достоверной информации – будет ли выходить его дайджест далее.
Однако я взял на себя смелость временно продолжить дело Романа и написать новый дайджест за тот месяц, что прошел с выхода последнего.
Если Роман сможет и захочет далее продолжать свой дайджест – он сам решит, как использовать мой текст: взять в свой проект, как его часть или нет. На всякий случай я ставлю нумерацию дайджеста через дробь. Однако не претендуя при этом на продолжение оригинального проекта.
PHP
Вышли версии PHP:
Релизы посвящены устранению обнаруженных багов.
Кроме того:
Одобрен стандарт PER Coding Style, который придет на смену PSR-12
Запущен сайт https://thephp.foundation/ На нем можно видеть – кто в данный момент спонсирует разработку PHP и в каких объемах.
RFC (Requests for Comments )Undefined Variable Error Promotion
https://wiki.php.net/rfc/undefined_variable_error_promotion
Интересное предложение, о запрете на использование не объявленных явно переменных в PHP. Подробный рассказ о нём был в предыдущем дайджесте.
Голосование завершено, предложение принято и будет реализовано в PHP 9.
Undefined Property Error Promotion
https://wiki.php.net/rfc/undefined_property_error_promotion
Предложение, достаточно близкое к предыдущему. Внесено в начале апреля.
Предлагается в случае чтения необъявленного или не созданного явно свойства объекта выдавать ошибку уровня E_WARNING.
Идет голосование, на данный момент результат таков: 18 голосов “за” и 3 голоса “против”
Typehint Array Desctructuring
https://wiki.php.net/rfc/typehint_array_desctructuring
Свежее предложение, пока что находящееся в статусе “Черновик” и не имеющее примера реализации.
Предлагается добавить возможность контроля типов в конструкцию “разборки” массива. Например так:
$data = ;
= $data;
Предполагается, что такой контроль типов будет работать по той же схеме, что и, скажем, в аргументах функций: при установленной директиве “strict_types=0” скалярные типы будут приводиться, а при “strict_types=0” – строго проверяться.
Автор RFC надеется, что в случае принятия его предложения, будет открыт путь к типизированному присваиванию не только в случае разыменования массивов, но и для простых переменных, примерно в таком виде:
int $id = 42;True type
https://wiki.php.net/rfc/true-type
Автор предложения, George Peter Banyard, предлагает ввести в систему типов, начиная с PHP 8.2, отдельный тип true. Обосновывает, в основном, уже принятым предложением о добавлении типа false и тем фактом, что введение данного типа упростит статический анализ, и позволит улучшить работу оптимизатора.
В тексте RFC приводится такой пример:
class User {
function isAdmin(): bool
}
class Admin extends User
{
function isAdmin(): true
{
return true;
}
}
Readonly classes
https://wiki.php.net/rfc/readonly_classes
Логичное предложение, развивающее уже имеющийся синтаксис readonly-свойств на целые классы.
Цитата из RFC:
readonly class Test {
public string $prop;
}
Объект такого класса нельзя будет изменить после создания (например – переприсвоить другое значение какому-либо свойству). Попытка изменения приведет к фатальной ошибке. Дополнительно следует учесть, что в подобных классах нельзя будет объявлять статические или нетипизированные свойства.
Предложение в данный момент находится на голосовании, промежуточный итог составляет 27/6 в пользу принятия.
Новости фреймворковSymfonyРелизы
Вышли новые версии фреймворка:
Новости Symfony 6.1
В Symfony 6.1 появится возможность использования перечислений (enum) в роутах. Смотрим пример из анонса новости:
use SymfonyComponentRoutingRequirementEnumRequirement;
// ‘bar’ parameter allows all values defined in the Enum
#)]
Кроме того, добавлена возможность использовать символы UTF-8 в параметрах роутов:
use SymfonyComponentRoutingAnnotationRoute;
#
public function someControllerMethod(string $föo, string $bár)
{
// …
}
Подробнее об этих нововведениях можно прочесть по ссылке https://symfony.com/blog/new-in-symfony-6-1-improved-routing-requirements-and-utf-8-parameters
Напомню, что Symfony 6.1 находится в стадии первой беты: https://symfony.com/blog/symfony-6-1-0-beta1-released
ДругоеLaravelYii
Нет значимых новостей. См. статью на Хабре.
Новости одной строкой:
Вышла в свет библиотека AnourValar/office, предназначенная для работы с MS Excel из PHP. В частности библиотека умеет подставлять значения в шаблонные файлы и сохранять результат в разных форматах, включая PDF. Смотрите подробности на https://github.com/AnourValar/office/blob/master/README.md
Продолжает публиковаться серия статей “Functional Programming in PHP” автора Viktor Daróczi – интересный цикл, заслуживающий внимания.
Опубликована небезыинтересная видеоинструкция, посвященная настройке XDebug для Laravel в окружении Sail.
Richard Warepam пытается поставить точку в бесконечном споре на тему того, какие алгоритмы и в какой объеме должен знать каждый разработчик и предлагает свою версию “Шести алгоритмов, которые должен знать каждый”
Вышла версия PHPStan 1.6.0 Самое интересное в этом выпуске – аннотации для условных возвращаемых типов примерно такого вида:
/**
* @return ($as_float is true ? float : string)
*/
function microtime(bool $as_float): string|float
…
Опубликована интересная, но не бесспорная статья об оптимизации по памяти и времени исполнения кода при использовании генераторов.
Вместо заключения
Подготовлено при активном участии сообщества телеграм-чата “PHP Russian Talks”.
Замечания по текущему выпуску и предложения для следующего можете отправлять автору в личку или в указанный выше чат.
Как правильно верстать в 2022 году. Часть 2. Как правильно вкладывать теги друг в друга | Веб-студия Nat.od.ua
Как правильно верстать в 2022 году. Часть 2. Как правильно вкладывать теги друг в друга
Привет хабр! Меня зовут Николай и я Frontend-разработчик в логистическом стартапе Relog. Хочу рассказать о самых распространённых ошибках в вёрстке современных проектов.
В этой статье мы говорим о вложении тегов друг в друга, так как это один из неочевидных моментов, в котором многие новички часто делают ошибки.
Также я расскажу о работе со спецификацией HTML — какие разделы важны для нас, как для верстальщиков и как искать там информацию.
Содержание
Используйте правильные теги
Как правильно вкладывать теги друг в друга
Работа с медиаконтентом
Пишем таблицы на HTML правильно
a или button? Работа с интерактивными элементами и как выбрать правильный тег
Различный теги для медиа-контента
Прекратите писать велосипеды! Как мы можем стилизовать дефолтные HTML-элементы
Пишем доступные формы
Избыточная вёрстка. Как облегчить разметку
Современные фишки HTML и CSS способные облегчить нам жизнь
Экспериментальные технологии, входящие в стандарт
Как правильно вкладывать теги друг в друга
Что значит правильно? Что является источником истины при работе с HTML? Конечно же это специфиакция! В данный момент существует так называемый «живой стандарт» пятой версии HTML. Это значит, что у него нет мажорных версий и он обновляется регулярно. Посмотреть последнее обновление спецификации можно здесь: https://html.spec.whatwg.org/
Спецификация HTML — это увесистый документ с кучей разделов. Она существует как для разработчиков браузеров, так и для нас — верстальщиков. Конкретно нас интересуют третий и четвёрный раздел (Semantics, structure, and APIs of HTML documents и The elements of HTML). Эти разделы описывают, как теги можно вкладывать друг в друга и что обозначает каждый тег.
Описание элемента
Каждый элемент имеет метаинформацию и описание.
Сверху размещены метаданные, куда включна следующая информация:
куда можно вкладывать тег;
какие теги можно вкладывать внутрь этого тега;
перечень аттрибутов тега (глобальные, дополнительные и ARIA);
информация о доступности;
вспомогательные данные.
Далее размещено описание тега — что он обозначает и как его можно использовать.
Спецификация элемента на примере тега
Метаданные тегаМетаданные тега
Метаинформация о теге включает в себя несколько пунктов:
Категории — обозначает, к каким типам тегов относится элемент, могут быть следующие типы:
Metadata content (например и
) — метаданные страницы, обозначающие представление или поведение содержимого, или отношение к другим документам; Flow content (например
, , Sectioning content (например
) — какие-либо большие секции, как правило имеющие конкретную структуру и заголовок; Heading content (все заголовки
–
, а также тег, про который я забыл рассказать в прошлой статье —) — определяет заголовок секции, обозначенной явно, либо.
Phrasing content (например , , ) — различный, в основном текстовый контент, но включающий также некоторые элементы, которые позволяют размечать текст на уровне параграфов;
Embedded content (например
Interactive content (например ,
Контекст использования элемента — где мы можем размещать элемент.
Контентная модель — важная для этой статьи часть! Это как раз то, что мы можем размещать внутри тега.
Tag omission — возможные сценарии, когда закрывающую часть тега можно опустить. Рекомендую не обращать внимания на этот раздел вообще, так как в современном вебе нормальной практикой является закрытие всех парных тегов.
Доступные аттрибуты тега.
Раздел, касающийся доступности. Надеюсь когда-нибудь дойдут руки написать о работе с доступностью в рамках спецификации.
DOM Interface — раздел, необходимый для JavaScript-разработчиков, подробно на нём останавливаться не будем.
И всё же, как правильно вкладывать теги друг в друга?Категории элементов по HTML-спецификации
Две основные категории тегов — это Metadata (метаданные) и Flow (поточные теги). Метаданные — это то что в основном входит в
, а Flow — то что можно положить в. Однако, некоторые мета-теги мы можем разместить в, поэтому они заходят на Flow-контент (например это