您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

你的博客用不着什么 JavaScript 框架

时间:2020-07-29 11:00:17  来源:  作者:

今年年初,我终于决定将自己的网站从基于 php 的 CMS 移植到基于 JAVAScript 的静态网站生成器(SSG)了。原因如下:

  1. 虽然一开始我是“全栈”开发人员,但现在我只负责前端工作:如果我需要编写自定义功能,那么能用 JavaScript 编写的代码我就不想用 PHP 来写。
  2. 我不需要抽象层或 CMS 的复杂性——我最喜欢用 markdown 文件编写内容,并且希望永远不要再碰 MySQL 数据库或所见即所得编辑器。
  3. 我想提高网站的性能:静态 html 文件在 99% 的时候都比动态页面更快。
  4. 最后还有成本优势:LAMP stack 服务器得按月付费;Netlify 的免费套餐(每月构建 300 分钟)应该可以轻松覆盖零成本个人博客的需求。

当我决定使用静态站点生成器和 JavaScript(排除了 Jekyll 和 Hugo)后,就只剩下两个差别颇大的选项了。

“我听说 Gatsby 很好用”

根据官方网站的说法,“Gatsby 是一个基于 React 的免费开源框架,可帮助开发人员构建速度飞快的网站和应用”。它有一个由 GraphQL 支持的数据层,并将所有内容输出到静态文件,使你可以在几乎任何地方托管它。

当我第一次听说我可以编写 React 并使用这个很酷的 GraphQL 新玩意儿,同时还能输出不需要 JavaScript 的静态页面时,我很想尝试它一下。我是这么想的:“这听起来像是渐进增强,但用不着什么投入”。不幸的是,就像大多数听起来过于美好的事情一样,经过一些调查我发现它就是个坑。用户首次访问 Gatsby 网站时会发生这些事情:

  1. 用户请求一个页面。
  2. 服务器将静态生成的 HTML 文档发送到用户的浏览器,然后浏览器开始渲染页面。
  3. HTML 文档到达后,JavaScript 包(包括 React 库和渲染页面所需的其他 JavaScript)开始在后台下载、解析和编译。
  4. JavaScript 已准备就绪,可以运行——整个 DOM 通过 React 组件“被水化”(hydrated)。

这里就有些不对劲——Gatsby 需要你以 React 组件的形式再加载一次页面;在完成多出来的这一步之前,所有需要 JavaScript 的元素(例如按钮、菜单、自定义输入)实际上都不能交互。

哪怕你的网站没有任何互动元素(链接除外,即使没有 Gatsby,它们也无需 JavaScript 即可工作),你的用户也必须下载这部分 JavaScript,仅仅是为了将你的网站变成单页应用程序(SPA);SPA 是有自己的缺点的,我们稍后再提。

这种多出来的操作看来是违背我转向 SSG 的初衷(提高页面速度)的。华丽的 Gatsby 网站在 2,000 美元的 macBook 上可能很快,但对于使用 3G 连接和廉价智能手机的用户来说,它显示是能显示出来,但是没有响应;用户等待加载 JavaScript 的过程要持续 15 秒。电池和数据流量也得跟着往下掉了。

如果浏览器需要解析 296kb 的 JavaScript 代码才能显示出博客文章的列表,这就不是什么"渐进增强”,而是用错了工具。从网站 /Web 应用的大致区别来看,React 是用于构建 Web 应用的,这种应用需要有响应用户输入或实时获取数据的交互式 UI;而博客只是一个网站而已。

单页应用程序中的可访问性

单页应用程序这种网站放弃了传统的 Web 导航方法,即通过加载新的 HTML 文档来加载新内容;相反,它使用 AJAX 和 History API 之类的 JavaScript 特性来切换到新内容上,而不会触发页面加载。它的目标是提高感知的性能,并使网站看起来更像“原生”应用(从应用商店下载的那种)。不再需要整页重新加载的问题在于,浏览器和辅助技术将页面加载用作触发某些有用行为的信号,包括宣布新页面的标题或将键盘焦点重置到文档的开头。

如果你在开发关注可访问性的单页应用程序,那么你可能会试着使用 JavaScript 来模拟浏览器的行为。Gatsby 试图通过包含一个 RouteAnnouncer 组件来为你解决这个问题。它使用一个 ARIA live region 来宣布页面的 title 或 h1,以对使用屏幕阅读器软件的用户提示页面跳转行为。但这种方法也存在问题:它在配置和本地化方面仍然存在很多未解决的 issue。

