关闭服务器端渲染的 Next.js 动态导入不适用于生产构建

Mr *_*tar 7 leaflet reactjs server-side-rendering next.js

我目前正在使用传单包构建一个网站。然而这个包需要 window 对象。这就是为什么我将使用 leaflet 制作的组件导入为关闭 ssr 的动态组件。像这样:

import dynamic from "next/dynamic";
   const MapWithNoSSR = dynamic(() => import("../../map"), {
             ssr: false
 });
 
export default function faqOnly(props){
 ...
 return (<> <MapWithNoSSR /></>)
 }
Run Code Online (Sandbox Code Playgroud)

地图组件如下所示:

    import React, { useEffect, useState, useRef } from "react";
import { OpenStreetMapProvider } from 'leaflet-geosearch';
import "leaflet/dist/leaflet.css";
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";
import dynamic from "next/dynamic";

const L = dynamic(() => import("leaflet"), {
      ssr: false,
      suspense: true,
      loading: () => <p>...</p>
    });


function Map(props) {


  useEffect(async () => {
    if(window === undefined) return
    const provider = new OpenStreetMapProvider();
     const results = await provider.search({ query: props.adress });
     if(results.length > 0 == true){
      var map = L.map('map', {
          center: [results[0].y, results[0].x],
          zoom: 18,
          layers: [
              L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png', {
                  attribution: ''
              }),
          ]
      })
      L.marker([results[0].y, results[0].x]).addTo(map)
  }else{
    document.getElementById("map").style.display = "none"
  }
  }, [])


    return <div id="map" style={{ height: "30vh"}}></div>

}

export default Map;
Run Code Online (Sandbox Code Playgroud)

当我运行时出现此错误npm run build

ReferenceError: window is not defined
    at E:\Github\Planer\rl-planer\node_modules\leaflet\dist\leaflet-src.js:230:19
    at E:\Github\Planer\rl-planer\node_modules\leaflet\dist\leaflet-src.js:7:66
    at Object.<anonymous> (E:\Github\Planer\rl-planer\node_modules\leaflet\dist\leaflet-src.js:10:3)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (E:\Github\Planer\rl-planer\node_modules\leaflet-geosearch\dist\geosearch.js:1:7) {
  type: 'ReferenceError'
}
Run Code Online (Sandbox Code Playgroud)

这在开发中工作得很好,但是当我尝试构建项目(下一个构建)时,它会在传单包内抛出“窗口未定义”错误,而我之前在开发中处理它时它没有这样做过模式。

我在这里查看了其他问题,但似乎将动态导入移到组件之外为除了我之外的每个人修复了它。我只是愚蠢还是这里有什么问题?

err*_*sto 1

也许你根本不需要,next/dynamic只需在内部使用简单的 js 动态导入即可useEffect即可。

\n

useEffect仅在客户端运行)

\n

Nextjs 有一个看起来非常相似的示例:https ://nextjs.org/docs/advanced-features/dynamic-import。(第一个带有fuse.js的页面)

\n
import React, { useEffect, useState, useRef } from "react";\nimport { OpenStreetMapProvider } from \'leaflet-geosearch\';\nimport "leaflet/dist/leaflet.css";\nimport \'leaflet/dist/leaflet.css\'\nimport \'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css\'\nimport "leaflet-defaulticon-compatibility";\n\nfunction Map(props) {\n  useEffect(async () => {\n    const L = await import("leaflet")\n    const provider = new OpenStreetMapProvider();\n    const results = await provider.search({ query: props.adress });\n\n    if(results.length > 0 == true) {\n      var map = L.map(\'map\', {\n        center: [results[0].y, results[0].x],\n        zoom: 18,\n        layers: \n          [\n            L.tileLayer(\n              \'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png\',\n              { attribution: \'\'}\n            ),\n          ]\n      })\n      L.marker([results[0].y, results[0].x]).addTo(map)\n    } else {\n      document.getElementById("map").style.display = "none"\n    }\n  }, [])\n\n\n  return <div id="map" style={{ height: "30vh"}}></div>\n}\n\nexport default Map;\n
Run Code Online (Sandbox Code Playgroud)\n

更新

\n

好吧,也许尝试在 useEffect 挂钩中移动需要窗口的所有 js 有点混乱。\n仅导入整个组件客户端会更容易。\n对我来说,除了事实之外,你的示例代码看起来不错 \xe2\x80\x93您在地图文件中再次动态导入传单:

\n

页面.jsx

\n
import dynamic from "next/dynamic";\nconst MapWithNoSSR = dynamic(() =>\n  import("../../map"), { ssr: false });\n \nexport default function faqOnly(props){\n  ...\n  return <MapWithNoSSR />\n}\n
Run Code Online (Sandbox Code Playgroud)\n

地图.jsx

\n
import React, { useEffect, useState, useRef } from "react";\nimport { OpenStreetMapProvider } from \'leaflet-geosearch\';\nimport L from \'leaflet\'\nimport "leaflet/dist/leaflet.css";\nimport \'leaflet/dist/leaflet.css\'\nimport \'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css\'\nimport "leaflet-defaulticon-compatibility";\n\nfunction Map(props) {\n  useEffect(async () => {\n    const provider = new OpenStreetMapProvider();\n    const results = await provider.search({ query: props.adress });\n\n    if(results.length > 0 == true) {\n      var map = L.map(\'map\', {\n        center: [results[0].y, results[0].x],\n        zoom: 18,\n        layers: \n          [\n            L.tileLayer(\n              \'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png\',\n              { attribution: \'\'}\n            ),\n          ]\n      })\n      L.marker([results[0].y, results[0].x]).addTo(map)\n    } else {\n      document.getElementById("map").style.display = "none"\n    }\n  }, [])\n\n\n  return <div id="map" style={{ height: "30vh"}}></div>\n}\n\nexport default Map;\n
Run Code Online (Sandbox Code Playgroud)\n


归档时间:

查看次数:

9940 次

最近记录:

2 年,7 月 前