首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >服务器端呈现的Next.js动态导入关闭,无法在生产构建中工作。

服务器端呈现的Next.js动态导入关闭,无法在生产构建中工作。
EN

Stack Overflow用户
提问于 2022-05-05 21:44:39
回答 1查看 3.8K关注 0票数 3

我目前正在建立一个使用传单包的网站。但是,这个包需要窗口对象。这就是为什么我要导入一个用传单制作的组件,作为关闭ssr的动态组件。就像这样:

代码语言:javascript
复制
import dynamic from "next/dynamic";
   const MapWithNoSSR = dynamic(() => import("../../map"), {
             ssr: false
 });
 
export default function faqOnly(props){
 ...
 return (<> <MapWithNoSSR /></>)
 }

Map组件如下所示:

代码语言:javascript
复制
    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;

当我运行npm run build时,我会得到这个错误

代码语言:javascript
复制
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'
}

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

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

EN

回答 1

Stack Overflow用户

发布于 2022-05-06 22:39:10

也许您根本不需要next/dynamic,只需在useEffect函数体中使用简单js动态导入即可。

(useEffect只在客户端上运行)

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

代码语言:javascript
复制
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";

function Map(props) {
  useEffect(async () => {
    const L = await import("leaflet")
    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;

已更新

好吧,所以,尝试移动所有需要useEffect钩子窗口的js有点麻烦。只导入整个组件客户端就更容易了。在我看来,您的示例代码看起来不错--除了您再次在地图文件中动态导入传单之外:

page.jsx

代码语言:javascript
复制
import dynamic from "next/dynamic";
const MapWithNoSSR = dynamic(() =>
  import("../../map"), { ssr: false });
 
export default function faqOnly(props){
  ...
  return <MapWithNoSSR />
}

map.jsx

代码语言:javascript
复制
import React, { useEffect, useState, useRef } from "react";
import { OpenStreetMapProvider } from 'leaflet-geosearch';
import L from 'leaflet'
import "leaflet/dist/leaflet.css";
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";

function Map(props) {
  useEffect(async () => {
    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;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72133970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档