javascript - 使传单插件可作为导入或直接从 html header 使用

标签 javascript webpack import leaflet dynamic-import

我构建了一个 plugin for leaflet ( npm package ),我希望它可以作为 ES6 导入或作为 HTML header 中的脚本使用。

期望的行为

例如,我希望这两个都是可能的:

// As an npm package
import 'leaflet-arrowheads'
// From your HTML header
<script type="text/javascript" src="./leaflet.arrowheads.js"></sript>

我的插件有一个依赖项,leaflet geometryutil .所以代码看起来像这样:

import 'leaflet.geometryutil'

L.Polyline.include({
   ...my plugin code here
})

L.LayerGroup.include({
   ... a bit more code here
})

这在使用 ES6 模块时有效,其中 leaflet.geometryutil 作为我的包的依赖项安装。但是当用在 HTML 文件的头部时,这显然是行不通的。 (当然,任何试图这样做的人都必须在我的插件之前的某个地方在他们的标题中有 leaflet.geometryutil 脚本 - 这在我的 github 自述文件中有清楚的解释。)

我目前的策略是只拥有 2 个 github 分支 - one with the import statement , 和 one without .但我试图了解我可以做些什么来合并这两个分支,并拥有一段适用于两种情况的代码。到目前为止,我的 2 个想法是:

使用动态导入

如果 geometryutil 模块不在 Leaflet 命名空间中,则只导入它:

if(!L.GeometryUtil){
   import('leaflet-geometryutil')
      .then( GeometryUtil => {
         console.log('all good')
      })
      .catch( err => throw(err) )
}

L.Polyline.include({ ..plugin code... })

这是行不通的,因为 import promise 在我的 L.Polyline.include 代码运行后才会返回,所以 GeometryUtil< 的任何使用 在我的代码中返回一个未定义的 GeometryUtil。这适用于 HTML header 场景,其中作者在我的插件标签之前有一个 GeometryUtil 脚本标签,因为 if 语句返回 false 并且导入 promise 未执行。

是否有另一种方法可以编写动态导入语句,以便插件代码仅在导入 promise 完成后运行,然后正确导入到插件用户正在编写的另一个模块中?

使用像 webpack 这样的构建工具

看来我可以用 webpack 来实现我的目标。基于关于 authoring libraries 的 webpack 文档,我可以做类似的事情

output: {
    path: './dist',
    filename: 'leaflet.arrowheads.js',
    library: 'arrowheads',
    libraryTarget:'umd'
}

但我不太确定如何准确配置输出。文档解释说这将公开一个全局变量 arrowheads,但这不是我们所需要的。我正在构建的插件并没有真正公开一个新变量,而是添加到现有的传单库中。

我如何配置 webpack.config 来构建插件,以便它 1: 可作为导入使用(它本身导入其依赖项 leaflet.geometryutil),还有 2: 可作为 HTML header 中的脚本标记使用,它会按预期自动更改传单对象 L

还有我没有想到的第三种选择吗?

感谢阅读。

最佳答案

这是前端库的一个常见难题。

webpack确实可以提供一些解决方案,Rollup也是如此(这是Leaflet使用的构建引擎)。

至于动态导入,当你构建一个应用程序并由你的构建引擎管理动态导入时它工作正常,但我不会在编写库时依赖它,因为你不知道环境/构建是否消费者项目使用的引擎将支持它。

在您的情况下,您甚至可以省去使用构建引擎和尝试正确配置它的麻烦。

首先,您正确地注意到(并遵循了 Leaflet 约定)大多数 Leaflet 插件不会将任何内容导出到全局范围或导入器,但会产生在 Leaflet 的 L命名空间。因此,在使用构建引擎导入程序时,我们只需要做:

import "leaflet";
import "leaflet-arrowheads"; // nothing in curly braces

因此您的库甚至不需要导出任何东西(即您可以在 L.Polyline.include 之前去掉 export default)。

您现在可能开始看到一个可能的解决方案:为导入和 HTML 脚本创建一个通用文件,只包含您的 L.Polyline.include 代码;有一个单独的导入条目文件(即您在 package.json/main 中引用的内容,它导入您的依赖项和您的公共(public)文件。顺便说一句,您甚至可以在该文件中导入 Leaflet!

package.json

{
   "main": "index.js" // npm convention, not even needed if your file is named "index.js"
}

index.js

import "leaflet";
import "leaflet.geometryutil";
import "./src/leaflet-arrowheads.js"; // common file

src/leaflet-arrowheads.js

L.Polyline.include() // etc.

然后你有一个单一的公共(public)文件来维护,不需要使用单独的分支,一切都发布到 npm,即免费的 CDN(如 unpkg、cdnjs 和 jsDelivr)将能够直接提供你的公共(public)文件,准备好HTML 脚本消费!

最后要担心的是您的依赖项:在节点样式导入的情况下,这很好,因为您的包将其列为依赖项,因此它将与您的包一起安装,并且您将其正确地导入到索引文件中。

但对于 HTML 脚本,您仍然需要“手动”导入依赖项,即您仍然需要告诉库的用户在他们的 HTML 脚本中包含依赖项。

这可以通过将依赖项与您的插件捆绑在一起来避免,通常是现在引入构建引擎。在这种情况下,通常的做法是构建多个版本: 1 已经捆绑了所有依赖项,因此您的库用户只需要 1 个导入; 1 只有你的代码,让你的库用户管理依赖项的导入(通常这样他们就可以控制版本,也可以直接使用它们而无需重复代码等)。为此,上面的索引文件也用作构建入口点。然后你必须指定不包含在包中的内容:排除 Leaflet,可能还有 Leaflet-geometryUtil。

关于javascript - 使传单插件可作为导入或直接从 html header 使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60105355/

相关文章:

javascript - Underscore.js _.template 导致 Chrome 扩展出错

javascript - Chunk.entrypoints : Use Chunks. groupsIterable 并通过 instanceof Entrypoint 过滤

python - Python 2.6 中的动态类加载 : RuntimeWarning: Parent module 'plugins' not found while handling absolute import

css - 如何让我的 sass 登陆页面在 codepen 上运行?

mysql - mongoDB是否有像mysql一样的机制,可以简单地将.sql文件导入数据库?

javascript - 注入(inject) Angular 服务时运行相同的代码

javascript - 将 Array.prototype.concat.apply([], [x]) 重构为 [].concat(x) 会引发错误

node.js - webpack错误: custom keyword definition is invalid: data/errors should be boolean

javascript - Yii2 在 yii2-formwizard 的表格步骤中使用 Select2

javascript - 在 Webpack 2 中,如何将日期(或任何其他变量)添加到横幅输出中?