我们已经看到,单页应用程序在导航方面存在固有的可访问性问题,但要注意的是,使用前端框架也会在其他方面带来可访问性问题。在 2020 年 2 月对 100 万个首页的调查中,WebAIM 发现使用 React 的网页的可访问性错误比平均水平高 5.7%;而使用 Vue 的网页则高出 25%。这并不一定意味着框架一定会导致这些错误,但是更多的 JavaScript 与更差的可访问性之间存在很强的相关性。

博客真的需要 JavaScript 吗?

很有可能,你构建的第一个网页的性能要比之后构建的许多页面都要好得多——它由一个 HTML 文件和一些 css 组成,也许还有一些未优化的图像,但它们并不会阻止页面加载。如果你也有我这样的经历,那么开始添加 JavaScript 的那一刻,你的网页性能就开始急剧下降了。并非所有字节都是一样的:与同等大小的 JavaScript 文件解析、编译和执行所需的时间相比,图像解码和渲染到屏幕所需的时间要少得多。

JavaScript 是一种强大的语言,可以完成一些令人难以置信的事情,但是在开发中你很容易过早开始使用它,其实本来用 HTML 和 CSS 就够了。应该看看最小功能原则:在你充分利用功能较弱的语言(HTML)之前,请不要使用功能更强大的语言(JavaScript)。在我看来,将博客变成 JavaScript 单页应用程序会带来不必要的复杂性。

这篇文章并不是要批判 Gatsby 而写的。它的背后有一些聪明的头脑,他们已经承认了本文中提到的许多问题,并试图解决它们。静态渲染和水化的页面还是比完全客户端渲染的 React 应用(如 create-react-App 生成的页面)要好得多,后者没有 JavaScript 就没法用。我确实不太满意 Gatsby 的宣传手法,他们说 Gatsby 适合任何类型的网站。客户端 JavaScript 是有成本的,开发人员应该意识到这一点。

用更少的 JavaScript 构建 Gatsby 网站

这使我陷入了一个两难境地:使用 Gatsby 开发网站是绝妙的体验;但是开发体验(DX)应该永远排在用户体验(UX)之后。那么如何在构建 Gatsby 网站时避免那些因为大量使用 JS 而带来的固有问题呢?当然,我们应该尽量删掉那些 JavaScript。所幸 Gatsby 社区内做出了很多努力来构建更、,更轻量级的网站:

首先,使用 gatsby-plugin-preact 将 React 换成 Preact 可以节省几千字节。我在 Component Gallery 上用了它,立刻将 JavaScript 负载减少了约 30kb。

如果你想用更激进的方法,可以使用一个插件来从你的 Gatsby 网站删除所有 Gatsby JavaScript。

你可以继续编写 react 组件和 GraphQL,甚至可以使用 CSS-in-JS 库(只要它输出 CSS 或内联样式),而无需向浏览器发送任何 JavaScript。只要扔掉所有客户端 JavaScript 就可以解决 Gatsby 的大多数问题。Gatsby Starter Low Tech 博客使用 no-javascript 插件和其他一些技术(包括将所有图像转换为灰度),来帮助你创建一个轻量且节能的博客。

用 Eleventy 从头开始

这时候我感觉有点不对劲——使用一个会大量推送客户端 JavaScript 的框架,却要删除所有 JavaScript 代码,这似乎是一种很复杂的网站构建方式。我想看看是否可以不用客户端 JavaScript 来构建功能完善的博客,这样就用不着什么插件来删除它了。于是我转向了另一个选项:

Eleventy 鼓励你按照自己的意愿构建网站。你可以使用自己最熟悉的技术,它只负责生成页面。Eleventy 为你提供了十种可以任意搭配的模板语言选项,包括 markdown、nunjucks 和 liquid;这意味着我可以从 Craft 中复制并粘贴旧的模板,更改文件扩展名,并做一些细微的调整就能运行在 Eleventy 中。用不着针对什么新的打包器来调整前端构建流程,我只需放入现有的 webpack 文件和 src 文件夹即可。使用并发包,我可以在 Eleventy 的 serve 过程中同时运行构建脚本。

像 Gatsby 一样,Eleventy 也有一个插件生态系统(虽然很小,但增长迅速)。我挑选了一些不需要添加客户端 JavaScript 也能添加功能的插件:

