摘要:换言之,用的代码取代。模块在顶层作用域中创建声明变量的行为有别于脚本。但现在是可以部署的,所以是时候去改变了。通过发布,我们为开发人员提供了一种选择,并最终惠及每个人。编写代码对开发者来说是一个胜利,部署代码对用户来说是一个胜利。
原文链接
与我交流过的绝大多数web开发者,都喜欢使用所有新的语法特性(如async/await,类,箭头函数等)。尽管所有现代浏览器都支持以上的语法,多部分开发者仍然会转译到ES5并且加上polyfill以便支持哪一小部分仍旧使用老版本浏览器的用户。
这...有点糟。在理想的的世界中,是没有不必要的代码!
新版本的JS和DOM接口能让我们选择性地加载polyfill,因为在运行时,我们可以检测浏览器对新特性的支持情况。但是新的JS语法有一点不好,因为无法识别的语法都会造成解析错误,导致没有代码会被执行。
虽然现在并没有对feature-detecting这个语法的好的解决方案,但我们确实有一个方法能做到ES2015语法支持的检测。
这就是
多数开发者将视为加载ES模块的一种方式(这没毛病啊),但也有更直接且实际的加载常规JavaScript文件与ES2015+功能,并知道浏览器能处理它!
换言之,所有支持语法的浏览器也支持绝大多数你爱的那些ES2015+属性。例如:
async/await
类
箭头函数
fetch,Promise,Map,Set等
剩下的事就是为不支持的浏览器提供一个降级的处理。如果你正在生成一个ES5版本的代码,那么恭喜你你已经做好这一步了,现在你需要做的就是生成一个ES2015+的版本!
本篇余下的部分将讨论如何实现这一技术以及发布ES2015+代码的能力将如何改变我们编写模块的方式。
实现如果你已经上手了webpack或rollup这样的工具来生成你的JS,那就继续吧!
下一步,在现有bundle的基础上,你要生成第二份bundle。与第一份bundle的唯一区别就是你不再需要把代码转译到ES5版本,同时你也不用在引入任何polyfill。
在使用babel-preset-env的前提下,第二步是非常简单的。你唯一要做的就是改变配置中的浏览器列表到支持的浏览器,这样Babel就不会进行那些不必要的转译。
换言之,用ES2015+的代码取代ES5。
举个例子,如果你在使用webpack,entry的路径是./path/to/main.js。目前的配置(要编译成ES5版本的)应该大致如下(我会把这个bundle曾为"古早版",因为它是ES6的):
module.exports = { entry: { "main-legacy": "./path/to/main.js", }, output: { filename: "[name].js", path: path.resolve(__dirname, "public"), }, module: { rules: [{ test: /.js$/, use: { loader: "babel-loader", options: { presets: [ ["env", { modules: false, useBuiltIns: true, targets: { browsers: [ "> 1%", "last 2 versions", "Firefox ESR", ], }, }], ], }, }, }], }, };
要得到一个现代的支持ES2015+的版本。你要做的仅仅是将目标环境改成支持的浏览器,像下面这样:
module.exports = { entry: { "main": "./path/to/main.js", }, output: { filename: "[name].js", path: path.resolve(__dirname, "public"), }, module: { rules: [{ test: /.js$/, use: { loader: "babel-loader", options: { presets: [ ["env", { modules: false, useBuiltIns: true, targets: { browsers: [ "Chrome >= 60", "Safari >= 10.1", "iOS >= 10.3", "Firefox >= 54", "Edge >= 15", ], }, }], ], }, }, }], }, };
当你执行构建时,这两个配置文件会得到两个JS文件:
main.js (ES2015+语法)
main-legacy.js (ES5语法)
下一步,就是更新你的HTML来支持选择性加载JS bundle。你同时可以使用和来实现。
小贴士:可恶的Safari 10并不支持nomodule属性,不过你可以在HTML前部引入safari-nomodule.js来解决这一问题。(好在,在Safari 11种他们解决了这个问题,我到都拔出来了)重要的思考
!
这多数情况下,这个方法“能用”。但是在使用这一策略前,我们需要了解模块加载的一些细节。
模块会像语言一样被加载,这就意味着。知道文件被解析前都不会被执行。如果你有一些代码需要先行,请把它们拆分出来,然后多带带引用。
模块会默认使用严格模式,所以如果出于某种原因,你不要使用严格模式,请拆分出这部分代码,并多带带引用。
模块在顶层作用域中创建/声明变量的行为有别于脚本。在脚本中通过var foo = "bar"或是 函数声明function foo() {…}的变量可以通过window.foo访问。但在一个模块中却并非如此。所以这可能会成为你书写代码时的一个坑!
一个实际的例子我创建了一个模版项目,读者可以看到这一方法在实际工作中的应用。
在这个模版中,我试用了许多新出的webpack特性,因为这个技术在实际工作中真的能用。摆脱,我可不是赵括。这些特性包括我们常见的实践:
代码拆分
动态引用(在运行时,根据条件引用额外代码)
资产指纹(一个有效的长期缓存)
我不会用自己不会的技术,如果你想要了解更多欢迎阅读源代码
如果你并非使用webpack来生成生产环境的bundle,过程也大同小异。我之所以选择webpack,因为它是当下最流行的,但它也是最复杂的!如果webpack能用,那么其他工具也能使用。
真的需要搞得这么复杂?在我看来必须的,这些付出是值得的。下表比较了两种版本最终生成文件的实际大小:
即便经过Gzip传统ES5版本也是ES2015+版本体积的两倍。
大体积文件不尽更耗费时间去加载,同时,也需要更长时间解析与执行。这两个版本的解析/执行时间依旧是两倍的关系。(这个测试我试用了webpagetest.org提供的 Moto G4)
虽然这些独立的文件不大,解析/执行的时间也不是特别长,但这仅仅是个博客。如果是外头那些庞然大物,ES2015+你绝对值得拥有!
一项来之HTTPArchive数据的统计显示。Alexa排名前列的网站中有85181在他们的项目中使用了babel-polyfill, core-js, 或是regenerator-runtime。6个月前这个数字是34588!
现实就是转译以及使用polyfill正迅速成为新的标准。不幸的事,大部分用户正因此牺牲了流量来下载这些本来可以更小的文件。
是时候,祭出ES2015了现在的问题就是开发者并没有发布ES2015+版本的代码,而是发布了转译后的ES5版本。
但现在ES2015+是可以部署的,所以是时候去改变了。
我完全明白,这会带来一些阵痛。 如今大多数构建工具发布的文档,都推荐ES5的配置。 这意味着,如果模块作者开始向npm发布ES2015 +源代码,他们可能会破坏一些用户的构建,这将会造成混乱。
问题是大多数使用Babel的开发人员将它配置为不在node_modules中传输任何内容,但是如果模块是使用ES2015 +源代码发布的,则这是一个问题。 幸运的是修复很简单。 您只需从构建配置中删除node_modules排除:
rules: [ { test: /.js$/, exclude: /node_modules/, // 移除这行 use: { loader: "babel-loader", options: { presets: ["env"] } } } ]
弊端就是,babel这样的工具不仅仅需要本地依赖关系,在执行时还需要在node_modules中传递这种关系。这样构件会变慢。不过这一问题可以在持续化的本地缓存工具上得到解决。
纵使前途坎坷,我们也因该为提升用户体验大步向前。通过发布ES2015,我们为开发人员提供了一种选择,并最终惠及每个人。
结论的价值远不仅仅是为了在浏览器中加载ES模块。
在支持这一特性的现代浏览器中,可以给予开发者,选择性加载单一JS文件的预约体验。
这与nomodule属性一起,为我们提供了一种在生产环境中使用ES2015+代码的方法,我们终于可以停止向不需要它的用户发送如此多的代码。
编写ES2015代码对开发者来说是一个胜利,部署ES2015代码对用户来说是一个胜利。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95797.html
摘要:如果是在生产环境下,则加入插件,执行代码压缩,并且去除。规定了在开发环境下才使用。疑问目前为止,对于多页面项目还是没有找到一个很好的方案去构建自动化。原文可以看我的博客最佳实践部署生产 tip webpack的入门篇可以看我的这一片博文。《如何使用webpack—webpack-howto》. 前言 最近一段时间在项目中使用了webpack和React来开发,总之来说也是遇到了许多坑,...
摘要:已经转码成了已经转码成了合并压缩并重命名的文件使用如果我们使用了中的,通过进行模块化开发,那么通过转码后,将被转码成符合规范的和等,但是浏览器还是不认识,这时可以使用对代码再次进行构建。 一说起ES6,总会顺带看到webpack、babel、browserify还有一些认都不认识的blabla名词,对于gulp才会一点点的我来说,内心简直是崩溃的,上网查了一些文章,探索着用gulp搭起...
摘要:虽然够好用,奈何没有浏览器对其可以完全支持,本文书写时间,开发版号称已经支持的特性。开始安装本系列假定读者都有使用经验,如果还没有,赶紧去这里了解并安装吧。到此,我们的已经准备就绪。 通过前面章节的讲解,大家对ES2015的一些新语法有了初步的理解,之前我们的测试代码都可以直接放入 Chrome Console 中直接运行,为了更好的学习后面的面向对象和模块开发,我先用一章介绍一下 B...
摘要:转自前端外刊评论非常感谢,翻译的很好,受益很多,转到此处让前端小伙伴们也惊呆下上次我写前端工程师必知必会已经是三年前了,那是我写过最火的文章了。测试的第二大障碍是工具。 转自:前端外刊评论 非常感谢,翻译的很好,受益很多,转到此处让前端小伙伴们也惊呆下........ 上次我写《前端工程师必知必会》已经是三年前了,那是我写过最火的文章了。三年了,我仍然会在Twitter上...
阅读 2385·2021-11-18 10:02
阅读 668·2021-10-08 10:04
阅读 2220·2021-09-03 10:51
阅读 3519·2019-08-30 15:44
阅读 2761·2019-08-29 14:09
阅读 2443·2019-08-29 12:21
阅读 2045·2019-08-26 13:45
阅读 1778·2019-08-26 13:25