一棵树的图示啥样的主干和小片,与附近的手锯。

负责的JavaScript:第二部分

你和开发团队的其他成员积极为公司的老网站的总重新架构游说。你的请求被管理,甚至达到C-套房谁开了绿灯听到。心花怒放,你和团队开始设计工作,复制和IA团队。不久,你敲出新的代码。

继续下面的条

它一开始是很无辜的NPM安装这里还有一个NPM安装在那里。不过,在您了解它之前,您就已经安装了产品依赖项,就像一个不关心第二天早上的大学生在做桶架一样。

然后你启动。

与大多数饮酒过量的后果不同,这种痛苦不是从第二天早上开始的。,没有。几个月后,产品所有者和中层管理人员开始感到恶心和头痛,他们想知道,为什么自产品推出以来,转化率和收入都下降了。当首席技术官周末从小木屋回来,想知道为什么这个网站在他们的手机上加载得这么慢时——如果它真的加载过的话——它就达到了狂热的程度。

每个人都高兴。现在没有一个是快乐的。欢迎来到您的第一个JavaScript宿醉。

这不是你的错# section2

当你和严重的宿醉作斗争时,“我早告诉过你”将是一个应得的,即使会引起争吵的指责——假设你甚至可以在如此糟糕的状态下战斗。

当涉及到JavaScript的宿醉,有很多怪施舍的。指责是在浪费时间,但。网络今天要求我们遍历比我们的竞争对手更快的景观。这种压力意味着我们可能采取的可用的是尽可能有任何方式的优势。那个这意味着我们更有可能(但并非注定)构建开销更大的应用程序,并可能使用有损性能和可访问性的模式。

Web开发并不容易。这是一个很长的过程,我们很少在第一次尝试时就成功。然而,在网络上工作的最好部分是,我们没有得到它完美的开局。我们可以在事后的改进,而这正是第二批本系列正在这里进行。完美还有很长的方式。现在,让我们的缘灭了JavaScript解酒通过提高你的网站的,呃,scriptuation在短期内。

逮捕惯犯# section3

这似乎死记硬背,但它的价值要通过基本的优化列表。它的情况并不少见大型开发团队,特别是那些工作在许多存储库或不使用优化的样板,忽视他们。

摇动那些树#第四单元

首先,确保工具链配置为执行树摇动。如果树摇晃是新的给你,我写的去年的指南你可以咨询。简而言之,树抖动是一个过程,在这个过程中,代码库中未使用的导出不会打包到生产包中。

树摇是可用的与现代捆绑的盒子,如的WebPack,卷起,或包裹咕哝着说狼吞虎咽地吃哪位不打包机,而是任务的跑步者-won't为你做这个。一个任务运行不建立依赖关系图就像一个捆绑者一样。相反,它们对您使用任意数量的插件提供给它们的文件执行离散的任务。任务的跑步者能够使用插件来扩展使用捆扎机处理JavaScript的。如果以这种方式扩展任务亚军是你有问题,你可能需要手动审核和删除未使用的代码。

摇树要有效,必须做到以下几点:

  1. 您的应用程序逻辑和您在项目中安装的包必须被编写为ES6模块。树摇晃CommonJS的模块实际上不可能。
  2. 你的打包机必须变换ES6模块插入在构建时另一模块的格式。如果发生这种情况在使用通天工具链,@babel / preset-env配置必须指定模块:假在预防ES6代码被转换为CommonJS的。

在关闭的机会摇树您的构建过程中没有发生,这让工作可能会有帮助。当然,其效果对案件逐案基础上变化。这也取决于你导入模块是否引进副作用,这可能会影响一个捆绑的动摇未使用的出口能力。

拆分代码# section5

很有可能你正在使用某种形式的代码分离,但值得重新评估一下你是如何做的。不管如何你是分裂码,还有那些总是值得问自己两个问题:

  1. 你是重复数据删除通用代码之间入口点吗?
  2. 你是否延迟加载了所有合理的功能动态进口()吗?

这些都很重要,因为减少冗余代码对性能至关重要。延迟加载功能还通过降低给定页面上的初始JavaScript占用空间来提高性能。在冗余方面,使用分析工具,如捆绑好友可以帮助你了解你是否有问题。

Bundle Buddy实用程序演示了JavaScript包之间共享了多少代码。
Bundle Buddy可以检查webpack编译统计数据,并确定包之间共享了多少代码。

在考虑延迟加载时,可能很难知道从哪里开始寻找机会。当我在现有项目中寻找机会时,我会在整个代码库中搜索用户交互点,比如单击和键盘事件,以及类似的候选事件。必威官网网址多少任何需要用户交互才能运行的代码都是dynamic的潜在候选对象进口()

当然,按需加载脚本可能会明显延迟交互,因为交互所需的脚本必须首先下载。如果数据使用不是一个问题,考虑使用相对=预取资源的提示以低优先级加载这样的脚本,这样就不会对关键资源争夺带宽。支持相对=预取虽好,但什么都不会破,如果它是不支持的,因为这样的浏览器会忽略标记他们不明白。

