分类
html

解决诡异的 Chrome 自动完成问题

上周末客户突然报告了一个奇怪的 bug:删除用户时,会自动进入搜索结果页。我在我本地试了一下,100% 复现,相当诡异。经过仔细观察,我发现点击删除用户的按钮时,地址栏会发生变化,在新的路由下,会搜索当前用户:

删除用户时的截图

反复重试之后,我认为:是浏览器自动完成的锅。因为删除用户的操作非常敏感,所以我们要求管理员必须输入密码作为校验。而这个界面与常见的用户登录界面非常相像,所以浏览器自作聪明,找了一个 它认为是 用户名的地方填入了用户名,而这个文本框刚好是全局搜索的搜索框:

如图可见搜索框的位置

当其中的内容发生变化时(也即触发了 change 事件),就会跳转到 /search?{key}={query},然后开始搜索。

问题找到后,接下来进入修问题时间。由于是浏览器的锅,Web 前端难以直接触及,所以很难修。经过反复艰难的 Google,终于在这个页面找到了答案:https://support.google.com/chrome/thread/9498749?hl=en(3楼),原来 autocomplete 不止有 onoff 两个可选值,还可以是 usernameemail、或 password,等。(详见 MDN The HTML autocomplete attribute。)于是我尝试给真正的 username 输入框加上 autocomplete 属性,果然问题解决了。

看来以后有时间得再研究一下 autocomplete 属性了,说不定能解决之前为了防止自动补全而做的各种 hack。

分类
npm

几步简单的操作解决 `npm audit` vulnerabilities

NPM 是 JavaScript 生态最重要的组成部分,我们的项目中会大量使用 NPM 安装第三方包(安装后就称为“项目依赖”)解决问题。这些第三方包也会带来他们的依赖,最终一个项目里可能安装成百上千个依赖。

有道是:没有完美的代码,代码里一定藏有隐患。所以用的依赖多了,其中有问题的概率也提升了,三五不时的,npm 就会提示我们:found N low/medium/high severity vulnerabilities

npm 提供命令 npm audit fix,理论上可以修复这些隐患,但在实际操作中,以我的经验来看,并不容易生效。我猜测可能是因为依赖间的复杂关系,想彻底解决并升级不太容易。所以我一般是这样做的:

分类
工具

推荐网页 IM:Drift

可能有些同学注意到了,最近两个月,只要打开这个博客并且稍微浏览一会儿,右下角就会弹出一个聊天框。此时读者就可以跟我聊天,如果我当时在线(打开了管理端),就能看到消息并且实时回复;如果我不在线,可以上线后再回复,读者下次回到博客时,也可以看到消息。

这个工具就是 Drift,它本质上是一个面向商家的网页 IM,支持匿名聊天,方便客户与商家交流。有点类似淘宝旺旺,只不过它可以嵌入任意网站。

实际上我是帮我厂试水,装上之后还真的有人用它咨询问题,然后聊了几句,各方面体验都不错。就很快实装到我厂官网了。

上线之后表现很好,工作日期间每隔一两天就会有人来咨询,而且接下来的进展也都比较理想,大部分可以发展到试用阶段。对比过去几年“联系我们”的邮箱,两者在接待客户方面真是天壤之别。

不过 Drift 也有不少小毛病,比如:因为网站在国外,所以国内的启动速度比较慢;静态资源的缓存设置也有问题,导致每次加载都要很久(我都想去给他们调 CDN 配置了……)。国内的同学可以考虑用去哪儿的 StarTalk,不过从架设难度上比 drift 难用很多、功能弱很多、界面丑很多……

总之,在网页上添加客服 IM 对增加客户有很大帮助,建议大家有机会都搞一下。

分类
css

CSS 网页保持全屏并自动伸长

其实是个小需求,以前也搞过很多次,没想到前几天被坑了一下,记一笔。

以前,如果想要页面在内容任意多的时候都能占满浏览器,可以简单设置:

html,
body {
  height: 100%;
}

但是这样设置,在 Safari 浏览器上,会将 <body> 固定为窗口高度,如果内容多,就会被底部挡住内容。解决方案是 body 高度用 min-height:100%

如果是三行一列的结构,即上面是导航条,下面是脚部,中间随内容自适应,可以用:

body {
  display: flex;
  flex-direction: column;
}

这个时候,不能用 flex-basis,在 Safari 上会失去弹性,也要用 min-height。所以,最终样式大概就是:

html {
  height: 100%;
}

body {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

#nav {
  height: 4rem;
}
#bottom {
  height: 10rem;
}
#content {
  flex-grow: 1;
  min-height: 40rem;
}

