读 《HTML5 揭秘》有感

最近在补一些 HTML 的书籍,偶尔读到这本书,虽然这本书已是10年之前的书籍了,不过其中有些有趣的知识点与观点被我提取了出来。css

标准建立与技术实现冲突

做者在开始就提出了 Mozilla 开发人员关于标准与实现之间的冲突的一个观点:html

一份技术规范和他的具体实现必需要作到步调一致。实现先于规范完成不是什么好事情,由于人们会开始依赖这些已实现的细节,这样会对规范形成制约。然而,你也不但愿在规范已经完成时尚未任何相关的具体实现与实践经验,由于这样规范就得不到任何反馈。这里面若是存在着没法避免的冲突,而咱们也须要硬着头皮去克服了。

事实上,对于前端开发而言,具体实现早于技术规范的制定已是一种常态了。但与其余领域不一样的是:前端的新标准非必要条件下是不能够破坏以前的实现。前端

在这里,我能够举几个兼容性的例子:vue

你们可能都使用过 String.prototype.includes 来判断一个字符串是否包含在另外一个字符串中。可是实际上,在 Firefox 18 - 39中,这个方法的名称叫 contains()。因为在Firefox 17上,一些使用 MooTools 1.2的网站会崩溃掉。当年因为各个框架为了可以更简单的使用函数,在各自的代码库中修改内置对象的 prototype,同时框架也考虑到了将来标准可能会实现,为了兼容之后的标准,他们对 prototype 进行判断,而后若是对象当前 prototype 上没有函数实现,就使用当前本身定制的函数,若是有函数实现的话,就使用浏览器所提供的函数。虽然他们考虑到了兼容标准,可是他们却没能考虑到标准是会发生改变的。可能在若干年后,标准实现后,函数已经与当前截然不同。所使用的代码就会发生错误。因此,无奈之下,该函数被重命名为 includes() 。事实上咱们能够看出,contains 命名要比 includes 好得多。 webpack

在最新的提案之一就是在类中添加私有变量方法,标准将使用 # 符号来表示类的私有变量。css3

class Count {
  #a = 1;
  getCount() {
    return this.#a  
  }
}
const count1 = new Count()

count1.getCount()
// 1

console.log(count1)
// Uncaught SyntaxError: Private field '#a' must be declared in an enclosing class

emmm...,美丑你们自行鉴别。也正是由于前端以前没有所谓的私有变量,因此你们都会“约定” _ 就是私有变量,可是事实上,任何约定都只会防君子不防小人。必定会有大量的代码直接进行调用。一旦浏览器支持后,必然会影响大量网页。 因此咱们也只能硬着头皮去克服了。git

受到影响的不只仅是 JavaScript,同时也有 Css。 Css 变量为了可以在 Sass(变量用了 $ ) 和 Less(变量用了 @) 中使用,也是不得不去使用 --。能够看到这样进行 Css 变量定义也是不那么美观的。github

:root {
  --main-bg-color: brown;
}

交付出东西的人才是赢家

该书也讨论了为何会存在 <img> 这个元素标签。为何它是 img,而不是 include,image(事实上,貌似 image 元素标签也是存在在浏览器中的,能够看这一篇 blog Having fun with <image>)?web

答案以 93 年一群大佬的精彩的对话为主线,其中能够看到一些真知灼见,也有一些前瞻性很强的言论。众口难调是必然的。不少时候,协议的制定自己就不是一个技术问题,很难有对错而言。可是为何必定是 <img>,答案很简单,由于提议者马克·安德里森在对话后直接发布了代码来处理这个元素。vue-cli

这并非说给出代码实现的就必定是赢家,可是这是赢家的必要条件,不是吗?讨论固然重要,是一种思想的交流,可是当咱们不能从道理上说服别人的时候,就只能用其余的方案来代表本身的态度。

过于超前就会死亡

该书也讨论了当年 WHAT 小组和 W3C HTML 小组之间对于 HTML 发展的不一样思考和看法,开始时候,两个小组之间各自为政,无视对方存在。WHAT 小组针对 Web 表单和新的特性进行工做,而另外一组忙于制定 XHTML 2.0 版本,但惋惜的事情是: 没有浏览器为之提供实现。