外部化的第三方托管的代码# section6

理想情况下,您应该自行托管尽可能多的站点依赖项。如果因为某种原因你必须从第三方加载依赖项,将它们标记为外部在捆绑的配置。如果不这样做可能意味着你的网站的访问者会下载在本地托管代码来自第三方的相同代码。

让我们看一个假设的情况下,这可能伤害你:说,从公共CDN你的站点载入Lodash。你还在你的项目为当地发展安装Lodash。但是,如果你失败了,以纪念Lodash外部,你的产品代码最终会加载它的第三方拷贝此外到绑定的、本地托管的副本。

今年五月似乎就像常识一样,如果你知道如何对付捆扎者,但我看到它被忽视了。值得你花时间检查两次。

如果您不相信自己托管第三方依赖项,那么可以考虑添加DNS预取,PRECONNECT,或者甚至预加载提示他们。这样做可以降低你的网站的互动的时间如果JavaScript对于呈现内容至关重要的话,那么您的站点的内容也可以速度指数

更小的替代方案,更少的开销# section7

用户级的JavaScript就像一个巨大的糖果店,我们作为开发人员被大量的开源产品吓到了。框架和库允许我们扩展我们的应用程序,以快速完成各种事情,否则会花费大量的时间和精力。

虽然我个人倾向于尽量减少在我的项目中使用客户端框架和库,但它们的价值是引人注目的。然而,我们有责任有点强硬,当涉及到我们安装的内容。当我们已经建立并运东西,取决于安装的代码的转换来运行,我们已经接受了基准成本,只有那些代码的维护者几乎可以地址。对?

也许吧,但话说回来,也许不会。这取决于所使用的依赖。举例来说,作出反应是非常受欢迎的,但Preact是一个超薄很大程度上共享相同API并与许多React插件保持兼容性的备选项。勒克桑date-fns是更紧凑的替代品moment.js,这是不是很小

库如Lodash提供许多有用的方法。然而,其中一些可以很容易地用本机ES6替换。Lodash的紧凑方法,例如,可替换为过滤数组的方法还有更多的可更换无需太多努力,也不需要引入大型实用程序库。

无论你的首选工具,这个想法是一样的:做一些研究,看看是否有更小的替代品,或者如果本地语言功能可以做的伎俩。你可以在它多么小的努力带你到严重降低你的应用程序的开销感到惊讶。

为您的脚本提供不同的服务# section8

您很有可能在工具链中使用Babel将您的ES6源代码转换为可以在旧浏览器上运行的代码。这是否意味着我们注定要向不需要捆绑服务的浏览器提供捆绑服务,直到老浏览器完全消失?当然不是!不同的服务通过生成两种不同的ES6源代码来帮助我们解决这个问题:

  • 捆绑之一,它包含了所有你的网站工作旧版浏览器上所需的变换和polyfills。你可能已经现在这个服务包。
  • 包二,其中包含几乎没有的转换和填充,因为它的目标是现代浏览器。这是您可能不会提供的包——至少不会然而,

实现这涉及到一个位。我已经写了一个指南,教你如何做到这一点,所以没有必要在这里深潜。长期和短期的是,你可以修改你的构建配置来生成您的网站的JavaScript代码额外但更小的版本,它的作用只是现代浏览器。最好的部分是,这些储蓄就可以实现在不牺牲你已经提供的任何特性或功能。根据您的应用程序代码,储蓄可能是相当显著。

对项目遗留包(左)和现代包(右)的webpack-bundle-analyzer分析。查看大图

简单的模式对于这些服务捆绑到其各自的平台是短暂的。它也可以在现代浏览器一种享受:

< !现代浏览器加载这个文件:——>/js/app.mjs<! - 传统的浏览器加载该文件: - >/ js / app.js

遗憾的是,这种模式一个警告:旧版浏览器如IE 11,甚至比较现代化的,如边缘版本15到18,将下载包。如果这对你来说是一个可以接受的取舍,那么不要再担心了。

在另一方面,你需要一个解决办法,如果你很在意旧的浏览器下载两套束对性能的影响。下面是一个使用脚本注入一个潜在的解决方案(而不是脚本),以避免在受影响的浏览器上重复下载:

