软件技术学习笔记

个人博客,记录软件技术与程序员的点点滴滴。

UniApp小程序分包异步化–预告

经过10多天的努力修改UniApp与新增Webpack插件,终于实现ES6语法的JS异步化、Vue组件异步化。

用法如下:

// pkg-b/b.js
const myFunc = async () => {
  const { yourFunc } = await import('@/pkg-a/a.js');
}


// pkg-d/d.vue
// Vue组件经过特殊处理,不需要 import(). 缺点是不兼容h5动态import,后续有空再优化.
import YourComp from '@/pkg-c/c.vue';

export default {
  components: {
    YourComp
  }
}

继续阅读→

React Polyfill ReplaceAll

最近使用Create React App创建一个APP,使用react-app-polyfill/stable完成Polyfill,但是,发现string.replaceAll()函数一直没有polyfill。打开core-js/stable/index.js,发现已经包含了require('../modules/es.string.replace-all')。第一次遇到这种情况,相对懵逼。

经过一番的查阅,最后在babel官网看到一条消息(https://babeljs.io/docs/en/babel-preset-env#corejs):

By default, only polyfills for stable ECMAScript features are injected: if you want to polyfill proposals, you have three different options:

* when using useBuiltIns: "entry", you can directly import a proposal polyfill: import "core-js/proposals/string-replace-all".
继续阅读→

Nginx Log前端上报的错误

使用Nginx搭建前端静态资源服务时,有时想在服务端收集一些前端的严重错误。如果不想搭建或引用其它服务来处理上报的错误日志,可以将简要的错误信息放到HTTP Header中,然后使用Nginx的 $http_xxx 变量打印到 access_log 中。在没有新增其它Nginx模块时,Nginx是无法直接访问HTTP Body中的内容,但是Header中内容可以直接访问。

Nginx配置:

log_format  reportError escape=none  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      '"$http_fe_href" "$http_fe_error"';

server {
    location = /api/reportError {
        # Methods Limit
        limit_except POST {
          deny all;
        }

        expires epoch;

        ### Log the error
        access_log  /var/log/nginx/access.log  reportError;
        return 200;
    }
}
继续阅读→

vConsole兼容Android与Polyfill

目前,在低版本的Android模拟器中,比较稳定的 vConsole 版本有:3.3.4 与 1.0.x。

vConsole依赖MutationObserver,在Android 4.4及以上版本中不需要Polyfill。但是,在Android 4.3中,需要引入MutationObserver Polyfill,勉强可以打开vConsole,如下:

<link href="https://cdn.bootcdn.net/ajax/libs/normalize/8.0.1/normalize.min.css" rel="stylesheet">
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?version=3.46.0&features=default%2Ces6%2Ces7%2CMutationObserver"></script>

总的来说,Android 4.3 与 4.4 浏览器之间的差异还是比较大,见 Can I use

继续阅读→

微信小程序插件不适合快速迭代

前段时间,我们开发一款toC的小收据,选择微信小程序插件的方式进行开发。起初的目的是避免主程序过大、容易被别的小程序集成,做新的独立APP时避免重复开发,也选择团队中大部分人熟悉的Taro + React技术栈。

但是,在产品迭代过程中,隔三差五就需要改动这个小收据插件,麻烦就出现了。要发布新功能时,需先插件提审,插件通过之后在主程序中更新插件的版本号,最后才是主程序提审、发布,发布流程漫长。

继续阅读→

SSR超时回退到CSR

去年的时候,为了提升用户首屏显示时间,我们使用React SSR。但是,前段时间用户访问量比较大,发现用户导航之后首屏很久才出来。查看链路追踪,发现后端接口的响应时间远大于平常。

SSR的目的是为了让用户更快地看到内容,但是后端接口超时就白屏很久。为了解决这个问题,在SSR请求后端接口时,也启动一个超时Promise。如果超时先返回,立刻给用户返回CSR HTML模板,确保用户尽快能够看得界面。还没有数据的Loading界面,总比一直白屏好。

继续阅读→

NodeJS网络调用链优化

为了提升用户体验,前端首屏使用NodeJS SSR。为了容易观测多个环境NodeJS层的网络调用链与性能,我们加入了Jaeger链路追踪,这也是微服务开发中常用的手段。

通过Jaeger UI观察,我们很容易发现首屏SSR与API转发有以下问题:

  1. 多段接口依次执行,有先后次序依赖,没有发挥并发请求的优势。
  2. 未区分用户类型,有多余的网络请求。
  3. 转发的API请求,也请求多余的用户信息等。

如果使用以前打日志的方式,缺少可视化的分析手段,定位问题的周期比较长。处理以上的问题之后,首屏SSR与API转发的网络性能提升50%,给后端的请求数分别减少3/8与3/4。在并发量比较大的情况下,可以很大程度上减轻服务器的压力。

目前,用户量比较少,在云上后端接口返回在50ms时,首屏SSR可以在100ms内处理完成(不算用户到服务器的网络延时)。这也是我目前性能优化的极限了。

继续阅读→

新的方式传递链路追踪上下文(NodeJS)

最近一个多月都在忙于项目,没有时间记录新的知识。我们起了一个全新的前端项目,技术选型是React + SSR + Dva。要求的起点也比较高:用户导航首屏SSR,其它时候CSR;代码要求SSR与CSR复用;所有的请求经过Node层;页面显示、接口请求均要求小于1秒。

为了容易定位调用链路的性能点,我们加入了Jaeger Open Tracing,这就涉及到链路追踪上下文的传递。

继续阅读→

NodeJS微服务间传递用户上下文

后端包含众多微服务时,如果每个微服务都是自己去查询用户信息(比如: 用户ID、登录名),会造成用户微服务压力过大、响应延时增大。为了解决这类问题,可以在网关服务中查询用户信息等共用信息,然后传递到其它的微服务中,微服务之间也相互传递。

为了前端代码复用,在NodeJS中也使用Axios完成网络请求,也方便我们拦截处理。文本演示Express + Axios + Async hooks解决微服务间用户上下文传递的问题。

继续阅读→