XHTML 是和 HTML 不兼容的,这意味者不但浏览器开发者要作大量的工做,还须要让前端开发者一会儿切换到 XML,彻底书写良好的规范 — 这是行不通的。而 WHAT 小组采用宽容的错误处理,把重点放在新特性上。

不管从观念仍是互联网产品,过于超前的结局其实都不是太好。固然,这从侧面也印证了一个道理,选择比努力更重要的不是一句空话。

难以消失的浏览器兼容技术

最后,咱们来聊一下技术吧。

新的功能已经到来,可是咱们要等到何时才能够采用它?这个问题不但出如今 10 年前,同时也会在如今。优秀的开发者老是但愿使用最新的特性来提高用户体验。固然了,咱们如今能够依赖 Can I use 来判断浏览器支持状况。

很早以前,咱们用 <noscript> 来处理不使用脚本的网页。

再而后,咱们经过浏览器特性检测来进行兼容处理。例如 Modernizr 库来检查浏览器是否支持 HTML5 以及 css3。利用 polyfill 来升级不支持特性的浏览器。

即便在今天,这些问题依然没有被解决。固然咱们利用更加先进的技术来支持罢了。

Polyfill.io 根据不一样的浏览器确立不一样的 polyfill

若是进行过前端开发,就不可能没有使用过 polyfill。polyfill你能够理解为“腻子”,就是装修的时候,能够把缺损的地方填充抹平。针对于各个浏览器的把差别化抹平。因为各个浏览器版本不一样,所须要的 polyfill 也不一样,

Polyfill.io是一项服务,可经过选择性地填充浏览器所需的内容来减小 Web 开发的烦恼。Polyfill.io读取每一个请求的User-Agent 标头,并返回适合于请求浏览器的polyfill。

若是是最新的浏览器且具备 Array.prototype.filter

https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.filter

/* Disable minification (remove `.min` from URL path) for more info */

可是若是当前浏览器没有此函数,就会在 正文下面添加有关的 polyfill。

国内的阿里巴巴也搭建了一个服务,能够考虑使用,网址为 polyfill.alicdn.com/polyfill.mi…

type='module' 辅助打包与部署 es2015+ 代码

使用新的 DOM API,能够有条件地加载 polyfill,由于能够在运行时检测。可是,使用新的 JavaScript 语法,这会很是棘手,由于任何未知的语法都会致使解析错误,而后全部代码都不会运行。

该问题的解决方法是

<script type="module">。

早在 2017 年,我便知道 type=module 能够直接在浏览器原生支持模块的功能。具体能够参考 JavaScript modules 模块 以及 ECMAScript modules in browsers。可是当时感受只是这个功能很强大,并无对这个功能产生什么解读。可是却没有想到能够利用该功能识别你的浏览器是否支持 ES2015。

每一个支持 type="module" 的浏览器都支持你所熟知的大部分 ES2015+ 语法!!!!!

例如

  • async await 函数原生支持
  • 箭头函数 原生支持
  • Promises Map Set 等语法原生支持

所以,利用该特性,彻底能够去作优雅降级。在支持 type=module 提供所属的 js,而在 不支持的状况下 提供另外一个js。具体能够参考 Phillip Walton 精彩的博文,这里也有翻译版本 【译】如何在生产环境中部署ES2015+

若是当前项目已经开始从 webpack 阵营转到 Vue CLI 阵营的话,那么恭喜你,上述解决方案已经被内置到 Vue CLI 当中去了。只须要使用以下指令,项目便会产生两个版本的包。

vue-cli-service build --modern

具体能够参考 Vue CLI 现代模式

不得不说的是: 目前也有开发者把 ESM module 已经做为主流浏览器的功能来思考。还提供了 10 倍打包速度的 Snowpack。虽然目前距离生产环境还有必定差距,不过若是下次须要开发小型我的项目,我会尝试使用该工具。

鼓励一下

若是你以为这篇文章不错,但愿能够给与我一些鼓励,在个人 github 博客下帮忙 star 一下。

博客地址

参考资料

ECMAScript modules in browsers

Vue CLI 现代模式

【译】如何在生产环境中部署ES2015+

相关文章
相关标签/搜索