Исправление ошибки импорта milsymbol.js с ArcGIS 4.12
Узнайте, как устранить ошибку 'Uncaught SyntaxError: Cannot use import statement outside a module' при интеграции milsymbol.js с ArcGIS JSAPI 4.12. Полное руководство с 5 рабочими решениями.
Как исправить ошибку ‘Uncaught SyntaxError: Cannot use import statement outside a module’ при использовании milsymbol.js с ArcGIS JSAPI 4.12? Я пытаюсь интегрировать библиотеку Spatial Illusions milsymbol для отрисовки военных символов на карте ArcGIS. Когда я добавляю milsymbol.js в свой скрипт, возникает ошибка ‘Uncaught SyntaxError: Cannot use import statement outside a module’. Добавление type=‘module’ в тег script устраняет эту ошибку, но вызывает новую ошибку ‘Uncaught ReferenceError: ms is not defined’. В официальной документации не упоминается использование type=‘module’. Вот моя реализация:
<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
<script src="https://js.arcgis.com/4.12/"></script>
<script type="module" src="milsymbol-2.0.0/src/milsymbol.js"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/MapImageLayer",
"esri/layers/FeatureLayer"
], function (Map, MapView, MapImageLayer, FeatureLayer) {
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [121, 23],
zoom: 7
});
});
</script>
Файл milsymbol.js содержит:
import { ms } from "./ms.js";
import Symbol from "./ms/symbol.js";
ms.Symbol = Symbol;
export { ms };
Как можно правильно интегрировать milsymbol.js с ArcGIS JSAPI 4.12 без этих ошибок?
Решение ошибки ‘Uncaught SyntaxError: Cannot use import statement outside a module’ при интеграции milsymbol.js с ArcGIS JSAPI 4.12
Чтобы решить ошибку ‘Uncaught SyntaxError: Cannot use import statement outside a module’ при интеграции milsymbol.js с ArcGIS JSAPI 4.12, необходимо устранить фундаментальную несовместимость систем модулей между ES6 модулями (используемыми milsymbol) и AMD (используемыми ArcGIS 4.12). Вот как правильно интегрировать эти библиотеки:
Содержание
- Понимание конфликта систем модулей
- Решение 1: Использование динамических импортов с AMD
- Решение 2: Сборка с помощью Webpack
- Решение 3: Обновление до ArcGIS 4.18+
- Решение 4: Конвертация milsymbol в синтаксис AMD
- Решение 5: Использование вспомогательной библиотеки esri-loader
- Лучшие практики для интеграции модулей
Понимание конфликта систем модулей
Основная проблема возникает из-за смешивания двух разных систем JavaScript модулей:
- AMD (Asynchronous Module Definition) - Используется ArcGIS JSAPI 4.12
- ES6 Modules (ESM) - Используется milsymbol.js
Согласно документации Esri, ES модули были введены в ArcGIS API версии 4.18. Поскольку вы используете версию 4.12, официально поддерживаются только AMD модули. При добавлении type="module" в тег script, браузер обрабатывает его как ES модуль, но AMD модули ArcGIS не могут получить доступ к объекту ms, экспортируемому milsymbol.
Решение 1: Использование динамических импортов с AMD
Этот подход динамически загружает ES модуль внутри обратного вызова AMD require:
<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
<script src="https://js.arcgis.com/4.12/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/MapImageLayer",
"esri/layers/FeatureLayer"
], function (Map, MapView, MapImageLayer, FeatureLayer) {
// Динамический импорт milsymbol как ES модуля
import('https://unpkg.com/milsymbol@2.0.0/dist/milsymbol.js').then(milsymbolModule => {
const ms = milsymbolModule.ms;
// Теперь можно использовать и ArcGIS, и milsymbol
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
console.log('Военный символ создан:', symbol);
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [121, 23],
zoom: 7
});
}).catch(error => {
console.error('Не удалось загрузить milsymbol:', error);
});
});
</script>
Решение 2: Сборка с помощью Webpack
Создайте конфигурацию Webpack для сборки обеих библиотек вместе:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
resolve: {
extensions: ['.js']
}
};
// src/index.js
import 'https://js.arcgis.com/4.12/';
import { ms } from 'milsymbol';
// Ваш код приложения
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
var map = new Map({ basemap: "topo-vector" });
var view = new MapView({ container: "viewDiv", map: map, center: [121, 23], zoom: 7 });
Решение 3: Обновление до ArcGIS 4.18+
Согласно руководству по миграции Esri, ES модули были введены в версии 4.18. Обновление даст вам нативную поддержку ES модулей:
<link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/css/main.css">
<script type="module" src="https://js.arcgis.com/4.28/"></script>
<script type="module" src="https://unpkg.com/milsymbol@2.0.0/dist/milsymbol.js"></script>
<script type="module">
import Map from "https://js.arcgis.com/4.28/esri/Map.js";
import MapView from "https://js.arcgis.com/4.28/esri/views/MapView.js";
import { ms } from "https://unpkg.com/milsymbol@2.0.0/dist/milsymbol.js";
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
var map = new Map({ basemap: "topo-vector" });
var view = new MapView({ container: "viewDiv", map: map, center: [121, 23], zoom: 7 });
</script>
Решение 4: Конвертация milsymbol в синтаксис AMD
Измените файл milsymbol.js для использования синтаксиса AMD вместо ES6 модулей:
// milsymbol-amd.js (измененная версия)
define(function(require) {
// Загрузка зависимостей
var ms = {};
// Загрузка модуля символов
require(["./ms/symbol.js"], function(Symbol) {
ms.Symbol = Symbol;
});
// Возврат модуля
return ms;
});
Затем используйте его с вашей исходной настройкой AMD:
<script src="https://js.arcgis.com/4.12/"></script>
<script src="milsymbol-amd.js"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/MapImageLayer",
"esri/layers/FeatureLayer"
], function (Map, MapView, MapImageLayer, FeatureLayer) {
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
// Остальной код ArcGIS...
});
</script>
Решение 5: Использование вспомогательной библиотеки esri-loader
Библиотека esri-loader помогает преодолеть разрыв между разными системами модулей:
<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
<script src="https://unpkg.com/esri-loader@3"></script>
<script src="https://unpkg.com/milsymbol@2.0.0/dist/milsymbol.js"></script>
<script>
// Загрузка модулей ArcGIS с помощью esri-loader
esriLoader.loadModules([
"esri/Map",
"esri/views/MapView",
"esri/layers/MapImageLayer",
"esri/layers/FeatureLayer"
]).then(([Map, MapView, MapImageLayer, FeatureLayer]) => {
var map = new Map({ basemap: "topo-vector" });
var view = new MapView({ container: "viewDiv", map: map, center: [121, 23], zoom: 7 });
// Использование milsymbol
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
console.log('Военный символ создан:', symbol);
}).catch(err => {
console.error("Ошибка загрузки модулей ArcGIS:", err);
});
</script>
Лучшие практики для интеграции модулей
-
Совместимость версий: Убедитесь, что ваша версия ArcGIS поддерживает используемую вами систему модулей. Как объясняется в статье Esri, “фундаментальная функциональность API абсолютно одинакова между AMD и ES модулями.”
-
Используйте сборщик для продакшена: Для производственных приложений рассмотрите использование Webpack или Rollup для сборки всех зависимостей, что разрешает конфликты модулей и оптимизирует загрузку.
-
Управляйте порядком загрузки: Убедитесь, что зависимости загружаются в правильном порядке, особенно при смешивании систем модулей.
-
Обработка ошибок: Всегда включайте обработку ошибок для загрузки модулей, как показано в решении с динамическими импортами.
-
Рассмотрите интеграцию с фреймворками: При использовании фреймворков, таких как Angular или React, ищите специфичные для фреймворка библиотеки интеграции ArcGIS, например angular-arcgis-es-modules.
Наиболее практичным решением для вашей текущей настройки будет Решение 1 (динамические импорты) или Решение 5 (esri-loader), поскольку они работают с ArcGIS 4.12 без необходимости внесения значительных изменений в существующую кодовую базу.
Источники
- ArcGIS API for JavaScript – Learn about ES modules
- Migrating from 3.x to 4.32 | ArcGIS Maps SDK for JavaScript
- What’s New in the ArcGIS API for JavaScript (version 4.18)
- GitHub - Esri/esri-loader: A tiny library to help load ArcGIS API for JavaScript modules
- Using ES Modules with the ArcGIS JSAPI
Заключение
Интеграция milsymbol.js с ArcGIS JSAPI 4.12 требует тщательной обработки различий в системах модулей. Ключевые решения:
- Используйте динамические импорты внутри обратных вызовов AMD для немедленной совместимости
- Рассмотрите возможность обновления до ArcGIS 4.18+ для нативной поддержки ES модулей
- Используйте сборщики, такие как Webpack, для производственных приложений
- Воспользуйтесь вспомогательными библиотеками, такими как esri-loader, для упрощения загрузки модулей
- Конвертируйте библиотеки в синтаксис AMD при необходимости
Для вашего конкретного случая с версией 4.12 подход с динамическими импортами предоставляет наиболее простое решение, которое сохраняет вашу существующую AMD структуру, позволяя использование ES6 модулей. Всегда тщательно тестируйте в целевых браузерах и учитывайте долгосрочные последствия поддержки для каждого подхода.