VAR scriptEl =使用document.createElement( “脚本”);如果(在scriptEl “noModule”){//建立现代脚本scriptEl.src = “/js/app.mjs”;scriptEl.type = “模块”;}其他{//设置传统脚本scriptEl.src = “/js/app.js”;scriptEl.defer = TRUE;//类型=默认情况下,“模块”推迟,所以设置在这里。} //进样!document.body.appendChild(scriptEl);

该脚本推断,如果浏览器支持nomodule属性在里面脚本元素,它理解类型=“模块”。这确保了旧浏览器只能得到旧脚本,而现代浏览器只能得到现代脚本。但是要注意,动态注入的脚本默认情况下是异步加载的,因此设置异步属性如果依赖顺序是至关重要的。

Transpile少# section9

我不是来垃圾巴贝尔的。它是不可或缺的,但是上帝,它增加了批量你不知道的额外的东西。它是值得偷看的幕后,看看它在做什么。编码习惯上的一些小改变可以对Babel输出的内容产生积极的影响。

https://twitter.com/_developit/status/1110229993999777793

即:默认参数是一个非常方便的ES6功能,你可能已经使用:

function logger(message, level = "log") {console[level](message);}

这里要注意的是水平参数,其默认值为“log”。这意味着如果我们想调用的console.log使用这个包装器函数,我们不需要指定水平。太好了,对吧?除非当Babel转换这个函数时,输出如下:

函数logger(消息){var level =参数。长度> 1 &&参数[1]!==未定义?参数[1]:“日志”;控制台(水平)(信息);}

这是一个例子,尽管我们的初衷是好的,但开发人员的便利可能适得其反。源文件中的几个字节现在转换成了什么在我们的生产代码较大。丑化不能做太多关于它要么,作为参数不能减少。哦,如果你认为其他参数也许是一剂有价值的解药,巴别塔的变形对他们来说更笨重:

//源功能记录器(...参数){常量[级别,消息] = ARGS;控制台(水平)(信息);} //巴别输出函数记录器(){对于(VAR _len的arguments.length =,ARGS =新阵列(_len),_key = 0; _key <_len; _key ++){ARGS [_key] =参数[_key];}常量级别= ARGS [0],消息= ARGS [1];控制台(水平)(信息);}

更糟糕的是,Babel甚至可以为带有a的项目转换此代码@babel / preset-env组态针对现代浏览器,这意味着不同服务的JavaScript中的现代包也会受到影响!你可以采用宽松的变换柔化吹气——这是一个好主意,因为它们通常比更符合规格的同行要小得多——但使松散转换可能会导致问题,如果您从构建流水线巴贝尔删除以后

不管你是否决定启用宽松的变换,这里的削减transpiled默认参数的克鲁夫特的一种方式:

//巴贝尔不会接触这个函数记录器(消息,电平){控制台[水平||“日志”(消息);}

当然,默认参数是不是只要要小心的特征。例如,传播的语法转化,就像箭头功能还有一大堆其他的东西

如果你不想完全避免这些功能,你有几个方法来减少它们的影响:

  1. 如果您正在编写一个库,可以考虑使用@babel /运行时在音乐会@巴贝尔/插件变换的运行时为了重复Babel放入代码中的helper函数。
  2. 对于应用程序中的polyfilled功能,可以有选择地将它们与@babel / polyfill通过@通天/预设env的useBuiltIns:“用法”选择。

这完全是我的观点,但我认为最好的选择就是完全避免现代浏览器产生的束transpilation。这并不总是可能的,特别是如果你使用JSX,其必须被转化为所有如果您使用的是没有得到广泛支持的前沿语言特性,那么就可以使用浏览器。在后一种情况下,也许有必要问问那些特性是否真的是交付良好用户体验所必需的(它们很少是必需的)。如果您认为Babel一定是您的工具链的一部分,那么您就有必要不时地查看一下Babel可能正在做的、您可以改进的次优内容。

改进是不是一场比赛# section10

当你按摩你的寺庙时,这个可怕的JavaScript解酒是要提升琢磨,明白,这恰恰当我们急于尽可能快,因为我们可能可以在用户体验可能遭受得到的东西在那里。作为Web开发社区的迭代更快占据心思在竞争的名字,它的值得你花时间慢下来一点点。您将发现,通过这样做,您可能没有竞争对手那么快地迭代,但是你的产品快点比他们。

当你把这些建议,并把它们应用到你的代码,知道进步不自发地在一夜之间发生。Web开发工作。当我们深思熟虑并致力于工艺的长途真正有影响力的工作就完成了。专注于稳步改善。测量,测试,重复,和你的网站的用户体验将提高,你会随着时间的推移得到更快的点点滴滴。

特别感谢贾森米勒为了技术编辑这篇文章。的创建者和众多维护者之一Preact,这是一个小得多的替代方案,可以使用相同的API进行响应。如果你使用Preact,请考虑通过开放式的集体支持Preact

没意见

有什么要说的吗?

我们已经关闭了评论,但是你可以看到在我们关闭评论之前人们都说了些什么。

从阿拉巴马州

待做的工作

“设计价值”,由吉姆Kalbach的书作业的节选做剧本,创造一个就业机会驱动的路线图和使用工作的故事来解决特定的设计问题给出了建议。

betway必威app

语音驱动许多我们可用性测试方法的内容挑战。普雷斯顿所以把他们变成为介质本身的机会和优势。
内容

跨文化设计

在这段跨文化设计的摘录中,Senongo Akpem讨论了排版的许多方面,当你想要达到一个全球的受众时必须考虑。
设计