通过 CDN 使用但不通过 npm pakcage 使用时,Leaflet 渲染 Windy 地图

Mr.*_*bot 5 javascript leaflet reactjs

我正在通过 CDN 在 React 中使用带有Windy 的Leaflet,效果很好:

在 index.js 中:

<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
<script src="https://api.windy.com/assets/map-forecast/libBoot.js"></script>
Run Code Online (Sandbox Code Playgroud)

反应组件:

export const renderMap = (): void => {
    const options = {
        key: 'xyz',
        lat: 41.3,
        lon: 2.1,
        zoom: 10,
    };
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (window as any).windyInit(options, (windyAPI: any) => {
        const { map } = windyAPI;
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (window as any).L.popup()
            .setLatLng([41.3, 2.1])
            .setContent(':)')
            .openOn(map);
    });
};
Run Code Online (Sandbox Code Playgroud)

但是我希望能够使用传单 npm 包,而不是 CDN。当我导入包时,它被定义但 Windy 抛出错误:

libBoot.js:3 Leaflet 库丢失

在 index.js 中:

<script src="https://api.windy.com/assets/map-forecast/libBoot.js"></script>
Run Code Online (Sandbox Code Playgroud)

反应组件:

import L from 'leaflet';

export const renderMap = (): void => {
    console.log('L', L); // defined - object is present
    const options = {
        key: 'xyz',
        lat: 41.3,
        lon: 2.1,
        zoom: 10,
    };
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (window as any).windyInit(options, (windyAPI: any) => {
        const { map } = windyAPI;
        L.popup()
            .setLatLng([41.3, 2.1])
            .setContent(':)')
            .openOn(map);
    });
};
Run Code Online (Sandbox Code Playgroud)

关于在线设置的信息很少,因为 Windy 遵循 Leaflet,而 Leaflet 遵循 Windy。Leaflet 快速入门指南或他们的 github 中没有信息。

使用Leaflet npm 包进行这项工作的正确方法是什么

ghy*_*ybs 1

Leaflet 库丢失”错误仅仅是由于这些 JS 库的加载顺序造成的:

https://github.com/windycom/API/tree/master/hello-world#hello-world

在脚本开头加载 Leaflet 库,然后从 URL 加载 Windy API 库https://api.windy.com/assets/map-forecast/libBoot.js

  • 当您自己在 HTML 页面中明确编写<script>标签(通过 CDN 加载它们)时,您正确地首先加载 Leaflet,然后加载 Windy
  • 但是当你使用importLeaflet 时,webpack(使用 React 时的默认构建引擎)将其与你的应用程序代码捆绑在一起,并且默认情况下它会<script>在 HTML 页面的最后插入标签,因此使其<body>Windy 之后加载(然后抛出错误消息)
  • 当您重新引入<script>标签以从文件夹加载Leaflet时node_modules,我猜您首先将其放回去(即在Windy的标签之前);但是,这仅在开发中有效,因为该node_modules文件夹在生产中不可用。

对你来说最简单的解决方案是,如果 Windy 库可以从本地文件(或 npm 包)而不是从它的 URL(/ CDN)加载:在这种情况下,你只需将import它放在 Leaflet 之后,webpack 就会将它们捆绑在一起那个订单。

然而,Windy 很可能会根据其位置自行执行一些魔法,例如加载 CSS:

Leaflet CSS 会自动加载。

虽然可以解决 CSS 的这种行为,但它也可能对其他东西(例如访问其数据和图层)产生一些魔力。

因此,如果我们假设我们必须从 CDN 加载 Windy,但是(无论出于何种原因)我们绝对准备好仍然会遇到从 npm 加载 Leaflet 的麻烦(而不是从 CDN 加载,我们知道 CDN 工作得很好而且很容易),我们必须找到一种方法以某种方式强制 webpack 加载顺序。

我们现在显然已经超出了 webpack 主要用例,因为在这种特定情况下,我们仍然希望捆绑 Leaflet,但从 URL 加载 Windy,在Leaflet之后,但显然在我们的应用程序代码之前。

我看到至少有两种可能的(显然是 hacky 的)解决方案:

  • 在我们的应用程序代码中动态生成<script>W​​indy 标签;这确保它在 Leaflet 之后加载;但我们必须延迟应用程序中依赖 Windy 的部分的执行(例如,通过将其包装在 中setTimeout,最好检查 Windy 现在是否可用,因为它的加载延迟可能会有所不同)
  • 在我们的代码中使用importWindy 的一些 webpack 插件,但 webpack 实际上仍然从 URL 加载它:例如使用具有特定配置的动态 CDN来指定 URL;不确定是否仍能轻松保持正确的加载顺序,因为它可能无法识别对 Leaflet 的依赖关系。

话虽如此,我们仍然可能会质疑在这种情况下是否需要从 npm 加载 Leaflet(因为在 Windy 之前从 CDN 加载它是轻而易举的事情)。

鉴于您必须为 Windy 进行强制转换any,我发现您实际上使用了 TypeScript。因此,您可能希望使用 Leaflet 类型,当您使用import它(并且已经安装@types/leaflet)时,这几乎是自然而然的,给您的印象是必须从 npm 加载它才能使这些类型起作用。在这种情况下,我们可以利用类型和实际运行时代码是两个独立的东西这一事实。在这种情况下,您仍然可以import在代码中使用 Leaflet 并从其类型中受益,但指示 webpack 不应将其捆绑;您将使其在外部可用,通常是因为您从 CDN 加载。请参阅webpack 的externals选项。这样,您就可以两全其美:您可以按照自己的方式自由地加载 Leaflet,这里明确地先于 Windy,并且仍然可以进行 Leaflet 类型。