另外,因为基本只有桌面浏览器需要这个功能,所以可以考虑加一个 @media (min-width: 576px) 做限制。

分类
http

解决跨域问题笔记

跨域问题常遇常新,每次都觉得再也不会有问题了,结果过几天又会掉进新坑。

因为种种原因,最近一个项目需要跨域请求 API。然后就随手设置了一下,结果 GET 没问题,POST 就不行,很明显是撞到跨域墙上了。

最后发现原因:

  1. 我们启用了 basic auth 验证用户身份
  2. OPTIONS 也会被要求验证
  3. 预请求失败,后面的正式请求就不会发出

趁着还没忘,总结一下跨域的处理过程:

  1. 首先,熟读《MDN HTTP访问控制(CORS)》
  2. 跨域时,复杂请求(除 HEADGETPOST) API 需要返回 CORS 头
  3. 发起复杂请求前,会发送一个 preflight 请求,也就是 OPTIONS,很多坑都在这个请求上
  4. OPTIONS 是浏览器自动发送的,不受我们控制,在开发者工具的 Network 面板里也看不到。我们经常需要模拟它,检查返回是否符合预期。请求头在后面。
  5. OPTIONS 无法处理 Basic auth,如果开了的话,要做特殊处理
  6. 需要返回 Access-Control-Allow-Origin 允许跨域的域名,简单点可以写 *,但如果要上传 cookie,则必须写明域名,且只能是 一个 域名
  7. 所以如果有多个域名要跨域访问 API,需要在服务器端判断来源,并返回不同的域名
  8. 如果要上传 cookie,需要在请求时声明 withCredential: true
  9. 服务器还要返回许可的方法,即 Access-Control-Allow-Methods: GET, DELETE, PATCH 等,让浏览器判断
  10. 如果前面都通过了,浏览器才会发送正式请求。如果正式请求失败,则看不到任何返回。

测试 OPTIONS 请求头

OPTIONS /resource/foo 
Access-Control-Request-Method: DELETE 
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.bar.org
分类
vue

Vue 2020 年路线图,Vue 3.0 计划于 Q2 发布

昨天 Vue 团队更新了 2020 年的路线图,里面包含了很多 Vue 3.0 的信息。建议大家一定要看原文,地址在:https://github.com/vuejs/vue/projects/6。下面我结合自己的理解翻译一下:

FAQ

问:3.0 啥时候能好?

答:请往后看。另外请注意,这些日期仅供参考,我们团队的首要目标是发布生产级别的高质量代码,不是赶 deadline。

问:3.0 里都有啥变化啊?

答:请自行翻阅最新的 RFC。另外,也要注意核心团队提交的 RFC 草案。

如果某个 RFC 里包含破坏性变更,那么里面一定会有“升级策略”章节,讨论迁移问题。

对于现在的 2.x 用户,我们会提供:

  • 迁移向导
  • 能够兼容 2.x 的兼容性版本(如果能兼容的话),并且对该升级的地方给出提示和升级建议
  • 命令行迁移工具
    • 自动升级能升级的代码
    • 不能自动升级的,扫描出来提示手动升级

问:我是新人,我现在该学 Vue 2.0 还是等 3.0?

答:如果你刚刚开始学习框架,那么应该开始使用 Vue 2。我们没有对 Vue 3 进行巨大的重新设计,所以大部分 Vue 2 知识仍将适用于 Vue 3。 如果你打算学习框架,没有必要等待。

如果你要为某个生产级别的项目选择技术栈:

  • 如果项目需要立即动工:我们仍然建议使用 Vue 2,以便获得完整的、框架级别的支持。 但是,也请留心 3.0 中即将发生的更改,不要使用将被移除的功能,最好也不要使用与 Vue 2 深度耦合的第三方依赖。
  • 如果项目可以等到 Q2 末:那我们建议你等等,用 3.0。

问:以后 2.x 会咋样呢?

答:接下来会有一个小版本(2.7)更新:

  • 将兼容的 3.x 功能反向移植回 2.x
  • 对 3.x 弃用的功能发出警告

这是 2.x 最后一个小版本,并提供长达 18 个月的 LTS(长期支持)。即使在 LTS 结束之后,我们也会继续提供重要的安全更新。

问:Vuex 方面有什么计划么?

答:一方面,我们正在开发Vuex(4.0)版本,其 API与 当前版本(3.0)完全相同,但与 Vue 3 兼容。我们力求向下兼容,让用户可以在 Vue 3 项目中继续使用现有 Vuex 代码。

另一方面,我们也在尝试新的设计,更多的利用 Vue 3 的响应式 API,也让 Vuex API 不那么冗长。 这个新版本暂定为“ vuex-next”,也就是 5.0。 眼下,我们只是在进行早期探索,最早也要到 2020 年第三季度才会发布。

