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

Next.js 15 + Turbo生产环境__webpack_require__未定义问题求助

问题解决:Next.js 15 + Turbo生产环境__webpack_require__/global未定义错误

问题分析

你的问题核心在于HERE Maps JavaScript库与Next.js 15生产构建的Webpack优化逻辑冲突:

  • 开发模式下Webpack保留了__webpack_require__这类内部全局变量,库能正常访问;但生产构建会剔除这类非标准变量,导致库调用时抛出未定义错误。
  • 手动设置global: false会直接移除全局global对象映射,而HERE Maps库依赖该对象(在浏览器环境实际对应window),因此触发新的global未定义错误。

可行解决方案

方案1:改用CDN加载HERE Maps(推荐)

绕过Webpack打包冲突,直接在客户端通过CDN加载库文件,完全避免模块打包带来的变量问题:

修改地图组件代码:

import React, { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';

interface MapProps {
    onMapReady?: (map: any, platform: any) => void;
}

const Map = forwardRef<HTMLDivElement, MapProps>(({ onMapReady }, ref) => {
    const mapRef = useRef<HTMLDivElement | null>(null);
    const map = useRef<any | null>(null);
    const platform = useRef<any | null>(null);
    const isLoaded = useRef(false);

    useImperativeHandle(ref, () => mapRef.current as any);

    useEffect(() => {
        if (isLoaded.current || !mapRef.current) return;

        // 加载核心地图库
        const loadCore = () => {
            const script = document.createElement('script');
            script.src = `https://js.api.here.com/v3/3.1/mapsjs-core.js`;
            script.async = true;
            script.onload = loadMapEvents;
            document.body.appendChild(script);
            return () => document.body.removeChild(script);
        };

        // 加载地图交互模块
        const loadMapEvents = () => {
            const script = document.createElement('script');
            script.src = `https://js.api.here.com/v3/3.1/mapsjs-mapevents.js`;
            script.async = true;
            script.onload = initMap;
            document.body.appendChild(script);
            return () => document.body.removeChild(script);
        };

        // 初始化地图
        const initMap = () => {
            isLoaded.current = true;
            const H = window.H;
            
            platform.current = new H.service.Platform({ 
                apikey: process.env.NEXT_PUBLIC_HERE_API_KEY! 
            });
            const defaultLayers = platform.current.createDefaultLayers();
            const newMap = new H.Map(
                mapRef.current!,
                defaultLayers.vector.normal.map,
                {
                    zoom: 14,
                    center: { lat: 64.144, lng: -21.94 },
                }
            );

            new H.mapevents.Behavior(new H.mapevents.MapEvents(newMap));
            map.current = newMap;

            onMapReady?.(newMap, platform.current);
        };

        const cleanupCore = loadCore();
        
        return () => {
            cleanupCore();
            map.current?.dispose();
        };
    }, [onMapReady]);

    return (
        <div
            style={{ width: '100%', height: '100%' }}
            className="w-full h-full"
            ref={mapRef}
        />
    );
});

Map.displayName = "Map";
export default Map;

动态导入组件的代码保持不变即可。

方案2:配置Webpack提供全局变量映射

通过修改next.config.js,让Webpack在生产构建时为HERE Maps库提供所需的全局变量:

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    // 仅在客户端构建时处理全局变量映射
    if (!isServer) {
      // 将global对象映射到window(浏览器环境的全局对象)
      config.plugins.push(
        new config.webpack.DefinePlugin({
          global: 'window',
        })
      );
      // 设置Webpack的全局对象为window,避免内部变量丢失
      config.output.globalObject = 'window';
    }

    return config;
  },
};

export default nextConfig;

这个方案无需修改组件代码,但需要注意:部分HERE Maps版本可能仍存在Webpack特定变量依赖,若此方案无效,优先尝试方案1。

关键注意事项

  • 动态导入的ssr: false配置是正确的,确保地图组件仅在客户端加载,避免服务端渲染时的环境不兼容。
  • 若使用方案1,可根据需求添加更多HERE Maps模块(如mapsjs-ui)的CDN加载逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:33:10