Spaghettify 将任何静态 HTML 站点转换为单页应用程序,具有 AJAX 驱动的导航和 DOM 元素的持久性功能。为此,它实现了一个 DOM 拦截器和一个中间件漏斗处理器,用于捕获链接单击事件,通过 XHR 获取每个请求的文档,并在刷新浏览器文档之前通过一系列中间件函数流式传输响应来消化响应。
这些中间件函数是可插入的 I/O 处理程序,它们遵守单一职责原则并符合完整的步骤管道,可以将其分类为onBeforeComplete
中间件钩子(不会改变当前页面 DOM)和onAfterComplete
中间件钩子(会应用其更改) (因此变异)在注入后直接在当前页面 DOM 上。
整个项目构建在 TypeScript 之上,并实现了多个填充和编码策略,以扩展对旧版浏览器(例如 MSIE11)的支持。
运行此项目的最低要求(无论是在开发还是生产模式下)及其开发脚本是node v12.16.0
和npm v.6.14.15
或更高版本。也许这个项目可以在旧版本的node
和npm
上顺利运行,但我们建议使用最新的 LTS 版本。
该项目依赖 BabelJS 和 Webpack 在开发模式下编译代码,运行构建服务演示站点文件并处理代码优化。
为了您的方便,与BabelJS
和Webpack
所有交互都已抽象在自定义 npm 脚本中。
作为生成开发环境或生产构建的第一步,请运行yarn
或npm install
来提取该项目所需的所有依赖项。
请从终端窗口执行yarn build
或npm run build
。
项目捆绑器将浏览整个应用程序树,并将 JavaScript 工件构建到/dist
文件夹中,捆绑为spaghettify.js
。为了您的方便,其他有用的捆绑包也将保存在那里。
我可以从 npm 注册表获取 Spaghettify 吗?在撰写本文时,项目的首要任务是进一步提高测试覆盖率,并通过扩展对用户提供的中间件挂钩的支持来扩展 API 功能。目前,Spaghettify 旨在作为浏览器依赖项使用,但将其作为 NPM 包分发已在路线图中。请稍后回来查看更新。
您可以通过方便的 API 来实例化 Spaghettify 并与之交互,该 API 提供全局切换、路由拦截器、排除和状态持久性属性标志,以及最后但并非最不重要的加载进度指示器和处理程序。
成功编译 Spaghettify 后,您可以将其导入并实例化到您的应用程序中,如下所示:
< script type =" text/javascript " src =" /dist/spaghettify.js " > </ script >
< script type =" text/javascript " >
new Spaghettify ( {
enabled : true ,
routes : [ '*.html' , 'content/*' ] ,
excludeByAttr : 'no-spa' ,
loadProgress : true ,
persistAttr : 'data-persist' ,
} ) ;
</ script >
正如您所看到的,Spaghettify 可以在实例化时获取配置对象。请注意,所有字段都是可选的,甚至整个配置对象本身也是可选的。如果未提供,Spaghettify 将使用下表中所述的默认选项进行实例化。
Spaghettify 配置设置对象可概括如下:
场地 | 类型 | 默认 | 描述 |
---|---|---|---|
enabled | Boolean | true | 在实例化时启用或禁用 Spaghettify |
routes | String[] | ['*'] | 定义通过 Spaghettify 拦截和服务的路由模式。支持全局令牌。 |
excludeByAttr | String | undefined | 定义排除数据属性标记(带或不带data- 前缀)。 Spaghettify 将绕过用此属性修饰的链接 |
loadProgress | Boolean Function | false | 是否启用内置进度条。它还可以采用一个函数处理程序,该处理程序将在加载时接收百分比进度整数。 |
persistAttr | String | undefined | 定义 UI 状态持久性标志数据属性(带或不带data- 前缀)。用此属性装饰的元素将在页面导航中保留其状态。 |
请注意,所有配置选项(以及选项有效负载本身)都是可选的,如果未明确声明,则将采用默认值。
Spaghettify 通过在内部将事件处理程序绑定到符合条件的链接来与当前文档进行交互。为了防止内存泄漏,或者如果您想停止 Spaghettify 直到它再次恢复,您将需要按如下方式销毁它:
< script type =" text/javascript " >
// First, we instantiate Spaghettify
const spa = new Spaghettify ( ) ;
// Then we dispose it after use
spa . destroy ( ) ;
</ script >
Spaghettify 将所有链接配置为要拦截的对象。内部事件管理器机制将通过针对routes
glob 令牌测试链接 href 值来评估链接是否有资格被视为 AJAX 请求。
但是,我们可以通过使用属性值(无论是否带有data-
前缀)配置excludeByAttr
选项来预先绕过此步骤。
尽管如此,出于语义考虑,Spaghettify 将仅考虑配置有完整属性的链接元素。
< script type =" text/javascript " >
new Spaghettify ( {
excludeByAttr : 'skip-me' ,
} ) ;
</ script >
<!-- Spaghettify will disregard the following link -->
< a href =" foo.html " data-skip-me > Skip this link </ a >
配置的属性可以填充任何值或根本不填充。 Spaghettify 无论如何都会忽略这个值。
正如我们已经看到的, loadProgress
配置选项可以采用Boolean
原始值或函数处理程序。
< script type =" text/javascript " >
new Spaghettify ( {
loadProgress : true ,
} ) ;
</ script >
如果未显式配置或设置为false
,则不会显示进度条指示器。如果设置为true
,Spaghettify 将在视口顶部显示一个动画的红色进度条指示器。进度条显示实际下载进度。
然而,消费者可能希望实现自己的视觉解决方案来呈现下载进度信息。 Spaghettify 通过提供一个加载进度处理程序来解决这些问题,该处理程序在其签名中需要一个整数值参数,当通过 HXR 请求和下载页面时,该参数将采用0
到100
之间的值。
< script type =" text/javascript " >
new Spaghettify ( {
loadProgress : function onLoad ( progress ) {
console . log ( progress ) ; // Will log values from 0 to 100
} ,
} ) ;
</ script >
Spaghettify 实现了一个实验性 API,用于在页面导航中保留选定的、带注释的 DOM 节点的状态。为此,您只需在persistAttr
选项中配置一个值标记,然后使用每个具有唯一值的等效data-
属性来注释那些您希望其状态持久化的 DOM 元素:
< script type =" text/javascript " >
new Spaghettify ( {
persistAttr : 'persist-id' ,
} ) ;
</ script >
< input type =" text " data-persist-id =" my-input " />
您可以显式地为值添加data-
前缀,也可以不添加前缀,但 Spaghettify 将要求您使用完整的数据属性语法来注释要持久保存的 DOM 元素。
请注意:属性值应该是唯一的。如果多个不同类型的元素配置了相同的属性值,Spaghettify 将抛出异常。
值得强调的是,持久性将应用于完整的 DOM Node
基础上,因此它将不仅包含元素的内部 HTML,还包含输入控件的本机触摸状态。所有这一切都与外部 HTML 的变化无关。
您可以通过在控制台中运行yarn dev
或npm run dev
来生成开发环境。
系统将生成所有工件并从 http://localhost:3000(或您选择的任何其他端口,如果您将--port=PORT
参数附加到dev
命令,其中PORT
是所需的端口)处于监视模式,因此应用程序将在源代码发生更改时重新编译。
沙盒站点是一个小型、超级简单的 Web 应用程序,可作为在实时环境中调试 Spaghettify 的游乐场和测试场所。它具有相当简单的样式,通过一组不同的分层页面描述以下关键功能:
index.html
包含一个用于演示目的的 Spaghettify 内联实例。所有其他文档都将此类实例实现为导入脚本。您无需在每个文档上导入 Spaghettify,只需在条目上导入即可。但是,出于演示目的,这允许在重新加载浏览器窗口后从任何文档启动 Spaghettify。在真实的生产场景中,Spaghettify 可以(并且应该)在入口位置仅导入和实例化一次。/sandbox
根级别和子/sandbox/content
子文件夹之间,因此贡献者可以在必要时使用指向子文件夹的链接选择器。/sandbox/content
中的页面具有内联或导入的自定义 JavaScript,Spaghettify 将在需要时消化、重新注入和执行。ESLint 目前已在 Spaghettify 代码库中启用,并且将在构建项目时触发 linting 审核。您可以将 IDE 配置为在引入更改时自动提供 linting 评估。此外,您可以通过在终端控制台中运行npm run lint
或yarn lint
随时触发代码 linting。
您可以在代码库中引入测试,或者通过在终端控制台中运行npm test
或yarn test
来执行现有测试。代码覆盖率数据被收集并存储在/coverage/lcov-report
中格式方便的文档中。对于屏幕覆盖率报告,请将--coverage
参数附加到test
命令中。
您还可以在 Coveralls 上在线查看全面的测试覆盖率报告。
版权所有 2021 巴勃罗·迪尔曼
特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人不受限制地使用本软件,包括但不限于使用、复制、修改、合并的权利、发布、分发、再许可和/或销售软件的副本,并允许向其提供软件的人员这样做,但须满足以下条件:
上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
本软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有者均不对因本软件或本软件的使用或其他交易而引起的或与之相关的任何索赔、损害或其他责任负责,无论是合同、侵权还是其他行为。软件。