062020.1

在切换至 ubuntu 之后,本来有意打算使用 firefox 作为默认浏览器,毕竟是开源的亲儿子,甚至有想把 firefox 作为常用浏览器的打算。但是在挣扎一段时间之后,还是放弃了。原因有两个:1. 慢,和 chrome v8 比,确实慢。2. 标准支持,和 chrome 相比,还有一些标准不支持,导致我的程序无法运行,而且因为是正则,还没有办法 polyfill。另外,从开发者工具的使用体验上,chrome 的开发者工具显然要优秀一些。所以,最后,只能抛弃 firefox,再投入 chrome。

12:38:37 已有0条回复
082019.12

Ubuntu18初体验

Ubuntu18已经发布一年多了,我一直忍者没升级,因为我挺喜欢原来的桌面风格的。但是因为它老是提示升级,我又有点强迫症,毕竟人要跟上时代,有些变化不得不跟着去适应,就像生活一样,所以,最后,我还是决定冒险升级一下。整个升级过程中有几次交互,我都点了 keep。最后升级完,重启,新的桌面系统,不得不适应一下。经过一会儿的调整之后,得到了我想要的界面,既然使用了 gnome 桌面,那就更像 windows 一些吧。

20:17:40 已有0条回复
032019.12

啥是微前端?

微服务应该很多人都听过了,大概是将一个大的复杂应用,拆分成多个独立的应用,通过 API 接口的方式串联在一起的,后端应用。微服务确实是后端的应用架构。而在前端,不知道是为了赶时髦还是什么意思,类似的概念被称为“微前端”,就是将原本一个完整的应用,通过某种架构形式,拆分为多个独立的应用,在整体层面,又可以将这些独立应用融合在一起,完成应用本身的功能。

形象的举个例子,假如说,你有一个订餐应用,现在要增加一个给外卖小哥用的独立部分,以往的做法,是在原有的基础上,新开一个菜单作为入口,进来之后是独立的模块,为了独立,尽可能和其他模块不产生耦合。在微前端的概念下,这个新的部分,则是一个完整的独立应用,它有一个入口,但是肯定不是在底部的菜单栏中,而可能是在首页的某个按钮区域内,点击进来以后,就像进入一片新天地,所有功能和外部没有任何耦合的地方,全部是自己独立的。没错,你会想到小程序,特别是支付宝首页菜单点进去的小程序。微前端就是这种架构,只不过是针对的web。

在我的直观感受中,微前端就是一个更高层面的路由和应用加载系统。路由就是要确保在已有应用基础上,两个应用可以不打架。当然你可以要求所有微前端应用的团队按照你的这个主体框架的要求来配置路由,但是对于需要复用的微前端应用而言,它不一定只在你一个框架中运行,可能在多个框架中跑,这个时候,没法只遵循你的路由规则。因此,微前端上层框架,首先要解决路由问题。其次要解决的是应用加载问题,一般而言,微前端里面的每一个微前端应用,都是异步加载的,就和小程序一样,当需要使用这个小程序的时候,才会下载下来运行。这和我们现在流行的 webpack 打包的方式完全不同,微前端框架如何去加载和渲染异步的应用,而且还要保证和路由一起工作良好。最后,除了这两大问题之外,还要解决样式冲突、状态共享、路由跳转传参等等问题。这些林林总总的问题凑到一起,OMG,又是一个新趋势……

但不管怎样,随着前端发展趋势,感觉这确实是要面临的一个问题。

12:29:00 已有0条回复
262019.11

使用 @babel/plugin-transform-runtime 的时候遇到坑。这个插件要求我们必须安装 @babel/runtime 系列,根据它的 corejs 参数,我们需要安装 @babel/runtime-corejs3 这种包,但是经过摸索之后我发现这里的 corejs 版本填写的越高,被植入的 polyfill 越多,到最后,打包出来的代码比之前大了很多。原本以为 corejs 版本越高越好。但是现在顿悟了,为了代码体积,放弃 corejs3 直接使用 @babel/runtime。之所以高版本 polyfill 加载的更多,我想是因为标准有一点改动,都会有新的 polyfill 被加入到 corejs 中,这就导致代码越来越多,最终导致原本为了减少代码量而使用的 transform-runtime 现在变成了负担。

17:29:49 已有0条回复
242019.11

占位符历险记

我是占位符,英文名placeholder,在编程领域跑龙套,开发者经常用到我,但我从来不是主角,我一直揣着一本《符号的自我修养》,并梦想有一天可以成为一个故事的主角而给开发者和用户带来快乐。我把我的故事写下来,希望在我的故事里,你可以获得一些乐趣吧。

配置

有一次,我到了一场叫“配置”的剧场里,导演在找一个跑龙套的,因为在这场剧里面,开发者不能直接把密钥写在代码里面,但是在运行时的时候,又要求使用这个密钥,密钥只会呆在独立的服务器里面。导演拿它没有办法,这个时候我毛遂自荐,上去说到:你把我放在本来要写密钥的地方,等构建的时候,再把密钥从密钥服务器里面拉下来,让密钥过来替我。导演拍了我的脑袋,说,你小子还真行。以上构建机,跑了大概10分钟,导演就让我去领盒饭了。

xargs

