tonysm/importmap-laravel

使用 importmap 管理 Laravel 中的现代 JavaScript,无需转换或打包。

2.3.2 2024-03-13 01:41 UTC

README

Logo Importmap Laravel

Total Downloads Latest Stable Version License

简介

使用 importmap 管理 Laravel 中的现代 JavaScript,无需转换或打包。

灵感

此包受 Importmap Rails 钥石的启发。此 README 的一些部分直接从那里复制并适配到 Laravel 版本。

它是如何工作的?

导入映射 允许您使用与版本/散列文件映射的逻辑名称导入 JavaScript 模块 - 直接从浏览器中导入。因此,您可以使用为 ES 模块 (ESM) 制作的 JavaScript 库来构建现代 JavaScript 应用程序,而无需转换或打包,无需 Webpack、Yarn、npm 或 JavaScript 工具链的任何其他部分。

使用这种方法,您将发送许多小的 JavaScript 文件,而不是一个大的 JavaScript 文件。多亏了 HTTP/2,它在初始传输中不再产生重大性能损失,并且由于更好的缓存动态,在长期运行中提供了实质性的好处。以前,对包含在大包中的任何 JavaScript 文件的任何更改都会使整个包的缓存失效,而现在只需使单个文件的缓存失效。

导入映射在所有主流、现代浏览器中都有原生支持。如果您需要与没有原生支持的旧版浏览器一起工作,您可能想探索使用 可用的模拟器

安装

您可以通过 Composer 安装此包

composer require tonysm/importmap-laravel

此包有一个 install 命令,您可以运行它以替换默认的 Laravel 脚手架为使用 importmap 的脚手架

php artisan importmap:install

接下来,我们需要将以下组件添加到我们的视图或布局文件中

<x-importmap::tags />

在您的 <head> 标签之间添加此内容。 entrypoint 应该是 "main" 文件,通常是 resources/js/app.js 文件,它将被映射到 app 模块(使用模块名称,而不是文件)。

默认情况下,x-importmap::tags 组件假定您的入口点模块是 app,这与 Laravel 默认脚手架中现有的 resources/js/app.js 文件相匹配。您可能想要自定义入口点,这可以通过 entrypoint 属性来完成

<x-importmap::tags entrypoint="admin" />

该包将自动使用 Laravel 的符号链接功能将 resources/js 文件夹映射到您的 public/js 文件夹。安装此包后,您只需运行

php artisan storage:link

如果您正在使用 Laravel Sail,请确保在命令前加上 sail,因为符号链接需要在容器内创建。

符号链接仅在本地环境中注册。对于生产环境,建议运行 importmap:optimize 命令

php artisan importmap:optimize

本功能应扫描您所有已固定的文件/文件夹(不包括URL)并将它们发布到public/dist/js,根据文件内容添加到文件名中的校验和,例如public/dist/js/app-123123.js,然后在public/文件夹中生成一个.importmap-manifest.json文件。该文件将覆盖您的固定项。如果您在开发中意外运行它,请确保删除该文件或简单地运行php artisan importmap:clear,这将删除它。您可能还想将/public/dist添加到您的.gitignore文件中,以及添加*importmap-manifest.json

用法

简而言之,importmap通过向浏览器提供一个映射,告诉它在哪里查找您的JavaScript导入语句。例如,您可以在routes/importmap.php文件中这样固定Alpinejs的依赖项

<?php

use Tonysm\ImportmapLaravel\Facades\Importmap;

// Other pins...
Importmap::pin("alpinejs", to: "/js/vendor/alpinejs.js"); //@3.8.1

然后,在您的JavaScript文件中,您可以安全地这样做

import Alpine from 'alpinejs';

本地文件固定

本地固定应手动添加到routes/importmap.php文件中,如下所示

Importmap::pin("app", to: "/js/app.js");

这意味着app模块将在浏览器中指向/js/app.js。这是浏览器将用于获取文件的URI,而不是文件的路径本身。对本地文件的固定假设有一个相对路径resources/js/来找到它们。

本地目录固定

声明所有本地文件可能会很繁琐,因此您可能希望映射整个文件夹,如下所示

Importmap::pinAllFrom("resources/js/", to: "js/");

当我们生成importmap JSON时,我们将扫描该目录,寻找其中任何.js.jsm文件,并根据它们的相对位置生成正确的importmap。

