店铺体验优化总结

Create at 2021 04 2918 min read技术JavaScriptReact阿里巴巴性能优化

本文整理了近两年来国际站店铺在体验优化上做的努力和探索,也取得了不错的成果,分享出来希望对其他类似场景能有帮助。

性能优化大体上可以分为网络性能优化和交互体验优化:

  • 交互体验优化,优化页面的交互体验,滚动是否顺滑,点击反馈是否及时,操作是否有卡顿等
    • 避免 DOM 的重绘和重排
      • DOM 操作尽量减少或者进行操作合并
      • 动画元素尽量采用 absolute 等脱离文档流的定位
    • 确保对用户的操作反馈及时,刷新率保持 60fps
      • 保证每一个 js 任务在 1000/60=16.67ms 执行完毕
      • 复杂计算交给 woker 进程
  • 网络性能优化,大多数情况是要进行首屏性能优化
    • 减少 ttfb 的时间
      • 减少 dns 查询、TCP 握手建链、ssl 建连
      • 避免 302 redirect
      • 减少后端

Rax 代码转换到 React

Create at 2019 08 0129 min read技术JavascriptBabelReactRax

背景

最近接手公司的一个移动端项目,是通过 Rax 作为 dsl 开发的,在发布的时候构建多分代码,在 APP 端编译为能够运行在 weex 上的代码,在 H5(跑在浏览器或者 webview 里面,不管什么技术我们统称 H5) 端使用降级的 weex

这一套开发体系,看起来很完美,一次开发,三端运行。但是真实在开发的时候,就不是这么完美了。由于毕竟是跑在 weex 上的,而不是浏览器。所以在开发方式上也很难直接从 web 端的开发方式平移过去,为了实现跨端运行,所以在样式上只实现了 Css 的子集, DOM API 也是如此,开发的时候,在浏览器里面调试的时候,一切正常,但是等发布到 APP 端用 weex 跑的时候又是各种问题,开发体验很不流畅。

当然,有人会说那是因为你对 weex 的 api 不了解,也对,~~一直以来对与这种自己搞一套非标准体系来实现各种魔法功能的东西都不怎么感兴趣~~ 但是如果了解它的成本大于了它带来的收益,那么对我们来说,

ReactDOM 是如何把组件渲染到 DOM 中的?

Create at 2017 09 2120 min read技术React

当我们在开发 React 项目中,第一次调用 ReactDOM.render 的时候都发生了什么呢? 今天就从源码角度来追踪一下这个问题(主要看流程, 而不纠结与细节)。

ReactDOMStackEntry

首先我们可以从 ReactDOM 的入口文件 ReactDOMStackEntry.js 中找到 render 方法。可以看到,render 方法是 ReactMount 组件提供的。

var ReactDOMStack = {
  findDOMNode: findDOMNode,
  render: ReactMount.render,
  unmountComponentAtNode: ReactMount.unmountComponentAtNode,
  version: ReactVersion,

  /* eslint-disable camelcase */
  unstable_batchedUpdat

React 源码浅析之 - onlyChildren

Create at 2017 09 212 min read技术ReactSourceCode

这个模块的代码非常简单,短短十几行。

var ReactElement = require("ReactElement")

var invariant = require("fbjs/lib/invariant")
function onlyChild(children) {
  invariant(
    ReactElement.isValidElement(children),
    "React.Children.only expected to receive a single React element child."
  )
  return children
}

module.exports = onlyChild

就是判断传入的 children 是不是一个合法的 React 元素,否则就抛错出来。判断的逻辑就在 ReactElement 模块里面:

ReactElement.isV

React 源码浅析之 - ReactElement

Create at 2017 09 216 min read技术ReactSourceCode

ReactElement

这个模块定义了 React 元素的行为和方法,首先看 ReactElement 函数:

ReactElement

var ReactElement = function (type, key, ref, self, source, owner, props) {
  var element = {
    // This tag allow us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,

    // Built-in properties that belong on the element
    type: type,
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this e

React 源码浅析之 - ReactChildren

Create at 2017 09 2111 min read技术ReactSourceCode

引入的模块

var ReactElement = require("ReactElement")

var emptyFunction = require("fbjs/lib/emptyFunction")
var invariant = require("fbjs/lib/invariant")

我们来看一下 ReactElement 模块,其他两个都是工具函数,不用关心。

Export 的对象

var ReactChildren = {
  forEach: forEachChildren,
  map: mapChildren,
  count: countChildren,
  toArray: toArray,
}

module.exports = ReactChildren

依次来看一下这个四个 API

forEach

React 源码浅析之 - ReactBaseClasses

Create at 2017 09 218 min read技术ReactSourceCode

引入的模块

var ReactNoopUpdateQueue = require("ReactNoopUpdateQueue")

var emptyObject = require("fbjs/lib/emptyObject")
var invariant = require("fbjs/lib/invariant")
var lowPriorityWarning = require("lowPriorityWarning")

其中, ReactNoopUpdateQueue 是默认的 updater ,用来提供 update, replaceState, setState 的入队操作,但可能是由于是默认 updater 的原因,只提供了 API 和对入参的校验,但没有提供实际的功能。比如:

Read more

React 源码浅析之 - 入口文件

Create at 2017 09 212 min read技术ReactSourceCode

本系列文章以 react 最新的版本: 16.0.0-beta.5 为准。 首先我们入口文件 ReactEntry.js 来看,

var ReactBaseClasses = require("ReactBaseClasses")
var ReactChildren = require("ReactChildren")
var ReactElement = require("ReactElement")
var ReactVersion = require("ReactVersion")

var onlyChild = require("onlyChild")

依赖模块: • ReactBaseClasses • ReactChildren • ReactElement • onlyChild • ReactElementValidator 接着:

var createElement = ReactElem

React-Redux 源码粗读

Create at 2017 08 046 min read技术ReactRedux

Overview

首先看一张图:

React-Redux

可以看到入口文件里面引入了这几个模块:

  • Provider
  • connectAdvanced
  • connect

我们就来依次看一下这几个模块

Provider

store 挂在在了 context 上面,给予了子组件访问 store 的能力。

connectAdvanced

一个用来生成 connect 的高阶函数,引用了以下模块:

import { Component, createElement } from "react"
import ho

技术选型

我们的项目主要选用以下技术开发,再配合一些其它辅助工具。

  • react
  • react-router
  • redux
  • react-redux

开发及线上环境

开发环境

由于项目是前后端分离的,所以我们需要一套完整的开发环境,需要包括以下功能:

  • 数据 Mock
  • Webpack 实施编译刷新
  • 方便前后端联调

基于这些需求,我们基于 Express, Webpack,Webpack-dev-middleware 搭建了这套完整的开发环境。

开发环境

可以看到,浏览器所有的请求都被本地的 Node.js 服务拦截。对于静态资源请求,都委托给 webpack-dev-middle