我灰溜溜串场到命令行的时候,遇到了 xargs,它让我过去帮忙。

ls /xx | xargs -t -I{}  cp {} /tmp/{}

moment.js

我签约了 moment.js,经常在它的剧里面跑龙套,例如:

'YYYY-MM-DD HH:mm:ss'

插值

在我25岁的时候,终于熬出了头,在一类叫“插值”的戏里,几乎每一场戏都有我,虽然每次出场我都被化妆师重新化妆。

<div>{{ text }}</div>
<div>{{ dog }}</div>

保持替换

真正让我在演艺界找到自己价值的,是在一场叫保持替换的电影里。在这场电影里,一个字符串中的某些字符要被替换,但是具有特殊样子的字符不会被替换。我不是这些特殊样子的字符,我在它们的变化过程中扮演了极其具有技术性的一环。

DD\D 要被替换为 44D, 因为最后一个D前面有一个\,所以这个D不能被替换掉。

刚开始导演没打算用我,直接使用正则 ?<! 就能实现。后来发现,浏览器不支持,于是不得不请出我这个大神。一开始,我给出了非常简单的方案:

先把 \D 改为 ___4___,等所有的 D 都被替换为 4 之后,又把 ___4___ 替换为 D,这样就可以了。

但是,这样不行,因为用户可能在字符串里面本身就包含了 ___4___ 这个字符串。我请出来深山里面的 unicode 来帮忙:

先把 \D 替换为 '\uddd1', \d 替换为 '\uddd0' 这种形式,这样,这些字符就是用户很难输入的了,几乎不会输入这种字符。后面再把这些字符给替换回来。

这样,我完美装逼,导演给我颁了一个最佳技术奖。

未完待续。。。

我的故事还在继续,你有你的故事么,跟我分享一下呗

17:32:29 已有0条回复

iOS Safari浏览器上overflow: scroll元素无法滑动bug解决方法整理

222019.11

一篇文章发布了两年了,阅读量仍然很飙,可见好文章不会过时,大家都知道我是写前端,区块链我一窍不通啊老铁

14:26:00 已有0条回复
212019.11

真正说服我使用 react hooks 的,是 react blog 里面提到的,使用 class component 打包时无法对 class 的属性方法进行优化,而使用 hooks 则可以将代码压缩到极致。这一点让我瞬间服软了,没有无论别人说的多么花哨,不足官方一句话让我释然。有人会说 hooks 是趋势是未来啥的,但是,实际上,hooks 比 class 复杂和难理解多了,而且随着业务逻辑的增长,一个 function 里面将会写出越来越多的代码,越来越复杂,让你无法维护。而实际上,在运行时,两则的差别不是特别大,都没有性能上的优劣。但是,唯独代码压缩这一点打动了我,真的。

23:19:48 已有0条回复

JS 如何获取高精度的时间戳

在js项目中,有的时候,我们希望获取比Date.now()更高精度的时间戳。这篇文章简单介绍了js时间精度的来龙去脉,这里就不再赘述了。现在,我们来介绍一下在浏览器中如何获取更高精度的时间戳。

在浏览器中有一个 performance.now() 的接口,它表达了从页面加载到执行该语句之间的时间间隔,是一个衡量值。页面加载结束时间通过 performance.timing.navigationStart 获取,两个值相加,就可以得到执行 performance.now() 的具体值,该值比 Date.now() 精度要高。

js中获取高精度时间戳

你可以看到,它的结果和 Date.now() 结果是一致的,只是精度更高,经过四舍五入之后是相等的(忽略js执行时间带来的微小误差)。

但是,在js中有一个不好的事实,浮点数运算会带来不可预料的误差。

单独执行 performance.now() 可以得到精度更高(小数点后面9+位,纳秒)的时间戳,但是,两个值相加之后,就只剩下毫秒数值。虽然这个精度其实已经够我们用了,但是我们如果非得要得到最高精度的时间戳,可以先将两个数值字符串化,在利用我写的来进行相加。

10:03:38 已有0条回复
112019.11

前端获取IP

在前端js代码中获取用户的IP地址:

export function getUserIP() {
  return new Promise((resolve, reject) => {
    const RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
    const pc = new RTCPeerConnection({
      iceServers: []
    })
    const noop = function() {}
    const localIPs = {}
    const ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g
    const iterateIP = (ip) => {
      if (!localIPs[ip]) {
        resolve(ip)
      }
      localIPs[ip] = true
    }

    //create a bogus data channel
    pc.createDataChannel('')
    // create offer and set local description
    try {
      pc.createOffer(function(sdp) {
        sdp.sdp.split('\n').forEach(function(line) {
          if (line.indexOf('candidate') < 0) {
            return
          }
          line.match(ipRegex).forEach(iterateIP)
        })
        pc.setLocalDescription(sdp, noop, noop)
      }, function(sdp) {
        reject()
      })
    }
    catch (err) {
      reject(err)
    }
    //listen for candidate events
    pc.onicecandidate = function(ice) {
      if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) {
        return
      }
      ice.candidate.candidate.match(ipRegex).forEach(iterateIP)
    }
  })
}

需要用到webRTC,如果不支持该接口,那就无法获取。

16:54:19 已有0条回复