在帖子中显示代码段时,通常会包含特定于语言的语法高亮显示。有一些 JavaScript 库可以做到这一点,其中最流行的似乎是 Prism——你可以在客户端中运行它,但由于我们使用的是 JavaScript SSG,因此可以在构建时运行它,并将语法高亮显示所需的 HTML 元素和 CSS 类直接烘焙到文档中——这样就无需在浏览器中下载这个库了。

eleventy-plugin-embed-tweet 也可以在构建时而非客户端运行 JavaScript。Twitter 的默认嵌入代码迫使用户下载大量 JavaScript 才能显示一条推文。这个插件可以在构建时获取并渲染推文,这样只需少量 HTML 和 CSS 即可,根本不需要额外的 JavaScript。

与其他新技术一样,Eleventy 缺少某些更加成熟的工具所提供的功能。例如,在 Eleventy 中没有一种优雅的方法来生成响应式图像。相比之下,Gatsby 中出色的 gatsby-image 插件可以生成延迟加载和响应式的图片元素,并能在加载全分辨率文件后在低分辨率或 SVG 版本的图像间平滑切换。Eleventry 还有一些让我感到困惑的事情:我有一阵子一直搞不懂它的分页功能,认为它只是将帖子分页到指定大小的一些组中,之后才意识到它可以动态生成全新的页面;我还发现自己在同一文件中混用了模板语言:你可以随意在 markdown 文件中包含 nunjucks 标签,或将基于 yaml 的 frontmatter 换成 JavaScript,但这会破坏语法高亮显示、linting 和自动格式化。

结论

如果你还是选择了 Gatsby,我也不会怪你——有时候使用一个 opinionated 的框架也不错,并且如果你想要快速完成工作,这是一个可靠的解决方案。只是要注意它的性能成本,以及所有与 JavaScript 相关的潜在可访问性问题。

我选择使用 Eleventy 来构建自己的网站,但我知道这种方法并不适合所有人——完全按照自己的意愿来构建某些东西可能是很麻烦的事情。但你也用不着完全学我——与 Gatsby 类似,Eleventy 也有许多入门项目可以用作基础。其中一些工具,例如 Andy Bell 的 Hylia 入门套件可以在几分钟内搞定一个网站。它甚至预配置了 Netlify CMS,因此你无需编写任何代码即可编辑网站内容。

我学到了什么呢?使用 Eleventy 可以轻松构建不带 JavaScript 的博客,但总会有一些功能需要客户端 JavaScript 的:

  • 我的网站拿掉了 google Analytics,但它对用户来说没什么用途,所以我也不在乎——我会在另一篇文章中介绍它的服务端替代品。
  • 我使用了 loading="lazy"属性来延迟加载图片,但它的浏览器支持不够完整,并且在原生浏览器实现改进之前,它无法在加载图片时淡入淡出。
  • 黑暗模式切换——虽然我可以只用 CSS 来实现,无需访问 cookies 或本地存储,但我没办法在页面之间保持设定的值。

我是否会在不久的将来在网站上加入 JavaScript 呢?答案可能是否定的:我上面列出的功能并不是那么重要的。我并不是推荐大家都删除自己网站上的所有 JavaScript 文件,但从现在开始,在构建网站时我会尝试将 JavaScript 视为可选的额外功能,而不是体验的基本组成部分。我鼓励你也这样做。



Tags:JavaScript 框架   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
今年年初,我终于决定将自己的网站从基于 PHP 的 CMS 移植到基于 JavaScript 的静态网站生成器(SSG)了。原因如下: 虽然一开始我是“全栈”开发人员,但现在我只负责前端工作:如果我...【详细内容】
2020-07-29  Tags: JavaScript 框架  点击:(62)  评论:(0)  加入收藏
多年来,业界已经发布了大量 JavaScript 框架,怎样进行选择可能是一个挑战。如果你感到困惑,不知道应该选哪个或者究竟哪个适合你,那么我已经帮你解决了问题。在本文中,我将列出用...【详细内容】
2019-12-02  Tags: JavaScript 框架  点击:(64)  评论:(0)  加入收藏
JavaScript 是开发领域的重要技术之一。根据 Statista 的报告,JavaScript 是 2018 年开发人员使用的最流行的编程语言,在 2019 年亦是如此。然而,在为项目选择恰当的 JavaScrip...【详细内容】
2019-10-16  Tags: JavaScript 框架  点击:(79)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条