2020 一季度计划

  • 3.0 SSR
  • 3.0 迁移
    • 升级向导(施工中)
    • 2.x 兼容版本
    • 迁移工具
  • 3.0 框架
    • router(施工中)
    • Vuex(施工中)
    • 测试工具(施工中)
    • JSX babel 插件(施工中)(我以为不会有这个东西了呢)
    • CLI
    • Devtools
    • 其它(虽然最后三个没标施工中,不过我觉得多半也是在施工中咯)
  • 3.0 beta
    • Q1 末发布!
    • 3.0 核心现在其实已经完成了,我们希望 API 到这个时候也能稳定下来。
    • 我们还需要更多的时间才能更新周边的库和工具。 如果您的使用场景对 router 和 vuex 没有硬性要求,这个时候就可以开始使用 3.0 了,但最好是非关键性应用程序。

2020 二季度计划

  • 继续之前未完成的 3.0 框架工作
  • 季度中,发布 3.0 RC
    • 冻结 API,不再有重大变化。进入 RC 之前,所有涉及到重大变更的 RFC 都要定案。
    • 全家桶能够和 3.0 版本协同工作。
    • 3.0 版本就绪,此阶段基本可用。仍然会有一些小错误和框架集成问题,在 RC 阶段都会慢慢被解决掉。
  • 3.0 发布管理
    • 回归测试
    • 自动化每晚发布
    • 正式确定版本生命周期
  • 3.0 IE11 兼容性版本
  • 3.0 官方正式版

2020 三季度计划

发布 2.7 版本

  • 反相迁移 3.x 功能到 2.x
  • 对 3.x 中弃用的功能发出警告
  • 2.x 最后的小版本,LTS
分类
nodejs

解决“[ERR_PACKAGE_PATH_NOT_EXPORTED]: No “exports” main resolved”

周末例行升级系统,今天打开项目,npm run dev,就报这个错误。检查代码,没变化,依赖也没变化。因为错误位置在 main.js,尝试给它加上 exports,无果。

Google 之,发现一个非常新的 issue:https://github.com/babel/babel/issues/11216,3天前,来自 @babel/babel 仓库,多半是了。

点进去一看,原来 node.js 从 13.10.1 之后,对 package.json 里的 exports 属性解读出现问题,继而导致 Babel 抛出错误。最简单的解决方法就是升级 Babel 到 7.8.4。

升级后问题解决。

分类
js

使用 Proxy 创建有魔术属性/方法的类

前几天在 SF 回答了这个问题:如何使用proxy,如何在内部拦截get方法,然后翻了翻以前写的博客:使用 Proxy 添加魔术属性/方法,发现上次写完代理对象就停笔了,所以今天补全一下:创建有魔术属性/方法的类。这样就比较完整了。

JavaScript 构造函数的特点

ES6 增加了 class 关键字,梳理了面向对象的语法,现在我们可以这样定义一个类:

class Person {
  constructor(name) {
    this.name = name; 
  }

  hello() {
    return `Hello, my name is ${this.name}.`;
  }
}

如果你有其它面向对象语言的经验,应该很容易理解这段代码。

不过 JS 的构造函数特别,它支持 return 一个其它对象,作为 new SomeClass() 的结果。(如果不 return 或者 return 一个空对象,那么 new SomeClass() 得到的就是 SomeClass 的实例。)

也就是说,原则上,我们可以这么做:

class Person {
  constructor(name) {
    this.name = name;
    return {name: 'Meathill'};
  }
}

const person = new Person('张三');
console.log(person.name); // 'Meathill'

结合 Proxy

理解了上一节的内容,我们就很容易得到这样一个类:

