Kyiv Go Meetup May 2018:
ведучий: - Всім привіт! Дякую, що ви тут зібралися! Сьогодні у нас два офіційні спікери – Льоша та Ваня. Буде ще два, якщо в нас вистачить часу. Перший речник – Олексій Грачов, він розповість нам про GopherJS.
Олексій Грачов (далі – АГ): – Я – Go-девелопер, і я пишу веб-сервіси Go. Деколи доводиться стикатися з фронтендом, іноді доводиться залазити туди ручками. Хочу розповісти про свій досвід та дослідження Go на фронтенді.
Легенда така: спочатку поговоримо чому ми хочемо запускати Go на фронтенді, потім поговоримо, як це можна зробити. Є два шляхи – Web Assembly та GopherJS. Подивимося, у якому стані ці рішення та що можна робити.
Що не так із frontend-ом?
Чи всі згодні, що все добре з фронтендом?
Тестів мало? Повільне складання? Екосистема? Добре.
З приводу фронтенду мені подобається цитата, яку сказав один із фронтенд-розробників у своїй книзі:
Javascript не має системи типів. Зараз я називатиму проблеми, з якими стикався під час своєї роботи і пояснювати, як їх вирішують.
Систему типів взагалі важко назвати системою типів Javasript – там є рядки, які позначають тип об'єкта, але насправді до типів це не має жодного відношення. Ця проблема вирішена в TypeScript (надбудова над Javasript) і Flow (static-checker типів Javascript). Власне, фронтенд уже дійшов до вирішення проблеми поганої системи типів Javascript.
Стандартної бібліотеки в браузері немає – є якісь вбудовані об'єкти та «магічні» функції в браузерах. Але я в Javascript як такому стандартна бібліотека відсутня. Ця проблема вже була вирішена jQuery (всі використовували jQuery з усіма прототипами, хелперами, функціями, які потрібні для роботи). Зараз же всі використовують Lodash:
Callback hell. Думаю, всі бачили код на Javascript десь 5 років тому, і він був схожий на «локшину» з неймовірного поєднання коллбеків. Зараз ця проблема вирішена (з виходом ES-15 або ES-16), додали в Javascript проміси (promises) і всім стало легше дихати на якийсь час.
Поки не прийшов Promice hell… Не знаю, як фронтенд-індустрія примудряється, але вони постійно заганяють себе в якісь дивні нетрі. Умудрилися і на «промісах» зробити hell. Потім вирішили цю проблему, додавши новий примітив – async/await:
З асинхронністю проблему вирішено. Async/await – досить популярний примітив у різних мовах. У «Пітоні» та інших є такий підхід – він досить хороший. Проблема вирішена.
Яку проблему не вирішено? Зростаюча в геометричній прогресії складність фреймворків, складність екосистеми та власне програм.
- Синтаксис Javasript трохи дивний. Всі ми знаємо проблеми зі складанням масиву та об'єкта та інші приколи.
- Javascript – мультипарадигмовий. Зараз це особливо нагальна система, коли екосистема дуже велика:
- всі пишуть у різних стилях - хтось пише структурно, хтось пише функціонально, різні девелопери пишуть по-різному;
- з різних пекеджів (packages) різні парадигми, коли ви використовуєте різні пакети;
- дуже багато «веселощів» з функціональним програмуванням у Javasript – з'явилася бібліотека rambda і тепер читати програми, написані в цій бібліотеці, не може ніхто.
- Це все робить великий impact в екосистему, і вона розрослася неймовірно. Пакети один з одним несумісні: хтось на промісах, хтось на async/await, хтось на коллбеках. Ще й у різних парадигмах пишуть!
- Це призводить до того, що проект важко підтримувати. Важко знайти баг, якщо не можеш прочитати код.
Що таке Web Assemly?
Браві хлопці з Mozilla Foundation та інших компаній придумали таку річ, як Web Assembly. Що це?
- Це вбудована у браузер віртуальна машина, яка підтримує бінарний формат.
- Бінарні програми туди потрапляють, виконуються практично нативно, тобто браузеру не потрібно щоразу парсити всю «локшину» JavaScript-коду.
- Усі браузери заявили про підтримку.
- Оскільки це байт-код, можна написати компілятор під будь-яку мову.
- Чотири основні браузери вже поставляються за допомогою Web Assembly.
- Скоро ми чекаємо нативну підтримку в Go. Така нова архітектура вже додалася: GOARCH = wasm GOOS = js (soon). Поки що, як я розумію, вона не функціональна, проте є заява про те, що це точно буде у Go.
Що робити зараз? GopherJS
Поки ми не маємо підтримки Web Assembly, є такий транспайлер, як GopherJS.
- Код на Go транспайліться в чистий Javascript.
- Запускається у всіх браузерах - там немає нових фіч, які підтримуються лише сучасними браузерами (це Vanilla JS, який запускається на всьому, що завгодно).
- Є підтримка майже всього, що є в Go, у тому числі горутини та канали… – все, що ми так любимо і знаємо.
- Майже вся стандартна бібліотека підтримується, за винятком тих пакетів, які немає сенсу підтримувати в браузері: syscall, net-взаємодії (є net/http-клієнт, але немає сервера, а клієнт емулюється через XMLHttpRequest). В цілому вся стандартна бібліотека доступна – ось вона у браузері, ось stdlib Go, яку ми любимо.
- Вся екосистема пакета в Go, всі сторонні рішення (темплейтинг та інше) можна скомпілювати за допомогою GopherJS і запустити це у браузері.
Отримати GopherJS дуже легко – це звичайний Go-пакет. Робимо go get, і у нас є команда GopherJS, щоб білдити додаток:
Ось такий маленький hello world.
…Звичайна Go-програма, звичайний пакет fmt стандартної бібліотеки та Binding Js достукатися до API браузера. Println у результаті буде перетворено на console log і браузер напише “Hello gophers”! Ось так просто: робимо GopherJS build – запускаємо у браузері – все працює!
Що є зараз? Bindings
Є біндінги до всіх популярних js-фреймворків:
- JQuery;
- Angular.js;
- D3.js для побудови графіків та роботи з великими даними;
- React.js;
- VueJS;
- навіть є підтримка Electron (тобто вже зараз можемо писати десктопні програми на «Електроні»);
- і найкумедніше – це WebGL (можемо робити повнографічні програми, у тому числі ігри з 3D-графікою, музикою та всіма плюшками);
- і дуже багато інших біндінгів до всіх популярних javascript-фреймворків та бібліотек.
Рамки
- Є вже розроблений спеціально для GopherJS веб-фреймворк – Vecty. Це повноцінний аналог React.js, але розроблений лише на Go, зі специфікою GopherJS.
- Є ігрові мішки (раптово!). Я знайшов два найпопулярніші:
- Engo;
- Ebiten.
Продемонструю пару прикладів, як це виглядає і що вже зараз можна написати на Go:
Або такий варіант (3D-шутер не знайшов, але, може, він є):
Що я пропоную?
Зараз індустрія фронтенду перебуває у такому стані, що туди зараз кинуться всі мови, які раніше плакали від Javascript. Тепер усі компілюватимуться у «Веб Асемблі». Що нам потрібно, щоб зайняти там гідне місце як гоферам?
Go традиційно пішло, що це – System programming language, і практично немає ніяких бібліотек для роботи з UI. Щось є, але воно наполовину занедбане, наполовину нефункціональне.
І ось – добрий шанс зробити UI-бібліотеки на Go, які запускатимуться на GopherJS! Можна нарешті написати свій фреймворк! Настав час, коли можна написати фреймворк, і він буде одним з перших і отримає ранню адаптацію, і ви будете зіркою (якщо це буде хороший фреймворк).
Адаптувати можна безліч різних пакетів, які вже є в екосистемі Go, до специфіки браузера (наприклад, Template engine). Вони вже запрацюють, можна зробити зручні обв'язки, щоб можна було легко рендерити контент прямо в браузері. Плюс, можна зробити, наприклад, сервіс, що вміє рендерити те саме на сервері і на фронтенді, використовуючи один і той же код - все як люблять фронтенд-девелопери (тільки тепер на Go).
Можна написати гру! Just for fun…
У мене все.
Питання
Питання (далі – В): – Я пишу на Go чи Js?
АГ: – Ти пишеш на Go рутини, канали, структури, embedding – все… Ти підписуєшся на event, передаєш туди функцію.
В: – Тобто я пишу на голому Js?
АГ: - Ні, ти пишеш як би на Go і підключаєшся до API браузера (API при цьому не змінився). Можеш написати свої обв'язки, щоб у канал приходили повідомлення – це ж нескладно.
В: - Що щодо мобайла?
АГ: - Я точно бачив: є біндінги для патча Cordova, які Js запускає. У React Native – не знаю; може, є, а може, ні (не особливо цікавився). Ігровий двигун N-go підтримує і мобільні програми - і iOs, і Android.
В: - Питання щодо Web Assembly. Місця займається все більше, незважаючи на стислість, «зазипованість»… Чи не вб'ємо таким чином світ фронтенду ще більше?
АГ: – Web Assembly – це бінарний формат, і бінарний за замовчуванням не може бути в підсумковому релізі більше, ніж текст… Вас тягне runtime, але це те саме, що стандартну бібліотеку Javascript затягнути, коли її немає, тому ми використовуємо якийсь Lodash . Я не знаю, скільки Lodash займає.
В: – Очевидно менше, ніж runtime…
АГ: - На "чистому" Javascript?
В: – Так. Ми його стискаємо перед тим, як відправляти…
АГ: - Але це ж текст ... Загалом, мегабайт - це начебто багато, але це все (у тебе весь runtime є). Далі ти пишеш свою бізнес-логіку, яка збільшить на 1% твій binary. Поки що я не бачу, щоб це вбивало фронтенд. Тим більше, Web Assembly працюватиме швидше, ніж Javascript з очевидної причини - його не треба парсить.
В: – Поки що спірний момент… Ще немає якоїсь еталонної реалізації «Васма» (Web Assembly), щоби можна було однозначно судити. Концептуально – так: ми всі розуміємо, що binary має бути швидшим, але поточна реалізація того ж V8 дуже ефективна.
АГ: - Так.
В: – Компіляція там працює реально дуже круто та не факт, що буде велика перевага.
АГ: – Web Assembly також великі дядьки роблять.
В: – Поки що, мені здається, ще важко судити про Web Assembly. Вже скільки років точаться розмови, а реальних досягнень, які можна помацати, небагато.
АГ: - Можливо. Поглянемо.
В: – У нас немає проблем на бекенді… Може, залишити ці проблеми у фронтенді? Навіщо туди лізти?
АГ: – Доводиться тримати штат фронтейнерів.
Небагато реклами 🙂
Дякую, що залишаєтеся з нами. Вам подобаються наші статті? Бажаєте бачити більше цікавих матеріалів? Підтримайте нас, оформивши замовлення або порекомендувавши знайомим,
Dell R730xd вдвічі дешевше в дата-центрі Equinix Tier IV в Амстердамі? Тільки в нас
Джерело: habr.com