react 16 ssr的重构踩坑
ssr
- 服务端不能识别前端的window。特别是首屏渲染的数据需要用到window对象(比如href += location.search);
- 服务端不能加载图片,css文件。
require.extensions['.less'] = function () {
return null;
};
global.__DEV__ = !bytedEnv.isProd();
global.__SERVER__ = true; // 代码服务端环境
global.window = {
location: {
search: ''
}
};
//做了个中间件事实修改window的属性。
module.exports = () => async (ctx, next) => {
global.window = {
location: {
search: ctx.search,
host: ctx.host,
protocol: ctx.protocol
}
};
await next();
};
客户端需要全局变量来表示是否是客户端环境来选择加载某些库。
- 首屏从localstorage取数据,并不能服务端渲染
isSsr ? <div className="channel-bar">: <ChannelBar />
这里用了hydrate而不是render渲染react组件,导致首刷的dom被尽可能的复用。
导致的问题是ChannelBar的最外层dom被复用。如果服务端渲染为空div占位的话,上面的class channel-bar
就会丢失。
所以首屏渲染最好还是要保证首刷客户端和服务端一样才行。
这种问题官方推荐的做法是在react生命周期里渲染首刷不同的部分。不过这种做法必然会导致组件rerender。
解决方案:ChannelBar的useEffect里去localstorage拿数据,这样保证首刷一致。
react 16 hooks问题
function OnePxBorder({ color }) {
const style = {
backgroundColor: color,
height: '1px'
};
return <div className="one-px" style={style} />;
}
对于这样一个组件,const style语句等语句(定义函数等)会在组件rerender的时候重新执行。这样会导致定义在组件内的函数多次定义。
解决方案:无关state的函数定义在react组件外。
function Channel() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
useEffect(() => {
setCount(1);
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect会在每次render的时候重新执行,以上代码,count再点也是1;
useEffect第二个参数传空数组可保证函数只执行一遍。
useEffect(() => {
setCount(1);
}, []);
这样实现初始化为1的效果。
function Channel() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('bind')
const timer = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => {
console.log('re bind')
clearInterval(timer);
};
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
如前,可以看到setInterval被触发,被解绑,被触发,再解绑。
如果加上useEffect(() => {}, [])
;
会导致count
永远是1。
原因是useEffect如果不重新执行,拿不到最新的state。拿到的state总是最早的state也就是0。
暂时没有好的方法。现在写为useEffect(() => {}, [count])
;
如果遇到只能初始化一次的,比如某些插件。可以用事件系统每次拿最新的函数去执行:
import { EventEmitter } from 'events';
const event = new EventEmitter();
new xxx({ // 此插件只运行一次。回调总执行新的doSomething
onFinish: () => {
event.emit('some_event');
}
});
function Components({ doSomething }) {
useEffect(() => {
event.on('some_event', doSomething);
return () => {
event.removeListener('some_event', doSomething);
};
});
}
render函数被重复执行
有这样一个组件,loading是个state,每次setloadding会导致list重新执行。
listEl需要数据处理,渲染。每次setloadding,就会处理一遍数据。
{ listEl }
{
loading && <div>'loading.....'</div>
}
处理方案:useMemo Hooks
useMemo能让我们保存一段dom。
const createMemo = function() {
return useMemo(() => {
// handle data
}, [data.length])
}
这样使得data.length变了之后useMemo hooks里的代码才会重新执行。
useMemo的第二个参数是用Object.is判断的,不能直接写个Object,react不会帮你deep assert。
react 16
如官网所说:react16需要set和map环境。而import的包不会被babel编译,所以需要手动引入map/set
import 'core-js/es6/map';
import 'core-js/es6/set';
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
React 16 depends on the collection types Map and Set. If you support older browsers and devices which may not yet provide these natively (e.g. IE < 11) or which have non-compliant implementations (e.g. IE 11), consider including a global polyfill in your bundled application, such as core-js or babel-polyfill.
服务端http请求
服务端请求不带header。需要把header带上。
首次请求set到客户端的cookie(用户标识),在服务端首刷请求的时候并不能取得。需要手动修改设置cookie。
if (!reqestHeader.cookie) {
reqestHeader.cookie = `uid=${ctx.u_id}; utm_source=${utmSource}`;
}
css module问题
css全局作用域。不想用插件。
靠规范解决。
编译
gulu要求目录文件是app,需要编译要按gulu目录来。
prod环境找问题比较麻烦,对gulu这种框架,需要看他源码来找,没得文档。
react 16 ssr的重构踩坑的更多相关文章
- React Native Android配置部署踩坑日记
万事开头难 作为一只进入ECMAScript世界不久的菜鸟,已经被React Native的名气惊到了,开源一周数万星勾起了我浓烈的兴趣.新年新气象,来个HellWorld压压惊吧^_^(故意少打个' ...
- ant.design React使用Echarts,实力踩坑
最近项目用到Echarts(以下用ec代替),于是照猫画虎得引入到团队的antd项目中,但是遇到2个棘手问题: 1. ec对dom不渲染,检查后发现,原来是全局存在id重复,所以使用React时,最好 ...
- React 16 升级时遇到的一个坑,分享一下
遇到的坑 今天在跟着dva.js官网上面的一个教程写东西的时候,照着教程上面的代码写之后,运行总是报错:TypeError: Cannot read property 'object' of unde ...
- react中的路由配置踩坑记
react 路由配置中,如果根路由(/)匹配一个组件,另一个路由(/list)在进行匹配的时候也会匹配到根路由(/),即在 /list 页面展示的时候 / 页面总是展示在上方. 此时如果想进行严格匹配 ...
- 使用 jest 测试 react component 的配置,踩坑。
首先安装依赖 npm i jest -g npm i jest babel-jest identity-obj-proxy enzyme enzyme-adapter-react-15.4 react ...
- 利用vue-router和compoment重构代码--踩坑(一)
业务主要功能 获取所有的数据库列表 点击某一个数据库列表的时候,右侧分页展示数据 点击右侧某一条数据的时候,现实数据详情 以下是之前的页面,存在以下问题: 前段开发没有工程化(webpack) 主要功 ...
- React Native踩坑日记 —— tailwind-rn
项目背景 在项目的初始阶段,我们需要建立自己的design system,我们spike了一些方案,tailwind-rn就是其中一种,如果有用到或者即将用到tailwind-rn的,可以进来看一看, ...
- React Native踩坑Tip
最近在使用React Native(以下简称RN)中踩了个坑,RN只能异步调用原生方法,所以在原生方法直接调用UI刷新操作需要将任务递交到主线程才可以. RCT_EXPORT_METHOD(finis ...
- Ubuntu 16.04 安装Mysql 5.7 踩坑小记
title:Ubuntu 16.04 安装Mysql 5.7 踩坑小记 date: 2018.02.03 安装mysql sudo apt-get install mysql-server mysql ...
随机推荐
- Java开发笔记(八十六)通过缓冲区读写文件
前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...
- 如何在Linux服务器和windows系统之间上传与下载文件
Do not let dream just be your dream. 背景:Linux服务器文件上传下载. XShell+Xftp安装包(解压即用)百度网盘链接:https://pan.baidu ...
- APICloud Studio2新建应用报错和检出错误
今天心血来潮,闲暇时间想做个移动应用app,听一哥们说APICloud开发app很方便,就查询了一下,看了之后简直就是热血沸腾,我感觉正是我一直要找的工具 信心满满的开始着手使用,看了一下介绍我选择了 ...
- [20190416]process allocation latch.txt
[20190416]process allocation latch.txt --//看链接:http://andreynikolaev.wordpress.com/2010/12/16/hidden ...
- Redis与Memocache的区别
转载地址:http://gnucto.blog.51cto.com/3391516/998509 Redis与Memcached的区别 传统MySQL+ Memcached架构遇到的问题 实际MySQ ...
- SQL Server数据库————增删改查
--增删改查--增 insert into 表名(列名) value(值列表) --删 delect from 表名 where 条件 --改 update 表名 set 列名=值1,列名2=值2 w ...
- vs code使用Git
做一夜的搬运工:https://www.cnblogs.com/richard1015/p/8336429.html
- 吴军武志红万维刚薛兆丰何帆曾鸣李笑来罗永浩等得到APP专栏作者的书3
整理了一下最近两三年内看过的得到APP专栏与课程作者的得到精选文集和他们写过的书共本.新增吴军1本,武志红1本. 其中:武志红3本,熊太行1本,薛兆丰2本,吴军4本,何帆3本,曾鸣2本,万维刚1本,李 ...
- [认证授权] 1.OAuth2授权
1 OAuth2解决什么问题的? 举个栗子先.小明在QQ空间积攒了多年的照片,想挑选一些照片来打印出来.然后小明在找到一家提供在线打印并且包邮的网站(我们叫它PP吧(Print Photo缩写
- 基于jQuery实现简单的js模块化
在多人合作完成网页,经常遇到大家的js代码相互影响的问题.现在有许多模块化的前端框架,应该是可以解决这个问题.但本人并非前端开发人员,那些框架都没用过,只对jQuery相对熟悉,就想用jQuery来解 ...