Alien ZHOU

Results 53 issues of Alien ZHOU

## 引言 如何“严谨地”判断两个变量相同?仅仅使用 `===` 就可以了么? ![](https://user-gold-cdn.xitu.io/2020/1/4/16f6f67316cf3a36?w=1400&h=200&f=png&s=34612) ## 严格相等 我们可以非常快的写一个 `is` 方法来判断变量 x 是否就是 y: ```JavaScript // 第一版 function is(x, y) { return x == y; } ``` 当然,你会很快发现,方法里用了 `==`,由于[隐式转换](https://www.w3schools.com/js/js_type_conversion.asp)的问题,这并不严谨。所以我们自然会使用如下的方法: ```JavaScript...

JavaScript

近来,GoogleChromeLabs 推出了 [quicklink](https://github.com/GoogleChromeLabs/quicklink),用以实现链接资源的预加载(prefetch)。本文在介绍其实现思路的基础上,会进一步探讨在预加载方面前端工程师还可以做什么。 ## 1. quicklink 是什么的? quicklink 是一个通过预加载资源来提升后续方案速度的轻量级工具库。旨在提升浏览过程中,用户访问后续页面时的加载速度。 当我们提到性能优化,往往都会着眼于对当前用户访问的这个页面,如何通过压缩资源大小、删减不必要资源、加快页面解析渲染等方式提升用户的访问速度;而 quicklink 用了另一种思路:我预先帮你加载(获取)你接下来最可能要用的资源,这样之后的真正使用到该资源(链接)时就会感觉非常顺畅。 照着这个思路,我们需要解决的问题就是如何预先帮用户加载资源呢?这里其实涉及到两个问题: - 如何去预加载一个指定资源?(预加载的方式) - 如何确定某个资源是否要加载?(预加载的策略) 下面就结合 quicklink 源码来看看如何解决这两个问题。 > 注:下文提到的“预加载”/“预获取”均指 prefetch ## 2. quicklink 实现原理 ## 2.1. 如何去预加载一个指定资源?...

JavaScript
浏览器

## 1. 熟悉的`JSON.stringify()` 在浏览器端或服务端,`JSON.stringify()`都是我们很常用的方法: - 将 JSON object 存储到 localStorage 中; - POST 请求中的 JSON body; - 处理响应体中的 JSON 形式的数据; - 甚至某些条件下,我们还会用它来实现一个简单的深拷贝; - …… 在一些性能敏感的场合下(例如服务端处理大量并发),或面对大量 stringify 的操作时,我们会希望它的性能更好,速度更快。这也催生了一些优化的 stringify 方案/库,下图是它们与原生方法的性能对比: ![](https://user-gold-cdn.xitu.io/2019/6/5/16b25784d49d825a?w=1200&h=488&f=png&s=42368)...

JavaScript
Performance

## 1. 什么是“划词高亮”? 有些同学可能不太清楚“划词高亮”是指什么,下面就是一个典型的“划词高亮”: [![](http://upload-images.jianshu.io/upload_images/6476654-54773175bfd4fa3f?imageMogr2/auto-orient/strip)](https://alienzhou.github.io/web-highlighter/) 上图的示例网站可以[点击这里访问](https://alienzhou.github.io/web-highlighter/)。用户选择一段文本(即划词),即会自动将这段选取的文本添加高亮背景,用户可以很方便地为网页添加在线笔记。 笔者前段时间为线上业务实现了一个与内容结构非耦合的文本高亮笔记功能。非耦合是指**不需要为高亮功能建立特殊的页面 DOM 结构,而高亮功能对业务近乎透明**。该功能核心部分具有较强的通用性与移植性,故拿出来和大家分享交流一下。 > 本文具体的核心代码已封装成独立库 [web-highlighter](https://github.com/alienzhou/web-highlighter),阅读中如有疑问可参考其中代码↓↓。 > [![image](http://upload-images.jianshu.io/upload_images/6476654-0036b39ea5538bfd?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)](https://github.com/alienzhou/web-highlighter) ## 2. 实现“划词高亮”需要解决哪些问题? 实现一个“划词高亮”的在线笔记功能需要解决的核心问题有两个: - 加高亮背景。即如何根据用户在网页上的选取,为相应的文本添加高亮背景; - 高亮区域的持久化与还原。即如何保存用户高亮信息,并在下次浏览时准确还原,否则下次打开页面用户高亮的信息就丢失了。 一般来说,划词高亮的业务需求方主要是针对自己产出的内容,你可以比较容易对内容在网页上的排版、HTML 标签等方面进行控制。这种情况下,处理高亮需求会更方便一些,毕竟自己可以根据高亮需求调整现有内容的 HTML。 而笔者面对的情况是,页面 HTML 排版结构复杂,且无法根据高亮需求来推动业务改动 HTML。这也催生出了对解决方案更通用化的要求,目标就是:**针对任意内容均可“划词高亮”并支持后续访问时还原高亮状态,而不用去关心内容的组织结构**。 下面就来具体说说,如何解决上面的两个核心问题。...

JavaScript
浏览器
综合

## Broadcast Channel 是什么? 在前端,我们经常会用`postMessage`来实现页面间的通信,但这种方式更像是点对点的通信。对于一些需要广播(让所有页面知道)的消息,用`postMessage`不是非常自然。Broadcast Channel 就是用来弥补这个缺陷的。 顾名思义,Broadcast Channel 会创建一个所有同源页面都可以共享的(广播)频道,因此其中某一个页面发送的消息可以被其他页面监听到。 下面就来速览一下它的使用方法。 ## 如何使用? Broadcast Channel 的 API 非常简单易用。 ### 创建 首先我们会使用构造函数创建一个实例: ```JavaScript const bc = new BroadcastChannel('alienzhou'); ``` 可以接受一个`DOMString`作为 name,用以标识这个...

浏览器
特性

> 往期文章: > - [【webpack进阶】前端运行时的模块化设计与实现](https://github.com/alienzhou/blog/issues/19) > - [【webpack进阶】使用babel避免webpack编译运行时模块依赖](https://github.com/alienzhou/blog/issues/18) ## 引言 webpack的成功之处,不仅在于强大的打包构建能力,也在于它灵活的插件机制。 也许你了解过webpack的插件与钩子机制;但你或许不知道,webpack内部拥有超过180个钩子,这些钩子与模块(内置插件)之间的「创建」「注册」「调用」关系非常复杂。因此,掌握webpack内部插件与钩子间的关系会帮助我们更进一步理解webpack的内部执行方式。 「webpack模块/内置插件与钩子关系图📈」:复杂性也可窥见一斑。 ![](https://user-gold-cdn.xitu.io/2018/9/29/16625513129661c2?w=2874&h=1636&f=png&s=2002331) --- 本文的第一部分会先介绍钩子(hook)这个重要的概念与webpack插件的工作方式。然而,熟悉的朋友会发现,这种灵活的机制使得webpack模块之间的联系更加松散与非耦合的同时,让想要理清webpack内部源码结构与联系变得更困难。 所以,第二部分将会介绍webpack内部插件与钩子关系的可视化展示工具📈,用一张图理清webpack内部这种错综复杂的关系。 **可视化工具使用效果图:** ![](https://user-gold-cdn.xitu.io/2018/9/29/16625b730faf4a62?w=800&h=511&f=gif&s=3405680) ## 1. webpack的插件机制 在具体介绍webpack内置插件与钩子可视化工具之前,我们先来了解一下webpack中的插件机制。 webpack实现插件机制的大体方式是: - 「创建」—— webpack在其内部对象上创建各种钩子; - 「注册」—— 插件将自己的方法注册到对应钩子上,交给webpack;...

Webpack
自动化工具

## 引言 前段时间在 github 上看到了一个很“trick”的项目:用纯 CSS(即不使用 JavaScript)实现一个聊天应用 —— [css-only-chat](https://github.com/kkuchta/css-only-chat)。即下图所示效果。 ![](https://user-gold-cdn.xitu.io/2019/5/20/16ad56d29a8af1c6?w=1503&h=870&f=gif&s=5194924) 在我们的印象里,实现一个简单的聊天应用(消息发送与多页面同步)并不困难 —— 这是在我们有 JavaScript 的帮助下。而如果让你只能使用 CSS,不能有前端的 JavaScript 代码,那你能够实现么? > 原版是用 Ruby 写的后端。可能大家对 Ruby 不太了解,所以我按照原作者思路,用 NodeJS 实现了一版 [css-only-chat-node](https://github.com/alienzhou/css-only-chat-node),对大家来说可能会更易读些。 ## 1. 我们要解决什么问题...

浏览器
CSS
服务端

## 引言 下面是一个使用脚手架来初始化项目的典型例子。 ![](https://user-gold-cdn.xitu.io/2019/5/16/16ac081750971790?w=1312&h=533&f=gif&s=1477981) 随着前端工程化的理念不断深入,越来越多的人选择使用脚手架来从零到一搭建自己的项目。其中大家最熟悉的就是`create-react-app`和`vue-cli`,它们可以帮助我们初始化配置、生成项目结构、自动安装依赖,最后我们一行指令即可运行项目开始开发,或者进行项目构建(build)。 这些脚手架提供的都是普遍意义上的最佳实践,但是我在开发中发现,随着业务的不断发展,必然会出现需要针对业务开发的实际情况来进行调整。例如: - 通过调整插件与配置实现 Webpack 打包性能优化后 - 删除脚手架构建出来的部分功能 - 项目架构调整 - 融合公司开发工具 - …… 总而言之,随着业务发展,我们往往会沉淀出一套更“个性化”的业务方案。这时候我们最直接的做法就是开发出一个该方案的脚手架来,以便今后能复用这些最佳实践与方案。 ## 1. 脚手架怎么工作? 功能丰富程度不同的脚手架,复杂程度自然也不太一样。但是总体来说,脚手架的工作大体都会包含几个步骤: - 初始化,一般在这个时候会进行环境的初始化,做一些前置的检查 - 用户输入,例如用 vue-cli 的时候,它会“问”你很多配置选项 -...

综合
自动化工具

## TL;DR - 可以考虑基于HTTP Cache来定义打包维度,将Cache周期相同的script尽量打包在一起,最大限度利用Cache; - 合并零散的小脚本,避免触发浏览器并发请求限制后,资源请求串行,TTFB叠加等待时间; - 注意打包后的资源依赖与资源引入顺序。 ## 1. 引言 性能优化涵盖的范围非常之广,其中包含的知识也非常繁杂。从加载性能到渲染性能、运行时性能,每个点都有非常多可以学习与实践的知识。 优化问题包含方方面面,优化手段也依场景和具体问题而定。因此,本文并不是一个泛而全的概览文章,而是以之前的一次对于业务产品的简单优化(主要是DOMContentLoaded时间)为例,介绍了如何使用Chrome Dev Tools来分析问题,使用一些策略来缩短DOMContentLoaded的时间,提高加载速度。 ## 2. DOMContentLoaded事件 W3C将页面加载分为了许多阶段, DOMContentLoaded(以下简称DCL)类似的有一些 DOM readState ,它们都会标识页面的加载状态与所处的阶段。我们接触最多的也就是 readState 中的 interactive、complete(或load事件)以及DCL事件 简单了解一下它们。浏览器会基于HTML内容来构建DOM,并基于CSS构建CSSOM。两者构建完成后,会合并为Render Tree。当DOM构建完毕后, `document.readyState`...

浏览器
综合

## 引言 babel是一个非常强大的工具,作用远不止我们平时的ES6 -> ES5语法转换这么单一。在前端进阶的道路上,了解与学习babel及其灵活的插件模式将会为前端赋予更多的可能性。 本文就是运用babel,通过编写babel插件解决了一个实际项目中的问题。 > 本文相关代码已托管至github: [babel-plugin-import-customized-require](https://github.com/alienzhou/babel-plugin-import-customized-require) ## 1. 遇到的问题 最近在项目中遇到这样一个问题:我们知道,使用webpack作为构建工具是会默认自动帮我们进行依赖构建;但是在项目代码中,有一部分的依赖是运行时依赖/非编译期依赖(可以理解为像requirejs、seajs那样的纯前端模块化),对于这种依赖不做处理会导致webpack编译出错。 为什么需要非编译期依赖呢?例如,在当前的业务模块(一个独立的webpack代码仓库)里,我依赖了一个公共业务模块的打点代码 ```javascript // 这是home业务模块代码 // 依赖了common业务模块的代码 import log from 'common:util/log.js' log('act-1'); ``` 然而,可能是由于技术栈不统一,或是因为common业务代码遗留问题无法重构,或者仅仅是为了业务模块的分治……总之,无法在webpack编译期解决这部分模块依赖,而是需要放在前端运行时框架解决。 为了解决webpack编译期无法解析这种模块依赖的问题,可以给这种非编译期依赖引入新的语法,例如下面这样: ```javascript // __my_require__是我们自定义的前端require方法...

Webpack
自动化工具