You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gatsby集成Maplibre GL运行时报maplibregl is undefined错误如何解决

Gatsby站点引入Maplibre地图运行时报maplibregl未定义错误的解决办法

我想要在Gatsby站点中展示Maplibre地图,该功能在React项目中可以正常实现。

执行gatsby develop命令没有出现报错,但火狐浏览器运行时抛出如下错误:
maplibre_gl__WEBPACK_IMPORTED_MODULE_2__.maplibregl is undefined

火狐浏览器报错截图

Chrome浏览器报错如下:
Chrome浏览器报错截图

package.json依赖配置

"dependencies": {
   "gatsby": "^3.13.0",
   "gatsby-image": "^3.11.0",
   "gatsby-plugin-feed": "^3.13.0",
   "gatsby-plugin-layout": "^2.13.0",
   "gatsby-plugin-local-search": "^2.0.1",
   "gatsby-plugin-react-helmet": "^4.13.0",
   "gatsby-plugin-sharp": "^3.13.0",
   "gatsby-remark-autolink-headers": "^4.10.0",
   "gatsby-remark-images": "^5.10.0",
   "gatsby-remark-prismjs": "^5.10.0",
   "gatsby-source-filesystem": "^3.13.0",
   "gatsby-transformer-remark": "^4.10.0",
   "gatsby-transformer-sharp": "^3.13.0",
   "maplibre-gl": "^1.15.2",
   "prismjs": "^1.24.1",
   "prop-types": "^15.7.2",
   "query-string": "^7.0.1",
   "react": "^17.0.2",
   "react-dom": "^17.0.2",
   "react-helmet": "^6.1.0",
   "react-use-flexsearch": "^0.1.1"
 },
 "devDependencies": {
   "eslint": "^7.32.0",
   "eslint-config-react-app": "^6.0.0",
   "gatsby-plugin-manifest": "^3.13.0",
   "postcss": "^8.3.6"
 }

地图组件map.js代码

import React, { useEffect, useRef } from "react"
import PropTypes from "prop-types"
import { maplibregl } from "maplibre-gl"
import "maplibre-gl/dist/maplibre-gl.css"

import { siteMetadata } from "../../gatsby-config"

const Map = ({ zoom, center, minZoom, maxZoom }) => {
  const { mapboxToken, maptilerToken } = siteMetadata

  // 该ref存储地图DOM节点,用于传入MapLibre GL
  const mapNode = useRef(null)

  // 该ref存储实例化后的地图对象,可在其他hook中调用
  const mapRef = useRef(null)

  useEffect(() => {
    let mapCenter = center
    let mapZoom = zoom


    const map = new maplibregl.Map({
      container: mapNode.current,
      style:
        `https://api.maptiler.com/maps/streets/style.json?key=YymZPIGfniu7apIvln6X`,
      center: mapCenter,
      zoom: mapZoom,
      minZoom,
      maxZoom,
    })
    mapRef.current = map
    // window.map = map // 用于控制台调试查询

    map.on("load", () => {})

    return () => {
      map.remove()
    }
  }, [])
  return <div ref={mapNode} style={{ width: "100vh", height: "100vh" }} />
}

Map.propTypes = {
  center: PropTypes.arrayOf(PropTypes.number),
  zoom: PropTypes.number,
}

Map.defaultProps = {
  center: [0, 0],
  zoom: 0,
  minZoom: 0,
}

export default Map

页面引入组件的代码

import * as React from "react"
import Map from "../components/map"


const IndexPage = () => (
  <>
    <h1>Hi people</h1>
    <p>
      Welcome to your new Gatsby Maplibre site. Here is a map without extras
    </p>
    <Map />
  </>
)

export default IndexPage

执行gatsby build命令也没有报错,但浏览器开发者工具中可以看到如下错误栈:

TypeError: o.maplibregl is undefined
    a map.js:24
    Fi React
    unstable_runWithPriority scheduler.production.min.js:18
    React 3
    D scheduler.production.min.js:16
    onmessage scheduler.production.min.js:12
react-dom.production.min.js:216:199
    React 5
    unstable_runWithPriority scheduler.production.min.js:18
    React 4
    D scheduler.production.min.js:16
    onmessage scheduler.production.min.js:12

运行环境信息

  • OS: Linux 5.11 Ubuntu 20.04.3 LTS (Focal Fossa)
  • CPU: (2) x64 Intel(R) Pentium(R) CPU 4417U @ 2.30GHz
  • Shell: 5.0.17 - /bin/bash
  • Node: 14.16.0 - ~/.nvm/versions/node/v14.16.0/bin/node
  • Yarn: 1.22.5 - /usr/bin/yarn
  • npm: 7.6.2 - ~/.nvm/versions/node/v14.16.0/bin/npm
  • Python: 2.7.18 - /usr/bin/python
  • Chrome: 92.0.4515.159
  • Firefox: 91.0
  • gatsby: ^3.13.0 => 3.13.0
  • gatsby-cli: 3.13.0

错误原因

这个问题是两个因素共同导致的:

  1. Maplibre GL 1.x版本默认采用CommonJS导出规范,没有ES模块的命名导出,所以import { maplibregl } from 'maplibre-gl'这种写法在Webpack打包时无法正确识别模块导出,服务端打包(Gatsby的build阶段是Node环境运行)不会报错,但浏览器端运行时找不到对应的导出对象。
  2. Gatsby默认会在服务端预渲染所有页面组件,Maplibre依赖浏览器的window、canvas等API,服务端运行时也可能引发隐性问题。

解决步骤

第一步:修改maplibre-gl的引入方式

将map.js中引入maplibre的代码替换为默认导入:

// 替换原来的import { maplibregl } from "maplibre-gl"
import maplibregl from 'maplibre-gl'

如果上面的写法仍报错,可以改成导入整个模块再取挂载的对象:

import * as maplibre from 'maplibre-gl'
const maplibregl = maplibre.default ?? maplibre.maplibregl

第二步:配置组件仅在客户端加载

Gatsby支持通过loadable-components让地图组件只在浏览器端渲染,避免服务端预渲染的问题:
首先安装依赖:

npm install @loadable/component
# 或者
yarn add @loadable/component

然后修改页面引入组件的代码:

import * as React from "react"
import loadable from '@loadable/component'

// 配置loadable仅在客户端加载地图组件
const Map = loadable(() => import("../components/map"), {
  ssr: false,
  // 可选:配置加载中的占位符
  fallback: <div>地图加载中...</div>
})

const IndexPage = () => (
  <>
    <h1>Hi people</h1>
    <p>
      Welcome to your new Gatsby Maplibre site. Here is a map without extras
    </p>
    <Map />
  </>
)

export default IndexPage

修改完成后重新执行gatsby develop或者gatsby build && gatsby serve即可正常加载地图。


内容的提问来源于stack exchange,提问作者astridx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 15:36:04