7-17
1 自己跟以前相比,有哪些进步?
- 前端基础方面:react组件封装、ts熟练度,对前端也有一个系统的认识
- 做事、沟通方面:抓得住重点
- 区块链方面:熟练联调合约、常见swap协议、稳定币协议是知道的
- 学习方面:总结出自己的一套学习方法
- 解决问题方面:善于利用Google检索问题、解决问题、并记录
-- 2022-07-19 12:18:08
2 Nextjs如何部署
部署方式很多,大致有:vercel、node、docker等,详见 Deployment
Docker部署
官方示例:with-docker
官方示例(多环境):with-docker-multi-env
坑1:安装git
RUN apk add --no-cache git
[1] https://github.com/sleede/fab-manager/issues/299
坑2:删除不需要的安装脚本
yarn 示例:
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
坑3:修改 yml 文件
示例,主要注意 服务名
和 镜像名
version: '3'
services:
crv-ftx-web-stage:
build:
context: ../../
dockerfile: docker/staging/Dockerfile
image: coinflow/crv-ftx-web:stage
ports:
- '3000:3000'
示例
TODO
3 Nextjs接口代理
作用
解决浏览器跨域问题
配置
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'https://api.example.com/:path*',
},
]
},
};
请求
请求到本机,就会被代理到 destination
http://localhost:3000/api
[1][NextJs CORS issue](https://stackoverflow.com/questions/65058598/nextjs-cors-issue)
4 Multicall原理
实现
实现multicall有两种方法:1.合约转发实现 2.provider.call
合约转发
以下是uniswap根据 multicall2 更改的multicall
// SPDX-License-Identifier: MIT
pragma solidity =0.7.6;
pragma abicoder v2;
/// @notice A fork of Multicall2 specifically tailored for the Uniswap Interface
contract UniswapInterfaceMulticall {
struct Call {
address target;
uint256 gasLimit;
bytes callData;
}
struct Result {
bool success;
uint256 gasUsed;
bytes returnData;
}
function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
timestamp = block.timestamp;
}
function getEthBalance(address addr) public view returns (uint256 balance) {
balance = addr.balance;
}
function multicall(Call[] memory calls) public returns (uint256 blockNumber, Result[] memory returnData) {
blockNumber = block.number;
returnData = new Result[](calls.length);
for (uint256 i = 0; i < calls.length; i++) {
(address target, uint256 gasLimit, bytes memory callData) =
(calls[i].target, calls[i].gasLimit, calls[i].callData);
uint256 gasLeftBefore = gasleft();
(bool success, bytes memory ret) = target.call{gas: gasLimit}(callData);
uint256 gasUsed = gasLeftBefore - gasleft();
returnData[i] = Result(success, gasUsed, ret);
}
}
}
无部署multicall
无部署multicall主要通过provider.call实现,具体原理请参见:Deployless Multicall for historical EVM data
通过 ethcall 对于无部署multicall的实现来看,她通过provider.call来实现
[1][ethcall](https://github.com/Destiner/ethcall)
[2][multicall2](https://github.com/makerdao/multicall)
5 拷贝文件到服务器
rsync -av --delete /Users/jiangjin/Documents/03_ftx/fox-ftx-interface [email protected]:/www
6 利用tree生成目录结构
# 显示深度为3级
tree -L 3
# 只显示目录,不显示文件
tree -d -L 3
[1][github中,生成项目展示的目录结构](https://juejin.cn/post/6844903843562520589)
7 Mui输入框隐藏label
关键:InputLabelProps={{shrink: false}}
and label=''
<TextField
id="outlined-select-gender"
select
label={gender=== "" ? "Gender": ""}
className={classes.textField}
value={gender}
onChange={handleChange}
InputLabelProps={{shrink: false}}
SelectProps={{
MenuProps: {
className: classes.menu,
},
}}
margin="normal"
variant="outlined"
>
{genders.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
[1][Remove Label on Material-UI Select Text Field](https://stackoverflow.com/questions/56879153/remove-label-on-material-ui-select-text-field)
8 PR时触发的GithubAction脚本示例
运行lint
# /.github/workflows/test.yml
name: Run tests
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: restore yarn
uses: actions/cache@v2
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- name: install
run: yarn
- name: lint
run: yarn lint
9 Eslint-Cannot read property 'loc' of undefined
原因
在使用 eslint-plugin-unused-imports
插件时,枚举类型导致出错,具体原因未知
解决
用对象模拟枚举
const LOCALES = {
'zh-CN': 'zh-CN',
'zh-TW': 'zh-TW',
}
type LOCALE = keyof typeof LOCALES
export type LanguageLabels = {
[key in LOCALE | string]: string
}
10 System UI Theme Specification(SystemUI主题规范)
[1][System UI Theme Specification](https://github.com/system-ui/theme-specification)
11 React18变更
一共4部分:
- Concurrent Model:并发渲染模型;
- Automatic Batching:多个state合并为一个更新;
- Transitions:指定渲染优先级;
- Suspense:更方便的组织请求和loading状态;
Transitions
import {startTransition} from 'react';
const handleChange = useCallback(()=> {
// Urgent: Show what was typed
setInputValue(input);
// Mark any state updates inside as transitions
startTransition(() => {
// Transition: Show the results
setSearchQuery(input);
});
}, [])
解释:第一时间响应用户输入,再展示输入结果
Suspense
完整设计文章见 0213-suspense-in-react-18
<Suspense fallback={<PageGlimmer />}>
<RightColumn>
<ProfileHeader />
</RightColumn>
<LeftColumn>
<Suspense fallback={<LeftColumnGlimmer />}>
<Comments />
<Photos />
</Suspense>
</LeftColumn>
</Suspense>
从概念上讲,您可以将
Suspense
其视为类似于catch
块。但是,它不是捕获错误,而是捕获“挂起”的组件。树中的任何组件都可以“挂起”,这意味着它还没有准备好渲染。(原因是任意的,但通常可能是由于缺少代码、数据等)
特殊情况
<div>
{showComments && (
<Suspense fallback={<Spinner />}>
<Panel>
<Comments />
</Panel>
</Suspense>
)}
</div>
提交的树总是一致的
:假设showComments
从false
变为true
。即使Panel准备好,但Comments未准备好,那也触发Spinner
12 如何通过 NPM 在应用程序之间共享 React 组件
[1][如何通过 NPM 在应用程序之间共享 React 组件](https://nosleepjavascript.com/package-react-components/)
13 Ts中extends和infer
TODO
Extends
作用:
- 表示继承/拓展的含义
- 表示约束的含义
- 表示分配的含义
约束
// 约束必须包含Contract,且缺省值为Contract
function getContract<T extends Contract = Contract>(){}
分配
// Exclude定义(排除)
type Exclude<T, U> = T extends U ? never : T
// Extract定义(包含)
type Extract<T, U> = T extends U ? T : never
// Pick定义(选取)
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
// Partial定义(全可选)
type Partial<T> = {
[K in keyof T]?: T[K]
}
[1][Typescript中的extends关键字](https://cloud.tencent.com/developer/article/1884330)
[2][白话typescript中的【extends】和【infer】](https://juejin.cn/post/6844904146877808653)
14 React的Suspense如何使用
如果在nextjs中使用,要注意服务器端渲染,要关闭ssr
关闭方法见 15
15 Nextjs预渲染每一个页面
所以,如果要进行客户端渲染,有两种方式:
#1 将数据放入useEffect中请求
export default function Home() {
const [data, setData] = useState();
useEffect(() => {
queryData().then((data: any)=> {
setData(data);
})
}, []);
return (
<div className={styles.container}>
{JSON.stringify(data)}
</div>
);
}
#2 动态导入,关闭ssr
const Home = dynamic(
() => import('../components/Home'),
{ ssr: false }
)
[1][Warning: Text content did not match. Server: "I'm out" Client: "I'm in" div](https://stackoverflow.com/questions/66374123/warning-text-content-did-not-match-server-im-out-client-im-in-div)
16 一个monorepo中存在多个react版本
该实现 较为困难
,但反过来想,在什么场景下需要多个react版本?
17 fabric.js
FabricJS.com is a simple and powerful Javascript HTML5 canvas library. It is also an SVG-to-canvas parser.
[1][fabric.js](https://github.com/fabricjs/fabric.js)