class Person {
  constructor(name) {
    this.name = name;

    return new Proxy(this, {
      get(target, property) {
        if (property in target) {
          return target[property];
        }
        console.warn('Sorry, I can't do that.');
      }
    }
  }
}

在这个类的构造函数里,我返回了一个 Proxy 实例,代理了对真正 Person 实例的访问。当访问的属性/方法在实例上时,就返回需要的属性/方法,否则的话,输出警告。

实际上,Proxy 的 getset 的功能远不止如此,上面的代码只是一些演示。

用途

魔法属性/方法主要有以下用途:

  1. 对象 a 要使用一部分对象 b 的功能,但是又不方便直接用原型链。比如上一篇文章的场景,我提供类 VElement 作为接口,实际完成工作的是另一个沙箱中的 Element。
  2. 不知道会怎么访问对象,希望所有访问都照顾到。
  3. 希望捕获到对对象的修改,也就是 Vue 3.0 的核心修改。

Vue 3.0

Vue 1.x & 2.x 期间,都在使用 ES5 的 Object.defineProperty 拦截对对象的修改,实现响应式。这样的做法看起来很神奇,给 Vue 带来了巨大的成功。但是这样做也有坏处:

  1. 声明实例时需要很多预处理工作,而且数据量越大处理的时间越久
  2. 不支持某些数组操作
  3. 不支持其它数据类型,比如 Set、Map
  4. 不支持后续的数据观察

使用 Proxy 之后,以上问题全部都迎刃而解,甚至,因为 Proxy 是原生 API,性能表现更好,取得了内存减半、速度加倍的效果。

想了解更多 Vue 3.0 的新特性,可以去看我在 SF 的分享:迎接 Vue 3.0。(注:这是免费广告,我不会从新购用户取得收益。)


参考文章:

Constructor, operator “new”(构造函数和操作符 “new”)

分类
学习

从 uiprint.co 聊一聊“练习作品”

我一直有做 Side project 的心,经常想实践一些 idea,不过多数止步于画原型。

虽然我常年购买 Adobe Creative 和 Sketch,也经常使用 Photoshop、XD、Sketch 切页面,不过并不擅长真刀实枪的“创作”。一旦涉及到画原型,进度就会很慢,经常让我的 indie hacker 之路止步于此。于是我就想,要不还是画在纸上。

然后我就找到这个网站:uiprint.co。上面有很多做好的 PDF,直接下载打印,就可以得到很好的设计底图,然后连连画画(上面有网格点),就能画出很棒的设计原型。这样做最大的好处是,设计思路不会中断,可以专注于产品逻辑。

为了方便大家理解,我截了一张图

接着聊聊“练习作品”。

我经常逛技术论坛和问答区,常常看到有同学提问:“自学前端,能仿着教程写出 demo,接下来该怎么做?”,或者“应届生,该写什么项目经历?”

面对这种问题,我都会建议他:

  1. 不要仿做 demo,要做有人用的东西
  2. 认真地进行推广、迭代
  3. 解决遇到的各种问题

模仿写 demo,意味着作品没有得到真正的检验。没有职业经验的新人,他眼里的“也做得出来”、“挺好”,在商业产品里多半连及格都算不上。满足于做这样的作品,没有办法获得真正的提升,写到简历里,也没什么价值。

接下来的问题是:做什么?

首先,不要贪大求全。你当然可以做电商网站,或者自己从头写个博客、论坛,看起来很高端,但实际上既耗时耗力,也没有什么价值,因为没有人真的会用。

其次,要把眼界放宽。互联网已经是一种基础设施,大部分行业都能被互联网赋能提升。与其照抄千篇一律的 todo-list,电商网站首页,好好想想自己周围的人需要什么,做一个他们会用的东西更有价值。

uiprint.co 就是一个很好的例子:

  1. 它本身很简单,就是网页+可以下载的 PDF,纯静态,开发成本维护成本都很低。即使是前端新人,也不太会遭遇无法攻克的技术难题。
  2. 有价值,是 Product Hunt 日榜第一,所有需要做产品设计的人都可以获得帮助。不断有人用,作者就有不断更新的动力,也有不断升级的需求,比如视觉效果调整、访问量统计、添加内容的后台等等。
  3. 就更不用说这个网站本身可能带来的价值

其实我们身边类似这样的机会并不少。比如 2010 年的时候,智能手机刚刚兴起,就有一个人告诉我,他想做一个应用,告诉你在北京上海这样的大城市怎么做地铁,哪站有厕所,哪站车门开在那边、等等。

这样的项目坚持下来,虽然未必有经济收益,但一定能获得很多有价值的项目经验,对入行、对找工作,都会有很大帮助。


总结一下:

  1. 想自学、想提升自己、想找工作,做项目一定要做有人用的东西,不要模仿做 demo
  2. 选择题目不需要特别大,也不需要纯互联网,有人用 是首要原则
  3. 接下来就是坚持,坚持开发、坚持维护、坚持推广

希望对大家有帮助。

分类
flarum

Flarum 添加导航并实现 i18n

Flarum 是一个开源论坛软件,基于 PHP Laravel 打造,外观很好看,功能也不错,一直想试一试。近期我厂要建社区,在我的强烈建议下,就选用了它。

Flarum 诞生很久了,现在的版本是 0.11.1-beta,还是测试版。官网也反复强调,不要把 flarum 用在生产环境,因为一切还不稳定。——这点从文档也能看出来,有些范例代码没法跑在最新版软件上。

换言之,坑比想象的多。经过将近两周断断续续的折腾,踏空很多次,完成了一些些小东西。接下来分享一下,也当给自己做笔记了。