Подключение API на Javascript
Примечание
Получите ключ для пакета «JavaScript API»
Ключ будет активирован в течение 15 минут после получения.
JS API 3.0 работает только с ключами, у которых заполнено поле "Ограничение по HTTP Referer". Подробнее об ограничениях
Обычное подключение
<!DOCTYPE html>
<html>
<head>
<!-- Вместо YOUR_API_KEY подставить значение настоящего ключа -->
<script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU"></script>
<script src="index.js"></script>
</head>
<body>
<div id="app" style="width: 600px; height: 400px"></div>
</body>
</html>
async function initMap() {
await ymaps3.ready;
const {YMap, YMapDefaultSchemeLayer} = ymaps3;
const map = new YMap(
document.getElementById('app'),
{
location: {
center: [37.588144, 55.733842],
zoom: 10
}
}
);
map.addChild(new YMapDefaultSchemeLayer());
}
initMap();
{
"devDependencies": {
"http-server": "14.1.1"
},
"scripts": {
"start": "npx http-server ."
}
}
Поставьте зависимости и запустите локальный сервер:
npm install
npm run start
Откройте приложение
Внимание
Работа API гарантируется в браузерах, чья аудитория больше 0.5% по данным Browserslist.
Особенности обычного подключения
- JS API распространяется исключительно по ссылке, которую нужно подключать в шапке документа.
- Компоненты API всегда загружаются асинхронно.
- Компоненты существуют только в глобальной области видимости в переменной
ymaps3. - Компоненты доступны только после разрешения промиса
ymaps3.ready.
Промисymaps3.readyгарантирует, что все компоненты основного модуляJavasript APIзагружены, аDOMпостроен.
Параметры загрузки API
apikey |
Обязательный параметр Ключ, полученный в Кабинете Разработчика. Примечание Ключ будет активирован в течение 15 минут после получения. JS API 3.0 работает только с ключами, у которых заполнено поле "Ограничение по HTTP Referer". Подробнее об ограничениях |
lang |
Обязательный параметр Локаль, задается в виде
|
Внимание
Обработчики событий типа document.ready, window.onload, jQuery.ready не сигнализируют об окончании загрузки компонентов JS API.
Подключение через top-level-await (рекомендуется)
<!DOCTYPE html>
<html>
<head>
<!-- Вместо YOUR_API_KEY подставить значение настоящего ключа -->
<script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU"></script>
<script type="module" src="index.js"></script>
</head>
<body>
<div id="app" style="width: 600px; height: 400px"></div>
</body>
</html>
import { YMap, YMapDefaultSchemeLayer } from './lib/ymaps3.js'
const map = new YMap(
document.getElementById('app'),
{
location: {
center: [37.588144, 55.733842],
zoom: 10
}
}
);
map.addChild(new YMapDefaultSchemeLayer());
await ymaps3.ready;
export const {YMap, YMapDefaultSchemeLayer} = ymaps3;
{
"devDependencies": {
"http-server": "14.1.1"
},
"scripts": {
"start": "npx http-server ."
}
}
Поставьте зависимости и запустите локальный сервер:
npm install
npm run start
Откройте приложение
Особенности
-
В теге script, который загружает скомпилированный проектный js, указываем атрибут
type="module", чтобы активировать поддержку ECMAScript Modules (ESM) и top-level-await:<script type="module" src="index.js"></script>Поддержка ESM при использовании бандлеров
Если для сборки проекта используется бандлер, например Webpack, то в файл
package.jsonнеобходимо добавить"type": "module" -
В файле
lib/ymaps3.jsдожидаемся полной загрузки JS API, после чего экспортируем необходимые компоненты карты для их использования в других частях проекта:await ymaps3.ready; export const {YMap, YMapDefaultSchemeLayer} = ymaps3; -
Использование top-level-await в
lib/ymaps3.jsгарантирует выполнениеymaps3.readyдо импорта компонентов карты, поэтому проектный код можно писать короче и опрятнее (больше не нужна асинхронная функция initMap):import { YMap, YMapDefaultSchemeLayer } from './lib/ymaps3.js' const map = new YMap({...});
Подключение с Webpack
Приемущества
С помощью Webpack и его опции externals можно:
- не подключать JS API в шапке
HTML-документа; - вызывать компоненты JS API не из глобальной переменной, а более привычно, словно они поставляются через
npm-пакет; - не обрабатывать разрешение промиса
ymaps3.ready.
Это можно сделать 3 способами:
№1, без глобальной переменной ymaps3
№2, без загрузчика JS API
№3, без разрешения промиса ymaps3.ready
Способ №1, без глобальной переменной ymaps3
<!DOCTYPE html>
<html>
<head>
<!-- Вместо YOUR_API_KEY подставить значение настоящего ключа -->
<script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU"></script>
<script src="build/bundle.js"></script>
</head>
<body>
<div id="app" style="width: 600px; height: 400px"></div>
</body>
</html>
import * as ymaps3 from 'ymaps3';
async function initMap() {
await ymaps3.ready;
const {YMap, YMapDefaultSchemeLayer} = ymaps3;
const map = new YMap(
document.getElementById('app'),
{
location: {
center: [37.588144, 55.733842],
zoom: 10
}
}
);
map.addChild(new YMapDefaultSchemeLayer());
}
initMap();
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build'),
},
externals: {
ymaps3: 'ymaps3'
},
devtool: 'cheap-source-map'
};
{
"devDependencies": {
"http-server": "14.1.1",
"webpack": "5.88.2",
"webpack-cli": "5.1.4"
},
"scripts": {
"build": "webpack",
"start": "npx http-server ."
}
}
Поставьте зависимости, соберите проект и запустите локальный сервер:
npm install
npm run build
npm run start
Откройте приложение
Особенности
-
На
HTML-странице всё ещё подключаем загрузчикJS API:<head> <script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU"></script> </head>Успешная загрузка скрипта гарантирует, что в глобальном доступе появляется переменная
ymaps3. -
В
webpack.config.jsобъявляем внешнюю переменнуюymaps3:module.exports = { // ... externals: { ymaps3: 'ymaps3' } };Благодаря этому в проектном коде появляется возможность импортировать
ymaps3так, словно кодymaps3поставляется не через глобальную переменную, а черезnpm-пакет:import * as ymaps3 from 'ymaps3'; // ...
Способ №2, без загрузчика JS API
<!DOCTYPE html>
<html>
<head>
<script src="build/bundle.js"></script>
</head>
<body>
<div id="app" style="width: 600px; height: 400px"></div>
</body>
</html>
import * as ymaps3 from 'ymaps3';
async function initMap() {
await ymaps3.ready;
const {YMap, YMapDefaultSchemeLayer} = ymaps3;
const map = new YMap(
document.getElementById('app'),
{
location: {
center: [37.588144, 55.733842],
zoom: 10
}
}
);
map.addChild(new YMapDefaultSchemeLayer());
}
initMap();
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build'),
},
externalsType: 'script',
externals: {
// Вместо YOUR_API_KEY подставить значение настоящего ключа
ymaps3: ['https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU', 'ymaps3']
},
devtool: 'cheap-source-map'
};
{
"devDependencies": {
"http-server": "14.1.1",
"webpack": "5.88.2",
"webpack-cli": "5.1.4"
},
"scripts": {
"build": "webpack",
"start": "npx http-server ."
}
}
Поставьте зависимости, соберите проект и запустите локальный сервер:
npm install
npm run build
npm run start
Откройте приложение
Особенности
Это видоизмененный первый способ:
-
Больше не нужно в шапке
HTML-страницы подключать тег<script>. Этим занимается самwebpack. -
В
webpack.config.jsтак же объявляется внешняя переменнаяymaps3, но в ней указывается путь к загрузчику API:module.exports = { // ... externalsType: 'script', externals: { ymaps3: ['https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU', 'ymaps3'] } };
Ограничения способа №1 и №2
В обоих вышеописанных способах импортируется не готовое API, а легковесный загрузчик. Компоненты становятся полностью доступны только после разрешения промиса ymaps3.ready. Это означает, что если ваш клиентский код разбит на свои модули, и JS API используется сразу в нескольких ваших модулях, следует в каждом вашем модуле дожидаться разрешения промиса ymaps3.ready.
Например, вы хотите отобразить на странице сразу две карты, каждую в своем контейнере. Вам удобнее описывать эту функциональность не в одном большом модуле, а в двух разных, например с именами module-a.js и module-b.js. Тогда с использованием вышеописанных способов код ваших модулей будет выглядеть примерно так:
// Файл module-a.js
import * as ymaps3 from 'ymaps3';
async function initMap() {
// Дождитесь резолва`ymaps3.ready`
await ymaps3.ready;
const {YMap} = ymaps3;
// Карта инициализируется в первом контейнере
const map = new YMap({document.getElementById('first-map-container')});
}
initMap();
// Файл module-b.js
import * as ymaps3 from 'ymaps3';
async function initMap() {
// Дождитесь резолва`ymaps3.ready`
await ymaps3.ready;
const {YMap} = ymaps3;
// Карта инициализируется во втором контейнере
const map = new YMap({document.getElementById('second-map-container')});
}
initMap();
Приходится в каждом модуле дожидаться разрешения ymaps3.ready. Это неудобно, хотелось бы писать код проще:
// Файл module-a.js
import * as ymaps3 from 'ymaps3';
const {YMap} = ymaps3;
const map = new YMap({document.getElementById('first-map-container')});
// Файл module-b.js
import * as ymaps3 from 'ymaps3';
const {YMap} = ymaps3;
const map = new YMap({document.getElementById('second-map-container')});
Чтобы этого достичь, воспользуйтесь третьим способом.
Способ №3, без разрешения промиса ymaps3.ready
<!DOCTYPE html>
<html>
<head>
<script src="build/bundle.js"></script>
</head>
<body>
<div id="app" style="width: 600px; height: 400px"></div>
</body>
</html>
import * as ymaps3 from 'ymaps3';
const {YMap, YMapDefaultSchemeLayer} = ymaps3;
const map = new YMap(
document.getElementById('app'),
{
location: {
center: [37.588144, 55.733842],
zoom: 10
}
}
);
map.addChild(new YMapDefaultSchemeLayer());
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build'),
},
externalsType: 'script',
externals: {
// Вместо YOUR_API_KEY подставить значение настоящего ключа
ymaps3: [
`promise new Promise((resolve) => {
if (typeof ymaps3 !== 'undefined') {
return ymaps3.ready.then(() => resolve(ymaps3));
}
const script = document.createElement('script');
script.src = "https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU";
script.onload = () => {
ymaps3.ready.then(() => resolve(ymaps3));
};
document.head.appendChild(script);
})`
]
},
devtool: 'cheap-source-map'
};
{
"devDependencies": {
"http-server": "14.1.1",
"webpack": "5.88.2",
"webpack-cli": "5.1.4"
},
"scripts": {
"build": "webpack",
"start": "npx http-server ."
}
}
Поставьте зависимости, соберите проект и запустите локальный сервер:
npm install
npm run build
npm run start
Откройте приложение
Особенности
Это почти тот же способ №2, только в webpack.config.js при объявлении переменной ymaps3 несколько иначе указывается путь к загрузчику API и там же происходит разрешение промиса ymaps3.ready.
При таком подключении в собранном проектном js-файле становятся доступны полностью загруженные модули JS API и гарантируется исполнение ymaps3.ready, поэтому проектный код можно писать короче и опрятнее:
import * as ymaps3 from 'ymaps3';
const {YMap} = ymaps3;
const map = new YMap({...});
Внимание
При таком способе подключения проектный код не начнет выполняться до тех пор, пока компоненты JS API не будут полностью загружены.
Ограничение способа №3
Например, вы хотите показывать анимацию загрузки до момента, пока не загрузились компоненты карты. Подключили JS API способом №3 и написали для этого вот такой код. К сожалению, у вас не получится выполнить задачу:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as ymaps3 from 'ymaps3';
// Выполнение этой строки начнется только после загрузки ymaps3 и резолва ymaps3.ready
const reactify = ymaps3.reactify.bindTo(React, ReactDOM);
const {YMap} = reactify.module(ymaps3);
function MapView() {
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
setLoading(false);
}, []);
// Этот код бесполезен. Он, конечно, выполнится при монтировании компонента в DOM, но
// монтирование-то произойдет лишь после загрузки ymaps3 и резолва ymaps3.ready.
// Поэтому при монтировании пользователь на долю секунды увидит статус 'Loading...',
// а потом сразу же случится useEffect, который отменит показ анимации загрузки.
if (loading) {
return <div>Loading...</div>;
}
return <YMap />;
}
function App() {
return (
<MapView />
);
}
Главный недостаток webpack-подключения №3 состоит в том, что в проектных модулях не будет ничего выполняться до тех пока, пока компоненты JS API не загрузятся полностью.
Чтобы показать анимацию загрузки, от способа №3 придётся отказаться:
- Перейти на webpack-подключение №1 или №2.
- Внутри
React.useEffectнужно дождатьсяymaps3.readyи только после этого снять флажокloading. - Код, использующий
reactify-модуль, необходимо поместить внутрь компонентаMapViewтак, чтобыJS-интерпретатор смог "прочитать" эти строчки только после разрешенияymaps3.ready:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as ymaps3 from 'ymaps3';
function MapView() {
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
ymaps3.ready.then(() => setLoading(false));
}, []);
if (loading) {
return <div>Loading...</div>;
}
const reactify = ymaps3.reactify.bindTo(React, ReactDOM);
const {YMap} = reactify.module(ymaps3);
return <YMap />;
}
function App() {
return (
<MapView />
);
}
Переключение языка
Помните, что при подключении API указывается язык. Если вы создаете интернациональные сайты, при любом способе подключения следите за его переключением.
Например, для подключения с Webpack третьим способом это можно сделать так:
module.exports = {
//...
externals: {
ymaps3: [
`promise new Promise((resolve) => {
...
const language_region = ['ru', 'ru-Ru'].includes(navigator.language) ? 'ru-Ru' : 'en-US';
script.src = "https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=" + lang;
...
})`
]
}
};
Подключение пакетов и модулей
JS API предоставляет дополнительные пакеты и модули, полезные для решения специфических задач. Для их загрузки предусмотрен метод ymaps3.import.