如果文件夹中有一个index.js文件,我们不会在模块名称中获取index,因此我们可以这样导入它

import libs from 'libs';

而不是

import libs from 'libs/index';

外部依赖项固定

如果您依赖任何外部库,可以使用importmap:pin命令来固定它,如下所示

php artisan importmap:pin alpinejs

它将下载alpinejs库,然后它将向您的routes/importmap.php文件添加以下行

Importmap::pin("alpinejs", to: "/js/vendor/alpinejs.js"); // @3.8.1

pin命令使用jspm.io API解析依赖项(以及我们的依赖项的依赖项),寻找我们可以固定的ESM模块,并将其解析为CDN URL并作为依赖项下载。我们可以通过指定--from标志来控制我们想要使用的CDN

php artisan importmap:pin alpinejs --from=unpkg

这将从unpkg而不是默认的JSPM CDN下载库。

请注意,pin命令将始终解析依赖项(以及我们的依赖项的依赖项)并将所有文件下载到您的resources/js/vendor文件夹中,您应该将其添加到您的版本控制中,并自行将其作为供应商。

Importmap::pin("alpinejs", to: "/js/vendor/alpinejs.js"); // @3.8.1

版本号作为注释添加到您的固定项中,以便您知道导入的哪个版本。不要删除它,因为稍后当您需要升级依赖项时它将非常有用。

模块预加载

为了避免浏览器必须一个接一个地加载文件才能到达最深的导入,我们默认使用modulepreload链接。如果您不希望预加载依赖项,因为它会按需加载以提高效率,请将preload: false附加到固定项中。

Importmap::pinAllFrom("resources/js/", to: "js/", preload: true);
Importmap::pin("alpinejs", to: "https://unpkg.com/alpinejs@3.8.1/dist/module.esm.js", preload: true); // @3.8.1

这将向HTML文档的head标签中添加正确的links标签,如下所示

<link rel="modulepreload" href="https://unpkg.com/alpinejs@3.8.1/dist/module.esm.js">

依赖项维护命令

维护一个健康的依赖项列表可能会很困难。以下是一些有助于您完成此任务的命令。

过时的依赖项

为了保持您的依赖项更新,请确保您不时运行importmap:outdated命令

php artisan importmap:outdated

此命令将扫描您的 routes/importmap.php 文件,查找您当前的版本,然后使用 NPM 注册表 API 查找您正在使用的包的最新版本。它还可以处理使用 importmap:pin 命令的 --download 标志添加的本地服务供应商库。

审计依赖项

如果您想对依赖项进行安全审计以查看您是否使用了已泄露的版本,请定期运行 importmap:audit 命令。更好的做法是将该命令添加到您的 CI 构建中。

php artisan importmap:audit

这将同样扫描您的 routes/importmap.php 文件,查找您的当前版本,然后使用 NPM 注册表 API 查找您的包中的漏洞。它还可以处理使用 importmap:pin 命令的 --download 标志添加的本地服务供应商库。

已知问题

关于 React 的 JSX 和 Vue 的 SFC

您可以使用 importmaps 同时使用 React 和 Vue,但遗憾的是,您将无法使用 JSX 或 SFC 的功能。这是因为这些文件类型需要一个编译/转译步骤,将它们转换为浏览器可以理解的格式。有其他方法可以使用这两个库,但我要说,这些方法在其社区中并不是“常见”的。您可以尝试使用 React with HTM。您也可以使用 Vue 而无需 SFC,唯一的区别是您的模板将位于 Blade 文件中,而不是 SFC 文件中。

进程环境配置

您可能习惯在 JS 文件中这里那里添加几行 process.env.MIX_*。这种方式是 Webpack 在构建时会用构建期间 process.env 的值替换您的调用。由于我们不再有“构建时间”,所以这不会工作。相反,您应该在布局文件中添加 <meta> 标签,以使您希望提供给 JavaScript 文件的内容可用,并使用 document.head.querySelector('meta[name=my-config]').content 而不是依赖于 process.env

考虑使用类似 current.js 的工具,通过全局可用的 Current 对象轻松消费您的 <meta> 配置。

测试

composer test

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

贡献

有关详细信息,请参阅 CONTRIBUTING

安全漏洞

有关报告安全漏洞的详细信息,请参阅 我们的安全策略

致谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件