我的技术和生活

  • GitChat: 使用 webpack 开发企业官网

    GitChat: 使用 webpack 开发企业官网

    最近我厂官网改版,我尝试用 Webpack 重建了开发工具链,效果不错,配置代码少了很多,逻辑更加简单清晰。我觉得值得拿出来分享一下。

    文章已经发布,慢慢写了将近5w字,干货很多,覆盖面很广,欢迎大家前去阅读:升级工具链吧!使用 Webpack 开发企业官网。感谢大家的支持。

    交流应该会通过直播进行,暂定7月中吧,斗鱼直播间:douyu.tv/meathill。

    (更多…)
  • Intersection Observer 笔记

    Intersection Observer 笔记

    有时候我们需要根据一个元素的位置来修改它的属性,比如图片的 lazyload,比如视频离开视窗之后停止播放。

    以前的做法通常是:

    1. 侦听 window.scroll 事件
    2. scroll 触发,遍历每个要检查的 DOM Element,执行 .getBoundingClientRect() 取出它的 widthheighttopleft,然后根据 viewport 和宽高 scrollTop scrollLeft 计算对象是否应该出现
    3. 然后做处理

    这样做会产生一些问题:

    1. 如果漏掉移除侦听器,可能造成内存泄漏
    2. 不同组件之间,很难共享侦听器
    3. 每一次都计算所有 Element,成本很高

    于是现在我们有了 Intersection Observer,专门用来观察一个 Element 是否出现在 viewport 或者父容器里。它可以很好的解决这些问题:

    1. API 更清晰
    2. 逻辑原生,速度更快,消耗更少
    3. 可以自定义阈值,更加可控

    关于 Intersection Observer 的详细知识,建议大家认真阅读 MDN – Intersection Observer,我就不抄文档了。

    使用 Intersection Observer 大体上分为三步:

    1. 声明一个 Intersection Observer 实例,这一步最关键的是要确定显隐依据哪个元素,也就是 root
    2. 将需要检查的元素加入侦听队列
    3. 在回调函数里处理元素状态

    写成代码大概是这样的:

    // 声明一个实例
    // 因为我的视口即当前 viewport,所以这里不需要 `options`
    const observer = new IntersectionObserver(entries => {
      // 遍历所有实例,如果它显示出来,即 intersectionRatio 显示比例大于 0
      // 那么就让它 `dispatch('visible')`
      entries.forEach(({target, intersectionRatio}) => {
        const event = new CustomEvent('visible', {
          detail: {
            isVisible: intersectionRatio > 0,
          },
        });
        target.dispatchEvent(event);
      });
    });
    
    // 然后可以在 Vue 里侦听这个事件
    export default {
      template: '<div @visible="onVisible"></div>',
      mounted() {
        observer.observe(this.$el);
      },
      beforeDestroy() {
        observer.unobserve(this.$el);
      },
    }

    Intersection Observer API 公布一段时间之后,又进行了升级,现在支持更丰富的参数,比如我们可以定义一个函数去判断更复杂情况下的显示状态。不过大部分场景下,我们并不需要很精准的判断,所以我觉得这个只是保障选择的机会。


    参考阅读:

    Proposed Updates for Intersection Observer

  • wget 笔记

    wget 笔记

    抓取整站

    wget -r https://target.site/
  • Node.js 里使用 Promise 的小技巧

    Node.js 里使用 Promise 的小技巧

    Node.js 8 的时候,引入了 util.promisify() 方法,可以把 node-like 的回调函数改造成返回 Promise 实例的方法,我当时还写了篇博文《Node.js 8 中的 util.promisify》小记。

    所以我现在写 Node.js 基本都是这种风格:

    const fs = require('fs');
    const {promisify} = require('util');
    
    const readFile = promisify(fs.readFile);
    const writeFile = promisify(fs.writeFile);

    刚才在推上看到两位大佬聊起这个话题,发现可以这么搞:

    去查了一下 Node.js 的文档,发现这是 v10 新增的 API,升级之后即可使用。

    我比较喜欢这么做:

    const {promises: {readFile, writeFile}} = require('fs');
    
    (async () => {
      let content = await readFile('1.txt', 'utf8');
      content = doSthToContent(content);
      await writeFile('2.txt', content, 'utf8');
      console.log('ok');
    })();
  • Chat Idea:扫雷网页版实战

    Chat Idea:扫雷网页版实战

    最近最常玩的游戏是扫雷。年纪大了,干什么时候都先考虑成本,游戏也是如此。扫雷的成本最低,倒不是说购买成本,而是启动、游戏、退出之类的成本。

    可惜的是,经典版扫雷已经从 Windows 10 里移除了,现在只能通过 Windows 应用商店装一个很复杂的扫雷游戏,花样多了很多,却并不好玩。所以我现在多半玩网页版。

    玩着玩着,出于程序员的本能,我就开始考虑如何写这个游戏,逻辑不算复杂,功能点也不多,好像蛮适合做成“实战派”教程的,比如用 Grid 写界面,项目结构就用 Vue CLI 3 吧,然后部署的话前端纯静态就够了。

    那么就愉快的决定了吧,把这个项目做出来,把中间需要的知识,用到的技能、工具,可能会遭遇的问题记下来分享出来,写成一篇文章,分享出去。读完整篇文章,你将学会:

    1. 使用 Vue CLI 3 搭建项目
    2. 使用 CSS Flex + Grid 完成页面布局
    3. 扫雷游戏的逻辑
    4. 使用 Vue 完成游戏逻辑
    5. 记录成绩
    6. 部署和分享

    目标读者:

    1. 初级开发者,能看到一个项目的成型
    2. 希望了解现代化前端框架、工具链
  • Chat idea:记一次 Firefox 下 Vue 带来的性能危机的解决

    Chat idea:记一次 Firefox 下 Vue 带来的性能危机的解决

    前两天遇到一个问题:我厂的一个产品在 Firefox 下,可能发生因为 CPU 占用过高而卡死的情况。这个问题在测试环境不复现,在 Chrome下基本上也不会复现。

    因为我厂老板是这个产品的主要用户,这个 bug 让我倍感压力,但一直没有解决它的好办法。终于有一天,在某台生产机上调试另外一个 bug 的时候,我终于发现了稳定复现这个 bug 的方式。

    接下来就是几个小时的 debug,然后发现问题所在,然后解决问题,然后发现解决方案不理想,于是寻求新的解决方案,然后找到新的 API,最终彻底的解决这个问题。

    接下来我就分享这个过程,读完整篇文章当中你将学会:

    1. 使用开发者工具查找性能问题
    2. 不断切分,缩小问题范围
    3. 理解 Vue 响应式原理分析问题根源
    4. 修复问题并验证
    5. 新的解决方案 Intersection Observer
    6. 解决问题并上线

    目标读者:

    1. 中级开发者
    2. 熟悉原生 JS

    大家觉得这个 idea 如何?请留言告诉我。不出意外的话这将是我下个月的 gitchat 内容。


    有同学在 Drift 里留言,这里更新回答一下:这篇文章最后没写,因为当时 GitChat 的编辑不感兴趣,所以就放弃了。将来有机会会写。

  • Stylus 实现 `content: “5”`

    Stylus 实现 `content: “5”`

    一般来说 Stylus 对属性是直接替换的,所以正常来说下面的 stylus

    $a = 10
    
    .foo::before
      content $a

    会编译成:

    .foo::before {
      content: 10;
    }

    这样是非法的,10 不会渲染出来。如果想让它渲染出来,必须用字符串。如果只有一个值,那就好办了,直接 $a = '10' 就好。但如果在循环里,就比较麻烦,此时,可以用 '' + 10 转换成字符串,或者使用 s(template, value),以下两种方式是等效的。

    // 注意运算顺序哦
    .foo
      for n in 1..5
        &:nth-child({n})::before
          $str = '' + (5 - n)
          content $str
    
      for n in 1..5
        &:nth-child({n})::after
          $str = 5 - n
          content s('"%s"', $str)

  • 最近折腾 @babel/preset-env 的一些小心得

    最近折腾 @babel/preset-env 的一些小心得

    近来厂里的项目越来越多,代码共享必不可少。我现在采取的方案是:

    1. 把公共组件拿出来,开一个新仓库
    2. 使用 webpack 进行打包编译,libraryTarget: 'umd'
    3. 将打包编译的代码一起提交到仓库
    4. 使用 npm i <owner>/<repo> -S 安装依赖,因为我厂的仓库均为私有,所以不能发布到 NPM

    这套方案简单好用,实操效果良好。接下来我希望优化打包结果,于是研究了打包配置项,下面是我的一点心得。

    [2021-04-07] 更新:

    我们目前采用 GitHub Registry 托管私有 packages 的方案,比上面直接安装仓库的方案更好,想了解的同学可以看 使用 GitHub Registry 托管私有 NPM 源

    (更多…)
  • OpenResty Inc. 招聘后端工程师

    OpenResty Inc. 招聘后端工程师

    OpenResty Inc 中国大陆子公司诚邀后端工程师/系统工程师加入。希望能和对后端技术有激情、有想法、有追求的年轻人一起构建 OpenResty Trace、OpenResty Edge、OpenResty QA/Showman、OpenResty CI 等全新一代的企业级软件产品,实现“机器编程”、“机器调试”、“机器测试”和“机器演示”的宏伟蓝图。

    (更多…)
  • GitChat:从 jQuery 里学习设计模式

    GitChat:从 jQuery 里学习设计模式

    文章已完成: https://gitbook.cn/gitchat/activity/5ccedbcfe5bb505613f45186

    本篇文章通过 jQuery 中令人喜爱的特性,介绍了五种设计模式,包含范例代码,使用场景等。在线交流会在6月2日晚8:30开始,地点是我的斗鱼直播间,欢迎大家光临。答疑优先级为:本文相关问题 > 设计模式相关问题 > 其它技术问题 > 职场问题 > 职业发展问题。

    本文内容将在交流会两周后解锁。现在起,欢迎已购读者在 Git Chat 读者圈 跟我互动。

    再次感谢大家支持。今年我会在 GitChat 平台上多发内容。也欢迎大家提出你们想看的内容。我的内容创意都在 分享 分类下,欢迎大家提出意见和建议。

    (更多…)