4. Изучение кода поиска JavaScript
В предыдущих уроках вы добавили поиск в статическое веб-приложение. В этом уроке описываются основные шаги, выполнив которые можно настроить интеграцию. Если вы ищете памятку о том, как интегрировать поиск в приложение JavaScript, в этой статье объясняется, что вам нужно знать.
Пакет SDK Azure @azure/search-documents
Приложение-функция использует пакет AZURE SDK для поиска ИИ Azure:
- NPM: @azure/search-documents
- Справочная документация: клиентская библиотека
Приложение-функция проходит проверку подлинности через пакет SDK для облачного API поиска ИИ Azure с помощью имени ресурса, ключа API и имени индекса. Секреты хранятся в параметрах статического веб-приложения и извлекаются в функцию в качестве переменных среды.
Настройка секретов в файле конфигурации
const CONFIG = < SearchIndexName: process.env["SearchIndexName"] || "good-books", SearchApiQueryKey: process.env["SearchApiKey"] || "", SearchServiceName: process.env["SearchServiceName"] || "", SearchFacets: process.env["SearchFacets"] || "authors*,language_code", >console.log(CONFIG); if (!CONFIG.SearchIndexName || !CONFIG.SearchApiQueryKey || !CONFIG.SearchServiceName) throw Error("./config.js::Cognitive Services key is missing"); module.exports = < CONFIG >;
Функция Azure: Поиск в каталоге
API поиска принимает условие поиска и выполняет поиск по документам в индексе поиска, возвращая список совпадений.
Функция Azure извлекает сведения о конфигурации поиска и выполняет запрос.
const < app >= require('@azure/functions'); const < CONFIG >= require("../lib/config"); const < readFacets, createFilterExpression >= require('../lib/azure-cognitive-search'); const < SearchClient, AzureKeyCredential >= require("@azure/search-documents"); // Create a SearchClient to send queries const client = new SearchClient( `https://` + CONFIG.SearchServiceName + `.search.windows.net/`, CONFIG.SearchIndexName, new AzureKeyCredential(CONFIG.SearchApiQueryKey) ); app.http('search', < methods: ['POST'], authLevel: 'anonymous', handler: async (request, context) =>< context.log(`Search request for url "$"`); try < const body = await request.json(); console.log(body); let q = body.q || "*"; const top = body.top || 5; const skip = parseInt(body.skip || 0); const filters = body.filters || undefined; const facets = readFacets(CONFIG.SearchFacets); const facetNames = Object.keys(facets); console.log(facetNames); const filtersExpression = (filters && facets) ? createFilterExpression(filters, facets) : undefined; console.log(filtersExpression) // Creating SearchOptions for query let searchOptions = < top: top, skip: skip, includeTotalCount: true, facets: facetNames, filter: filtersExpression >; console.log(searchOptions); // Sending the search request const searchResults = await client.search(q, searchOptions); console.log(searchResults); // Getting results for output const output = []; for await (const result of searchResults.results) < output.push(result); >console.log(searchResults) // Logging search results context.log(searchResults.count); return < headers: < "Content-type": "application/json" >, jsonBody: < count: searchResults.count, results: output, resultsCount: output.length, facets: searchResults.facets, q, top, skip, filters: filters || '' >>; > catch (error) < return < status: 500, jsonBody: < innerStatusCode: error.statusCode || error.code, error: error.details || error.message, stack: error.stack >> > > >);
Клиент: Поиск из каталога
Вызовите Функцию Azure в клиенте React, используя следующий код:
import React, < useState >from "react"; import request from "../api"; import CircularProgress from "@mui/material/CircularProgress"; import < useLocation, useNavigate >from "react-router-dom"; import styled from "@emotion/styled"; import Grid from "@mui/material/Grid"; import Stack from "@mui/material/Stack"; import Container from "@mui/material/Container"; import Results from "../components/Results"; import Pager from "../components/Pager"; import Facets from "../components/Facets/Facets"; import SearchBar from "../components/SearchBar"; import < useQuery >from "@tanstack/react-query"; const StyledPager = styled(Pager)(< marginLeft: "auto", marginRight: "auto", maxWidth: "fit-content", >); const StyledContainer = styled.div` // Uncomment to debug // border: 1px solid red; // Center body with space around margin: 1rem auto; margin-top: 5rem; min-height: 30em; padding-left: 0px; padding-right: 0px; max-width: 98%; outline: 0px; display: flex; `; const StyledSearchBar = styled(SearchBar)(<>); const LeftColumn = styled(Stack)` width: 30%; border-right: 1px solid #f0f0f0; padding: 0 16px 0 16px; `; const RightColumn = styled(Container)``; export default function Search() < const location = useLocation(); const navigate = useNavigate(); const [currentPage, setCurrentPage] = useState( new URLSearchParams(location.search).get("p") ?? 1 ); const [searchTerm, setSearchTerm] = useState( new URLSearchParams(location.search).get("q") ?? "*" ); const [top] = useState(new URLSearchParams(location.search).get("top") ?? 8); const [skip, setSkip] = useState( new URLSearchParams(location.search).get("skip") ?? 0 ); const [filters, setFilters] = useState([]); const [facets, setFacets] = useState(<>); let resultsPerPage = top; function setNavigation(q, p) < navigate(`/search?q=$&p=$`); > function changeCurrentPage(newPage) < const newSkip = (newPage - 1) * top; setNavigation(searchTerm, newPage); setCurrentPage(newPage); setSkip(newSkip); >const fiveMinutes = 1000 * 60 * 5; /* eslint-disable no-unused-vars */ const < data, isLoading, dataUpdatedAt, error >= useQuery( < queryKey: ["search", searchTerm, top, skip, currentPage, filters, facets], //refetchOnMount: false, //refetchOnWindowFocus: false, //refetchOnReconnect: false, enabled: searchTerm !== undefined, staleTime: fiveMinutes, // time in milliseconds cacheTime: fiveMinutes, queryFn: async () =>< setSkip((currentPage - 1) * top); return request("/api/search", "POST", < q: searchTerm, top: top, skip: (currentPage - 1) * top, filters: filters, >).then((response) => < setFacets(response.facets); setFilters(response.filters); return response; >); >, >); const postSearchHandler = (searchTerm) => < setNavigation(searchTerm, 1); setSearchTerm(searchTerm); setCurrentPage(1); setSkip(0); >; const updateFilters = (filters) => < setFilters(filters); >; return ( <> defaultTerm= > filters= setFilters= > ) : ( resultCount= resultsPerPage= setCurrentPage= > )> >); >
Клиент: аспекты из каталога
Этот компонент React включает текстовое поле поиска и аспекты , связанные с результатами поиска. Аспекты необходимо учитывать и разрабатывать как часть схемы поиска при загрузке данных поиска. Затем аспекты используются в поисковом запросе вместе с текстом поиска, чтобы обеспечить фасетную навигацию.
import React, < useEffect, useState >from "react"; import < List, Chip >from "@mui/material"; import CheckboxFacet from "./CheckboxFacet"; import styled from "@emotion/styled"; const StyledFacetComponent = styled.div` border-right: "1px solid #f0f0f0"; height: "100%"; `; const StyledSelectedFacets = styled.div``; const StyledFacetList = styled(List)` margin: "0.25em"; margin-top: "32px !important"; padding-left: "36px !important"; `; export default function Facets(props) < const [filters, setFilters] = useState([]); const [facets, setFacets] = useState(<>); useEffect(() => < setFilters(props.filters); setFacets(props.facets); >, [props.filters, props.facets]); // Change facet name to be more readable // e.g. "author" -> "Author" // e.g. "publication_year" -> "Publication Year" function mapFacetName(facetName) < facetName = `$$`.replace( "_", " " ) || ``; return facetName; > function addFilter(name, value) < const newFilters = filters.concat(< field: name, value: value >); props.setFilters(newFilters); > function removeFilter(filter) < const newFilters = filters.filter((item) =>item.value !== filter.value); props.setFilters(newFilters); > return ( < return ( label=: $`> onDelete= removeFilter(filter)> /> ); >)>
< return ( name= values= addFilter= removeFilter= mapFacetName= selectedFacets= f.field === key)> /> ); >)> ); >
Клиент: разбиение на страницы из каталога
Когда результаты поиска выходят за рамки тривиальных (8), @mui/material/TablePagination компонент предоставляет разбивку на страницы по результатам.
import React from "react"; import TablePagination from "@mui/material/TablePagination"; import styled from "@emotion/styled"; const StyledTablePagination = styled(TablePagination)` margin: auto; max-width: fit-content; border-bottom: 0; `; export default function Pager(props) < const pagesInResultSet = Math.round(props.resultCount / props.resultsPerPage); const moreThanOnePage = pagesInResultSet >1; if (!moreThanOnePage) return <>>; const handleChangePage = (event, newPage) => < props.setCurrentPage(newPage + 1); >; return ( page= // zero-based control from material ui onPageChange= rowsPerPage= rowsPerPageOptions= // don't display b/c there is a single value showFirstButton= showLastButton= labelDisplayedRows=<(< from, to, count >) => `$ of $ pages` > /> ); >
Когда пользователь изменяет страницу, это значение отправляется на родительскую Search.js страницу из handleChangePage функции. Функция отправляет новый запрос в API поиска для того же запроса и новой страницы. Ответ API обновляет аспекты, результаты и компоненты пейджера.
Функция Azure: предложения из каталога
API предложения принимает поисковый термин во время ввода пользователя и предлагает поисковые термины, такие как названия книг и авторы в документах в индексе поиска, возвращая небольшой список совпадений.
Средство подбора для поиска, sg , определяется в файле схемы, используемом при выполнении групповой отправки.
const < app >= require('@azure/functions'); const < SearchClient, AzureKeyCredential >= require("@azure/search-documents"); const < CONFIG >= require("../lib/config"); // Create a SearchClient to send queries const client = new SearchClient( `https://` + CONFIG.SearchServiceName + `.search.windows.net/`, CONFIG.SearchIndexName, new AzureKeyCredential(CONFIG.SearchApiQueryKey) ); app.http('suggest', < methods: ['POST'], authLevel: 'anonymous', handler: async (request, context) =>< context.log(`Suggester request for url "$"`); try < const body = await request.json(); console.log(`suggest body $`); let q = body.q; console.log(`suggest q $`) const top = body.top; console.log(`suggest top $`) const suggester = body.suggester; console.log(`suggest suggester $`) if(!body || !q || !top || !suggester) < console.log(`No suggester found in body`) return < status: 404, body: "No suggester found" >> // Let's get the top 5 suggestions for that search term const suggestions = await client.suggest(q, suggester, < top: parseInt(top) >); //const suggestions = await client.autocomplete(q, suggester, ); context.log(suggestions); return < headers: < "Content-type": "application/json" >, jsonBody: < suggestions: suggestions.results, q, top, suggester >> > catch (error) < return < status: 400, jsonBody: < innerStatusCode: error.statusCode || error.code, error: error.details || error.message >> > > >);
Клиент: предложения из каталога
API функции Suggest вызывается в приложении React \src\components\SearchBar\SearchBar.js в рамках инициализации компонента.
import React, < useState >from "react"; import request from "../api"; import Button from "@mui/material/Button"; import TextField from "@mui/material/TextField"; import Autocomplete from "@mui/material/Autocomplete"; import styled from "@emotion/styled"; import < useQuery >from "@tanstack/react-query"; const StyledContainer = styled.div` display: flex; flex-flow: row wrap; justify-content: space-evenly; align-items: center; gap: 1em; margin-top: 1em; `; const StyledAutoComplete = styled(Autocomplete)` width: 80%; `; const StyledButton = styled(Button)` max-height: 40px; `; export default function SearchBar(< navigateToSearchPage, defaultTerm = "" >) < const [q, setQ] = useState(defaultTerm); const [suggestions, setSuggestions] = useState([]); const top = 5; const suggester = "sg"; /* eslint-disable no-unused-vars */ const < data, isLoading, error >= useQuery( < queryKey: ["suggest", q, top, suggester], refetchOnMount: true, enabled: q.length >0, queryFn: async () => < if (q.length >0) < return request("/api/suggest", "POST", < q, top, suggester, >).then((response) => < let i = 0; const autoCompleteOptions = response.suggestions.map( (suggestion) =>(< id: i++, label: suggestion.text >) ); setSuggestions(autoCompleteOptions); return response; >); > >, >); const onFormSubmit = () => < if (navigateToSearchPage) < navigateToSearchPage(q); >>; function hasLabelValue (option) < return ( option !== undefined && option !== null && option.label !== undefined && option.label !== null ); >return ( > x> options= value= noOptionsText="What are you looking for?" onChange= < (e, value, reason) =>setQ(value?.label || "") > onInputChange= <(e, newValue, reason) => < if (newValue) < setQ(newValue); >>> getOptionLabel= hasLabelValue(option) ? option.label : q> // set key to force re-render when q changes renderOption= <(props, option) => < return hasLabelValue(option) ? ( key=> ) : ( key=> ) >> renderInput= ( variant="outlined" label="What are you looking for?" onKeyDown= < if (e.code.toLowerCase() === "enter" && e.target.value) < onFormSubmit(e.target.value); >>> /> )> /> > Search ); >
Этот компонент React использует @mui/material/Autocomplete компонент для предоставления текстового поля поиска, который также поддерживает отображение предложений (с помощью renderInput функции). Автозаполнение начинается после ввода первых нескольких символов. По мере ввода каждого нового символа он отправляется в качестве запроса поисковой системе. Результаты отображаются в виде короткого списка предложений.
Эта функция автозаполнения является распространенным компонентом, но эта конкретная реализация имеет дополнительный вариант использования. Клиент может ввести текст и выбрать из предложений или отправить введенный текст. Входные данные из списка предложений, а также входные данные из текстового поля должны отслеживаться для изменений, которые влияют на то, как форма отрисовывается и что отправляется в API поиска при отправке формы.
Если вариант использования для поиска позволяет пользователю выбирать только из предложений, это уменьшит область сложности элемента управления, но ограничивает взаимодействие с пользователем.
Функция Azure: получение конкретного документа
API подстановки принимает идентификатор и возвращает объект документа из индекса поиска.
const < SearchClient, AzureKeyCredential >= require("@azure/search-documents"); const < app >= require('@azure/functions'); const < CONFIG >= require("../lib/config"); // Create a SearchClient to send queries const client = new SearchClient( `https://` + CONFIG.SearchServiceName + `.search.windows.net/`, CONFIG.SearchIndexName, new AzureKeyCredential(CONFIG.SearchApiQueryKey) ); app.http('lookup', < methods: ['GET'], authLevel: 'anonymous', handler: async (request, context) =>< context.log(`Lookup processed request for url "$"`); try < const console.log(id); if (!id) < return < status: 404 >> const document = await client.getDocument(id); return < jsonBody: < document: document >>; > catch (error) < return < status: 400, jsonBody: < innerStatusCode: error.statusCode || error.code, error: error.details || error.message >> > > >);
Клиент: получение конкретного документа
Этот программный интерфейс функции вызывается в приложении React \src\pages\Details\Detail.js в рамках инициализации компонента:
import React, < useState >from "react"; import < useParams >from 'react-router-dom'; import CircularProgress from '@mui/material/CircularProgress'; import Container from '@mui/material/Container'; import request from '../api'; import BookDetailsTab from "../components/BookDetail/DetailPage/booktab"; import < useQuery, >from '@tanstack/react-query' export default function Details() < let < id >= useParams(); const [document, setDocument] = useState(<>); const lookupRequest = () => request('/api/lookup?id=' + id, "GET").then(response => < const doc = response.document; setDocument(doc); return response >); const fiveMinutes = 1000 * 60 * 5; /* eslint-disable no-unused-vars */ const < data, isLoading, error >= useQuery( < queryKey: ["lookup", id], queryFn: async() =>lookupRequest(), enabled: id !== undefined, staleTime: fiveMinutes, // time in milliseconds cacheTime: fiveMinutes, //refetchOnMount: false, //refetchOnWindowFocus: false, //refetchOnReconnect: false, >); return ( >> < isLoading ? : />> < error && > ); >
Если клиентское приложение может использовать предварительно созданное содержимое, эта страница является хорошим кандидатом для автоматического создания, так как содержимое является статическим, извлекается непосредственно из индекса поиска.
Следующие шаги
В этом руководстве вы узнали, как создать и загрузить индекс поиска в JavaScript, и вы создали веб-приложение, которое предоставляет интерфейс поиска, включающий панель поиска, фасетную навигацию и фильтры, предложения, страницы и поиск документов.
На следующем шаге можно расширить этот пример в нескольких направлениях:
- Добавьте автозавершение для дополнительных типов.
- Добавление или изменение аспектови фильтров.
- Измените модель проверки подлинности и авторизации, используя идентификатор Microsoft Entra вместо проверки подлинности на основе ключей.
- Измените методологию индексирования. Вместо отправки JSON в индекс поиска предварительно загрузите контейнер БОЛЬШИХ двоичных объектов с набором данных good-books и настройте индексатор BLOB-объектов для приема данных. Зная, как работать с индексаторами, вы можете использовать дополнительные возможности приема данных и обогащения содержимого во время индексирования.
Dart
Dart — язык программирования, который создали для использования в веб-разработке. Идея его создания — постепенно заменить популярный язык JavaScript: Dart позиционируется как решение, лишенное ключевых недостатков JS.
Освойте профессию «Frontend-разработчик»
Что такое Dart
Dart считается языком общего назначения, но его создатели ориентировали его в первую очередь на фронтенд: создание интерфейсов и взаимодействие с браузером. А собственная платформа Dart VM призвана заменить Node.js — инструмент, с помощью которого пишут код на JavaScript для серверной части.
Это высокоуровневый язык: он оперирует абстрактными понятиями, далекими от «железа», но близкими к человеку. Поэтому код на Dart лаконичный и понятный, а синтаксис легко освоить. Особенно удобным Dart считается для людей, которые до этого уже изучали другие языки программирования.
Создатели Dart — компания Google, которая также придумала язык Go. У Dart открытый исходный код, язык полностью бесплатный и свободно распространяется.
Профессия / 9 месяцев
Frontend-разработчик
Создавайте интерфейсы сервисов, которыми пользуются все

Для чего применяется язык Dart
Так как основная идея создания Dart — заменить JavaScript, сам по себе язык ориентирован на веб-разработку. Во встроенных инструментах языка много средств для работы с браузером и интерфейсами, веб-страницами — словом, фронтенд-частью разработки. В то же время в нем есть и инструменты для бэкенда и серверного программирования.
Но пока в веб-программировании, по крайней мере в России, Dart не прижился. В основном разработчиков на этом языке ищут в проектах по мобильной разработке. Дело в том, что на основе Dart написан Flutter — популярный фреймворк для создания мобильных приложений. Поэтому большинство вакансий по Dart — это работа с Flutter и с приложениями под iOS или Android.
В этом нет ничего удивительного. Возможности Dart для создания интерфейсов легко применить в мобильной разработке: они позволяют удобно и быстро создавать приложения.
Кроме того, на Dart написана надстройка CSS под названием SASS. Ею пользуются фронтенд-разработчики для более удобной верстки.
Особенности Dart
Ориентированность на создание интерфейсов. Dart создавался как язык для интерфейсов, поэтому в нем есть много фишек для их разработки. Сейчас эта особенность нашла применение в программировании мобильных приложений: создавать визуальный интерфейс с помощью Dart довольно удобно. Идея создателей языка была в том, чтобы уменьшить количество переключений между разметкой и кодом — чтобы разработчик не терял времени и не отвлекался. На это и направлены некоторые фишки языка. Например, при компилировании в JavaScript автоматически создается шаблонная HTML-страница с разметкой. Ее сразу можно открыть в браузере и посмотреть, что получилось.
Наследие C и C++. Dart испытал сильное влияние системных языков C и C++, и это нашло отражение в его синтаксисе. Он C-подобный: это значит, что правила написания кода и его структура похожи на C. Хотя Dart проще в освоении и ориентирован на другие цели, он унаследовал некоторые важные элементы: например, основной блок программы заключается в функцию main().
Факультативная типизация. Типизация в языках программирования бывает статической и динамической. В первом случае разработчик должен сам указывать, к какому типу будет относиться переменная: число, строка, массив или что-то еще. Во втором случае язык решает это сам на основании того, какие данные записал в переменную разработчик.
В Dart объединили эти подходы — типизация там факультативная. Это значит, что разработчик может указать тип при создании переменной, а может не указывать — допустимы оба подхода. Какой из них лучше использовать, зависит от задачи.
Компилируемость. В отличие от интерпретируемого JavaScript, Dart — компилируемый язык. Это значит, что код на нем проходит через специальную программу-переводчик — компилятор. Она переводит написанное в машинные коды, которые понимает операционная система, поэтому язык работает быстро и может активнее взаимодействовать с ОС.
Два вида компиляции.
- AOT (ahead of time, «прежде времени») — статическая, или опережающая компиляция. Написанная программа целиком переводится в машинные коды, и только после этого ее можно запустить. Это классический вариант компиляции, именно он используется в C++ и большинстве компилируемых языков.
- JIT (just in time, «точно вовремя») — динамическая компиляция. Программа компилируется по частям, и скомпилированные части тут же выполняются. Это роднит идею с интерпретацией — другим подходом к исполнению, когда специальная программа-интерпретатор исполняет код построчно. Обычно JIT используется в языках с байт-кодом, таких как Java.
Программа, скомпилированная AOT, быстрее запускается и работает, но такая компиляция замедляет разработку. После каждого изменения разработчик должен перекомпилировать код полностью — а это лишнее время. JIT, наоборот, ускоряет цикл разработки, но сама по себе программа запускается медленнее и требует больше ресурсов.
Поэтому в Dart и ввели оба вида компиляции: JIT для процесса разработки и AOT для финальной реализации уже готового продукта. Это нужно, чтобы экономить время и совмещать плюсы обоих типов.

Станьте Frontend-разработчиком
и создавайте интерфейсы сервисов, которыми пользуются все
Классическое ООП. В Dart реализован классический подход к объектно-ориентированному программированию, которое сейчас считается одной из наиболее популярных парадигм. В нем есть классы, в том числе абстрактные, реализовано наследование — все это без нововведений и экспериментов, так, как предписывает парадигма. Поэтому писать ООП-код в Dart довольно удобно: не приходится придумывать «костыли» и бороться с особенностями языка.
Изоляторы. Dart — однопоточный язык. Это значит, что все программы на нем выполняются в едином потоке действий, а не в нескольких. Однопоточность тоже роднит его с JavaScript. Но иногда процессы нужно распараллеливать, чтобы несколько действий могли выполняться одновременно. Для этого в Dart реализован механизм изоляторов (isolate). Иногда их еще переводят как изоляты.
Изолятор — это сущность, которая выполняет какие-то действия. У каждого изолятора своя область памяти, он может выполняться одновременно с другими и обмениваться с ними данными. Это своеобразные виртуальные потоки, созданные на более высоком уровне абстракции, чем настоящие.
Управляет ими Event Loop — процесс, который работает, пока открыта программа, и поочередно выполняет код внутри разных изоляторов. Он работает с очередью, действующей по принципу FIFO: «первый вошел, первый вышел». То есть тот процесс, который «пришел» в очередь раньше, и выполнится раньше других. Очередей две: для простых коротких действий и для блоков кода, которые должны выполниться в ответ на какое-то внешнее событие.
Горячая перезагрузка. Удобная особенность Dart — горячая перезагрузка, или hot reload. Термин означает, что код программы можно откорректировать, пока она запущена — и изменения внесутся «на ходу». Для этого не понадобится открывать и снова закрывать программу. В JavaScript и похожих языках тоже есть инструменты для hot reload, но там приходится использовать внешние решения, а в Dart эта возможность встроена изначально. Поэтому горячая перезагрузка в этом языке работает быстрее и эффективнее.
Dart и Dart 2
Современная версия языка называется Dart 2. Она вышла в 2018 году и отличается от более старой версии: в ней улучшили систему типов, сделали синтаксис лаконичнее, добавили новые возможности для создания клиентской части приложений. Инструменты новой версии позволяют реже переключаться между разметкой и кодом, а сущности можно описывать короче.
С выходом Dart 2 язык снова испытал взлет популярности. Сейчас новая версия считается более актуальной, поэтому если разработчики говорят про Dart, чаще всего они имеют в виду Dart 2.
Что такое Flutter и как он связан с Dart
Flutter — один из наиболее популярных фреймворков на Dart. Обычно именно с ним связаны вакансии разработчиков на этом языке. Фреймворк и SDK (набор средств разработки) предназначены для создания приложений под iOS и Android.
Особенность Flutter в том, что он позволяет имитировать нативную разработку под мобильные ОС. Это значит, что с помощью этого фреймворка и SDK можно создавать приложения, использующие системные элементы iOS и Android — они будут быстрыми, удобными и фактически неотличимыми от по-настоящему нативных программ.
Во Flutter легко создавать интерфейсы — в SDK есть визуальные компоненты, с помощью которых можно «собрать» дизайн. Код пишется на Dart, хотя движок Flutter написан на C++.
Пока что Flutter не так часто используется для создания приложений, как Java, Kotlin и Swift, но это интересный и перспективный вариант для мобильной разработки.
Dart и JavaScript
В отличие от других языков, созданных как альтернатива JS, Dart не разрабатывался на его основе. Это полностью самостоятельный язык программирования, независимый от JavaScript. Несмотря на схожесть синтаксиса и назначения, языки не связаны.
Тем не менее код на Dart можно скомпилировать в код на JavaScript — перевести с помощью специальной утилиты, встроенной в язык. Это сделано потому, что браузеры пока понимают только JS, а код на Dart выполнить не смогут. Так что разработчик может написать код для фронтенда на Dart, а потом автоматически преобразовать его в JavaScript и запустить в браузере.
Сможет ли Dart заменить JavaScript
Несмотря на то что Dart позиционировался как аналог JavaScript, пока что JS остается лидером в веб-разработке и самым используемым языком в мире. Дело в том, что заменить его не так просто. Веб-браузеры умеют обрабатывать только JS, а чтобы «научить» их понимать другие языки, понадобится серьезно их переписывать. Dart пока не настолько популярен, чтобы браузеры пошли на такие масштабные нововведения ради него.
Поэтому, даже если написать клиентскую часть сайта на Dart, код все равно понадобится компилировать в JavaScript. Поэтому же преимущественная область использования Dart сейчас — мобильная разработка, а не веб.
Некоторые разработчики считают, что за Dart будущее и со временем интернет перейдет на него. Но ожидать, что он заменит JavaScript в течение ближайших десятилетий, не стоит. Поэтому JS останется востребованным еще долго — хотя веб-разработчики считают, что на Dart стоит обратить внимание.

Станьте Frontend-разработчиком
и создавайте интерфейсы сервисов, которыми пользуются все
Перспективы Dart
Сейчас Dart не входит даже в топ-20 самых часто используемых языков программирования. Но некоторые считают, что у него большое будущее. Причин этому три:
- Он удобен для разработки интерфейсов и в принципе для веб-программирования, при этом лишен части недостатков более популярного JavaScript.
- Сам по себе язык простой и понятный, его легко изучить и начать применять в проектах.
- Язык активно продвигает Google, а поддержка крупной корпорации — хороший стимул для развития технологии.
Несмотря на это, в ближайшие несколько лет сфера применения Dart скорее всего не изменится: мобильные приложения, созданные в экосистеме Flutter. На эту область и стоит рассчитывать, если вы хотите учить язык.
Преимущества Dart
- Удобство. На языке просто писать, у него лаконичный синтаксис, понятный разработчикам.
- Простота освоения. Разработчики говорят, что освоить Dart легко, в особенности если до этого у человека был опыт программирования.
- Широкие возможности. В языке много особенностей и фишек, расширяющих возможности и облегчающих разработку.
- Высокая производительность. Dart компилируемый, поэтому быстрый и мощный. Он нормально работает и на клиенте, и на сервере.
- Поддержка Google. Корпорация поддерживает и рекламирует язык, стремится повысить его популярность. Поэтому у Dart отличная документация и туториалы.
Недостатки Dart
- Низкая популярность. К сожалению, вакансий на Dart все еще немного: в России их всего несколько десятков, и в основном они включают в себя разработку на Flutter. Но, возможно, в ближайшие годы язык станет популярнее, и разработчики на нем будут нужны в большем количестве.
- Небольшое комьюнити. Эта проблема — следствие предыдущей: разработчиков на Dart мало, поэтому сообщество у языка небольшое. Людей в нем мало, и со стороны комьюнити язык развивается не так активно, как мог бы.
- Неспособность полностью заменить JS. Dart все еще не может стать аналогом JavaScript и вряд ли сможет в ближайшие годы. Он не выполняется в популярных браузерах, а фреймворков и библиотек для него пока слишком мало, чтобы покрыть все возможности экосистемы JS.
Стоит ли изучать язык Dart
Считается, что в большинстве случаев изучение Dart — идея чисто факультативная, если вы не пишете на Flutter. Но мобильным разработчикам этот язык будет полезен: на Flutter можно создавать мощные приложения, а работает он на Dart. Веб-разработчикам же советуют изучать Dart по собственному желанию — на случай если язык действительно начнет активно использоваться в веб-разработке.
Вакансий непосредственно по Dart немного, поэтому его не советуют изучать в качестве первого и основного языка: найти работу может быть непросто. Но в качестве дополнительного навыка Dart — отличный выбор и для мобильных, и для фронтенд- или бэкенд-разработчиков.
Хотите узнать больше про IT? Записывайтесь на курсы: мы поможем выбрать и освоить новую профессию!
Frontend-разработчик
Научитесь создавать удобные и эффектные сайты, сервисы и приложения, которые нужны всем. Сегодня профессия на пике актуальности: в России 9000+ вакансий, где требуется знание JavaScript.

Статьи по теме:
