Другое

Исправление ошибки импорта 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’. Вот моя реализация:

html
<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 содержит:

javascript
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). Вот как правильно интегрировать эти библиотеки:

Содержание

Понимание конфликта систем модулей

Основная проблема возникает из-за смешивания двух разных систем JavaScript модулей:

  1. AMD (Asynchronous Module Definition) - Используется ArcGIS JSAPI 4.12
  2. 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:

html
<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 для сборки обеих библиотек вместе:

javascript
// 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']
  }
};
javascript
// 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 модулей:

html
<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 модулей:

javascript
// milsymbol-amd.js (измененная версия)
define(function(require) {
    // Загрузка зависимостей
    var ms = {};
    
    // Загрузка модуля символов
    require(["./ms/symbol.js"], function(Symbol) {
        ms.Symbol = Symbol;
    });
    
    // Возврат модуля
    return ms;
});

Затем используйте его с вашей исходной настройкой AMD:

html
<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 помогает преодолеть разрыв между разными системами модулей:

html
<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>

Лучшие практики для интеграции модулей

  1. Совместимость версий: Убедитесь, что ваша версия ArcGIS поддерживает используемую вами систему модулей. Как объясняется в статье Esri, “фундаментальная функциональность API абсолютно одинакова между AMD и ES модулями.”

  2. Используйте сборщик для продакшена: Для производственных приложений рассмотрите использование Webpack или Rollup для сборки всех зависимостей, что разрешает конфликты модулей и оптимизирует загрузку.

  3. Управляйте порядком загрузки: Убедитесь, что зависимости загружаются в правильном порядке, особенно при смешивании систем модулей.

  4. Обработка ошибок: Всегда включайте обработку ошибок для загрузки модулей, как показано в решении с динамическими импортами.

  5. Рассмотрите интеграцию с фреймворками: При использовании фреймворков, таких как Angular или React, ищите специфичные для фреймворка библиотеки интеграции ArcGIS, например angular-arcgis-es-modules.

Наиболее практичным решением для вашей текущей настройки будет Решение 1 (динамические импорты) или Решение 5 (esri-loader), поскольку они работают с ArcGIS 4.12 без необходимости внесения значительных изменений в существующую кодовую базу.

Источники

  1. ArcGIS API for JavaScript – Learn about ES modules
  2. Migrating from 3.x to 4.32 | ArcGIS Maps SDK for JavaScript
  3. What’s New in the ArcGIS API for JavaScript (version 4.18)
  4. GitHub - Esri/esri-loader: A tiny library to help load ArcGIS API for JavaScript modules
  5. 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 модулей. Всегда тщательно тестируйте в целевых браузерах и учитывайте долгосрочные последствия поддержки для каждого подхода.

Авторы
Проверено модерацией
Модерация