Leaflet 在通过 CDN 而不是通过 npm 包使用时呈现 Windy 地图

Leaflet renders Windy map when used via CDN but not via npm pakcage

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

在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>

React 组件:

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);
    });
};

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

libBoot.js:3 Leaflet library is missing

在index.js中:

<script src="https://api.windy.com/assets/map-forecast/libBoot.js"></script>

React 组件:

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);
    });
};

关于在线设置的信息很少,因为 Windy 服从 Leaflet,而 Leaflet 服从 Windy。 Leaflet 快速入门指南或其 github.

中没有任何信息

使用 Leaflet npm package

进行这项工作的正确方法是什么

Leaflet library is missing”错误仅仅是由于这些JS库的加载顺序:

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

Load the Leaflet library at the beginning of your script and after that the Windy API library from URL https://api.windy.com/assets/map-forecast/libBoot.js.

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

最简单的解决方案是,如果可以从本地文件(或 npm 包)而不是从其 URL (/ CDN) 加载 Windy 库:在这种情况下,您只需 import 它在 Leaflet 之后,webpack 将按顺序打包它们。

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

The Leaflet CSS is loaded automatically.

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

因此,如果我们假设我们必须 从 CDN 加载 Windy,但是(无论出于何种原因)我们绝对准备好从 npm(而不是从CDN 也是如此,我们知道它可以很好地且轻松地工作),我们必须找到一种方法以某种方式强制 webpack 加载顺序。

我们现在显然已经脱离了 webpack 的主要用例,因为在这种特定情况下,我们仍然希望捆绑 Leaflet,但是从 URL 和 after[=63 加载 Windy =] Leaflet,但显然在我们的应用程序代码之前。

我看到至少 2 个可能的(显然是 hacky)解决方案:

  • 在我们的应用程序代码中为 Windy 动态生成 <script> 标签;这确保它在 Leaflet 之后加载;但我们必须延迟执行依赖于 Windy 的应用程序部分(例如,通过将其包装在 setTimeout 中,理想情况下检查 Windy 现在是否可用,因为它的加载延迟可能会有所不同)
  • 在我们的代码中使用一些 webpack 插件 import Windy,但 webpack 实际上仍然从 URL 加载它:例如使用具有特定配置的 dynamic-cdn 来指定 URL;不确定仍然有正确的加载顺序是否容易,因为它可能无法识别对 Leaflet 的依赖性。

综上所述,在这种情况下,我们可能仍然质疑是否需要从 npm 加载 Leaflet(因为在 Windy 之前从 CDN 加载它是一件轻而易举的事)。

考虑到您必须为 Windy 执行 any 的转换,我发现您实际上使用的是 TypeScript。因此,您可能希望使用 Leaflet 打字,当您 import 它(并且已经安装 @types/leaflet )时,这几乎自然而然地出现了,给您的印象是必须从 npm 加载它才能使这些打字工作。在这种情况下,我们可以利用类型和实际运行时代码是两个独立事物这一事实。在这种情况下,你仍然可以在你的代码中 import Leaflet 并从它的类型中获益,但是指示 webpack 它不应该被捆绑;您将使它在外部可用,通常是因为您从 CDN 加载。参见 webpack 的 externals 选项。这样,您就可以两全其美:您可以自由地以自己的方式加载 Leaflet,在 Windy 之前明确加载 Leaflet,并且仍然有 Leaflet 类型。