制作传单插件作为导入或直接从 html header
Making a leaflet plugin available as an import or directly from html header
我构建了一个 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文件的header中使用时,这显然是行不通的。 (当然,任何试图这样做的人都必须在我的插件之前的某个地方的 header 中包含 leaflet.geometryutil 脚本——这在我的 github 自述文件中有清楚的解释。)
我目前的策略是只有 2 github 个分支 - one with the import statement, and one without。但我试图了解我可以做些什么来合并这两个分支,并拥有一段适用于两种情况的代码。到目前为止,我的两个想法是:
使用动态导入
如果 geometryutil
模块不在 Leaflet 命名空间中,则只导入它:
if(!L.GeometryUtil){
import('leaflet-geometryutil')
.then( GeometryUtil => {
console.log('all good')
})
.catch( err => throw(err) )
}
L.Polyline.include({ ..plugin code... })
这不起作用,因为 import
承诺在我的 L.Polyline.include
代码运行后才会 return,所以在我的代码中使用 GeometryUtil
returns a GeometryUtil
未定义。这适用于 HTML header 场景,作者在我的插件标签之前有一个 GeometryUtil
脚本标签,因为 if
语句 return false 和导入承诺未执行。
是否有另一种方法来编写动态导入语句,以便插件代码仅在导入承诺完成后运行,然后正确导入到插件所在的另一个模块中用户正在创作?
使用像 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 中获得,它会自动更改传单 object L
如预期?
有没有我没有想到的第三种选择?
感谢阅读。
我为我的网站做了以下...
在结束 'body' 标记之后包括以下行
<?php include_once("files_java/_java_loader.php");?>
_java_loader.php 文件是这样的...
<?php
$script_Array = explode("/", $_SERVER['SCRIPT_FILENAME']);
$script_Name = $script_Array[count($script_Array)-1];
// Load module specific scripts for each module
switch ($script_Name) {
case 'maps.php':
case 'map_all.php':
case 'neighbors.php':
case 'view_large_map.php':
?><script type="text/javascript" src="<?php echo SERVER_PATH; ?>files_java/mapper.js"></script><?php echo PHP_EOL;
?><script type="text/javascript" src="<?php echo SERVER_PATH; ?>files_java/initMaps.js"></script><?php echo PHP_EOL;
?><script type="text/javascript" src="<?php echo SERVER_PATH; ?>files_java/downloadXML.js"></script><?php echo PHP_EOL;
?><script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAXPvUkWaeVfdwQjtlBZwlZND0-0bcYpZs" defer></script><?php echo PHP_EOL;
break;
}?>
因此,您可以为特定模块设置特定文件以加载。在 $script_array 语句上方包括所有模块所需的所有 javascript 链接。
我也对 CSS 负载使用类似的结构。
杰达威尔逊
这是前端库的一个常见难题。
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
中引用的导入依赖项和公共文件的内容。顺便说一句,您甚至可以在该文件中导入 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.
然后你有一个单一的公共文件来维护,不需要使用单独的分支,一切都发布到 npm,即免费的 CDN(如 unpkg、cdnjs 和 jsDelivr)将能够直接为你的公共文件提供服务,准备 HTML 脚本消费!
最后要担心的是您的依赖项:在节点样式导入的情况下,这很好,因为您的包将其列为依赖项,因此它将与您的包一起安装,并且您可以在索引中正确导入它文件。
但是对于 HTML 脚本,你仍然需要导入依赖项 "manually",即你仍然需要告诉你的库的用户在他们的 HTML 脚本中包含依赖项.
这可以通过将依赖项与您的插件捆绑在一起来避免,通常是现在引入构建引擎。在这种情况下,通常的做法是构建多个版本: 1 已经捆绑了所有依赖项,因此您的库用户只需要 1 个导入; 1 只有你的代码,让你的库用户管理依赖项的导入(通常这样他们就可以控制版本,也可以直接使用它们而无需重复代码等)。为此,上面的索引文件也用作构建入口点。然后你必须指定不包含在包中的内容:排除 Leaflet,可能还有 Leaflet-geometryUtil。
我构建了一个 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文件的header中使用时,这显然是行不通的。 (当然,任何试图这样做的人都必须在我的插件之前的某个地方的 header 中包含 leaflet.geometryutil 脚本——这在我的 github 自述文件中有清楚的解释。)
我目前的策略是只有 2 github 个分支 - one with the import statement, and one without。但我试图了解我可以做些什么来合并这两个分支,并拥有一段适用于两种情况的代码。到目前为止,我的两个想法是:
使用动态导入
如果 geometryutil
模块不在 Leaflet 命名空间中,则只导入它:
if(!L.GeometryUtil){
import('leaflet-geometryutil')
.then( GeometryUtil => {
console.log('all good')
})
.catch( err => throw(err) )
}
L.Polyline.include({ ..plugin code... })
这不起作用,因为 import
承诺在我的 L.Polyline.include
代码运行后才会 return,所以在我的代码中使用 GeometryUtil
returns a GeometryUtil
未定义。这适用于 HTML header 场景,作者在我的插件标签之前有一个 GeometryUtil
脚本标签,因为 if
语句 return false 和导入承诺未执行。
是否有另一种方法来编写动态导入语句,以便插件代码仅在导入承诺完成后运行,然后正确导入到插件所在的另一个模块中用户正在创作?
使用像 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 中获得,它会自动更改传单 object L
如预期?
有没有我没有想到的第三种选择?
感谢阅读。
我为我的网站做了以下...
在结束 'body' 标记之后包括以下行
<?php include_once("files_java/_java_loader.php");?>
_java_loader.php 文件是这样的...
<?php
$script_Array = explode("/", $_SERVER['SCRIPT_FILENAME']);
$script_Name = $script_Array[count($script_Array)-1];
// Load module specific scripts for each module
switch ($script_Name) {
case 'maps.php':
case 'map_all.php':
case 'neighbors.php':
case 'view_large_map.php':
?><script type="text/javascript" src="<?php echo SERVER_PATH; ?>files_java/mapper.js"></script><?php echo PHP_EOL;
?><script type="text/javascript" src="<?php echo SERVER_PATH; ?>files_java/initMaps.js"></script><?php echo PHP_EOL;
?><script type="text/javascript" src="<?php echo SERVER_PATH; ?>files_java/downloadXML.js"></script><?php echo PHP_EOL;
?><script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAXPvUkWaeVfdwQjtlBZwlZND0-0bcYpZs" defer></script><?php echo PHP_EOL;
break;
}?>
因此,您可以为特定模块设置特定文件以加载。在 $script_array 语句上方包括所有模块所需的所有 javascript 链接。
我也对 CSS 负载使用类似的结构。
杰达威尔逊
这是前端库的一个常见难题。
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
中引用的导入依赖项和公共文件的内容。顺便说一句,您甚至可以在该文件中导入 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.
然后你有一个单一的公共文件来维护,不需要使用单独的分支,一切都发布到 npm,即免费的 CDN(如 unpkg、cdnjs 和 jsDelivr)将能够直接为你的公共文件提供服务,准备 HTML 脚本消费!
最后要担心的是您的依赖项:在节点样式导入的情况下,这很好,因为您的包将其列为依赖项,因此它将与您的包一起安装,并且您可以在索引中正确导入它文件。
但是对于 HTML 脚本,你仍然需要导入依赖项 "manually",即你仍然需要告诉你的库的用户在他们的 HTML 脚本中包含依赖项.
这可以通过将依赖项与您的插件捆绑在一起来避免,通常是现在引入构建引擎。在这种情况下,通常的做法是构建多个版本: 1 已经捆绑了所有依赖项,因此您的库用户只需要 1 个导入; 1 只有你的代码,让你的库用户管理依赖项的导入(通常这样他们就可以控制版本,也可以直接使用它们而无需重复代码等)。为此,上面的索引文件也用作构建入口点。然后你必须指定不包含在包中的内容:排除 Leaflet,可能还有 Leaflet-geometryUtil。