Skip to main content

5-9

1 rollup

rollup 是一个 js 打包器

[1] rollup 从入门到打包一个按需加载的组件库.https://juejin.cn/post/6934698510436859912

[2] 使用 rollup 构建 Javascript 库.https://lexmin0412.github.io/blog/%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%8C%96/%E4%BD%BF%E7%94%A8rollup%E6%9E%84%E5%BB%BAJavascript%E5%BA%93.html#why-rollup

[3] rollup.js 中文文档.https://www.rollupjs.com/

2 react 时间区间选择组件

react-date-range

import { Calendar } from 'react-date-range'

[1] react-date-range.https://www.npmjs.com/package/react-date-range

3 BigNumber 向上取整

var BN = BigNumber.clone()
BN.config({ DECIMAL_PLACES: 2 })
//取值范围:
BigNumber.ROUND_UP = 0 //远离0方向舍入
BigNumber.ROUND_DOWN = 1 //向0方向舍入
BigNumber.ROUND_CEIL = 2 //向正无限大舍入
BigNumber.ROUND_FLOOR = 3 //向负无限大舍入
BigNumber.ROUND_HALF_UP = 4 //四舍五入:向最接近的数字方向舍入,如果与两个相邻数字的距离相等,则向上舍入。
BigNumber.ROUND_HALF_DOWN = 5 //向最接近的数字方向舍入,如果与两个相邻数字的距离相等,则向下舍入。
BigNumber.ROUND_HALF_EVEN = 6 //向最接近数字方向舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入
BigNumber.ROUND_HALF_CEIL = 7
BigNumber.ROUND_HALF_FLOOR = 8

[1] bignumber.js 使用记录.https://juejin.cn/post/6844903704714280968

[2] https://mikemcl.github.io/bignumber.js/

4 emotion 的主题类型定义

import '@emotion/react'

declare module '@emotion/react' {
export interface Theme {
color: {
primary: string
positive: string
negative: string
}
}
}

// You are also able to use a 3rd party theme this way:
import '@emotion/react'
import { LibTheme } from 'some-lib'

declare module '@emotion/react' {
export interface Theme extends LibTheme {}
}

[1] https://emotion.sh/docs/typescript

5 sx 属性原理

TODO

[1] rebassjs 的 flexbox.https://github.com/rebassjs/rebass/blob/master/packages/reflexbox/src/index.js

6 forwardRef 作用?

const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
))

// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef()
;<FancyButton ref={ref}>Click me!</FancyButton>

[1] Refs 转发.https://zh-hans.reactjs.org/docs/forwarding-refs.html

7 合约监听事件

contract.on('ValueChanged', (author, oldValue, newValue, event) => {
// 在值变化的时候被调用

console.log(author)
// "0x14791697260E4c9A71f18484C9f997B308e59325"

console.log(oldValue)
// "Hello World"

console.log(newValue)
// "Ilike turtles."

// 查看后面的事件触发器 Event Emitter 了解事件对象的属性
console.log(event.blockNumber)
// 4115004
})

8 注意登录服务器的账号

不同账号,有不同.ssh 目录,以及配置

附:腾讯云修改轻量应用服务器的的 ROOT 密码.https://cloud.tencent.com/developer/article/1875209?from=15425

sudo -i

9 搭建 monorepo + nextjs 项目的一些问题

这里有一个比较完整的示例项目:https://github.com/belgattitude/nextjs-monorepo-example

问题一:无法导入外部 Ts 模块

表现

../../packages/uilib/src/components/Alert/index.tsx
Module parse failed: Unexpected token (3:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| export { default as Alert } from './Alert'
| export { variants as alertVariants } from './types'
> export type { AlertProps, Variants as AlertVariants } from './types'
|

原因:nextjs 无法导入外部 Ts 模块

解决方案:

const nextConfig = {
experimental: {
// Experimental monorepo support
// @link {https://github.com/vercel/next.js/pull/22867|Original PR}
// @link {https://github.com/vercel/next.js/discussions/26420|Discussion}
externalDir: true,
},
}

问题一:Can't build React/Next project - found page without a React Component as default export (context api file)

解决方案:把组件搬离到 pages 之外

You should move your components outside the pages folder. pages/ should only be used for page components as Next.js routing is based on its structure.

[1] https://stackoverflow.com/questions/65598753/cant-build-react-next-project-found-page-without-a-react-component-as-default

问题二:nextjs 将文件移动到 src 目录下

nestjs 默认支持将资源放到 src 目录中

[1] https://nextjs.org/docs/advanced-features/src-directory

问题三:在 nextjs 中无法使用 styled-components 的 macro

现象:

cannot find 'module' ...

原因:未知

解决方案:不使用 macro

import styled from 'styled-components'

问题四:nestjs 提示 Warning: Prop className did not match

原因:未知

解决方案:添加 babel 插件处理

yarn add --dev babel-plugin-styled-components

Then add this to .babelrc file:

{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
}

问题五:Module not found: Can't resolve 'fs' in Next.js application

原因:未知

解决方案:

// Fixes npm packages that depend on `fs` module
// @link https://github.com/vercel/next.js/issues/36514#issuecomment-1112074589
config.resolve.fallback = { ...config.resolve.fallback, fs: false }

附:一份完整的 nextjs 配置

涉及到 监控导入外部ts模块安全头部支持react18 等配置

// @ts-check

// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
const { withSentryConfig } = require('@sentry/nextjs')
// const pc = require('picocolors');
const packageJson = require('./package.json')

const trueEnv = ['true', '1', 'yes']

const isProd = process.env.NODE_ENV === 'production'
const isCI = trueEnv.includes(process.env?.CI ?? 'false')

const NEXTJS_IGNORE_ESLINT = trueEnv.includes(process.env?.NEXTJS_IGNORE_ESLINT ?? 'false')
const NEXTJS_IGNORE_TYPECHECK = trueEnv.includes(process.env?.NEXTJS_IGNORE_TYPECHECK ?? 'false')
const NEXTJS_DISABLE_SENTRY = trueEnv.includes(process.env?.NEXTJS_DISABLE_SENTRY ?? 'false')
const NEXTJS_SENTRY_UPLOAD_DRY_RUN = trueEnv.includes(process.env?.NEXTJS_SENTRY_UPLOAD_DRY_RUN ?? 'false')

/**
* A way to allow CI optimization when the build done there is not used
* to deliver an image or deploy the files.
* @link https://nextjs.org/docs/advanced-features/source-maps
*/
const disableSourceMaps = trueEnv.includes(process.env?.NEXT_DISABLE_SOURCEMAPS ?? 'false')

// if (disableSourceMaps) {
// console.info(
// `${pc.green(
// 'notice'
// )}- Sourcemaps generation have been disabled through NEXT_DISABLE_SOURCEMAPS`
// );
// }

// Tell webpack to compile those packages
// @link https://www.npmjs.com/package/next-transpile-modules
const tmModules = [
// for legacy browsers support (only in prod)
...(isProd
? [
// ie: '@react-google-maps/api'...
]
: []),
// ESM only packages are not yet supported by NextJs if you're not
// using experimental experimental esmExternals
// @link {https://nextjs.org/blog/next-11-1#es-modules-support|Blog 11.1.0}
// @link {https://github.com/vercel/next.js/discussions/27876|Discussion}
// @link https://github.com/vercel/next.js/issues/23725
// @link https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
...[
// ie: newer versions of https://github.com/sindresorhus packages
],
]

// Example of setting up secure headers
// @link https://github.com/jagaapple/next-secure-headers
// const { createSecureHeaders } = require('next-secure-headers');
// const secureHeaders = createSecureHeaders({
// contentSecurityPolicy: {
// directives: {
// // defaultSrc: "'self'",
// // styleSrc: ["'self'"],
// },
// },
// ...(isProd
// ? {
// forceHTTPSRedirect: [
// true,
// { maxAge: 60 * 60 * 24 * 4, includeSubDomains: true },
// ],
// }
// : {}),
// referrerPolicy: 'same-origin',
// });

/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
reactStrictMode: true,
productionBrowserSourceMaps: !disableSourceMaps,
// i18n,
optimizeFonts: true,

httpAgentOptions: {
// @link https://nextjs.org/blog/next-11-1#builds--data-fetching
keepAlive: true,
},

onDemandEntries: {
// period (in ms) where the server will keep pages in the buffer
maxInactiveAge: (isCI ? 3600 : 25) * 1000,
},

// @link https://nextjs.org/docs/advanced-features/compiler#minification
swcMinify: true,

experimental: {
// Still buggy as of nextjs 12.1.5
/**
emotion: {
sourceMap: process.env.NODE_ENV === 'development',
autoLabel: 'dev-only',
// Allowed values: `[local]` `[filename]` and `[dirname]`
// This option only works when autoLabel is set to 'dev-only' or 'always'.
// It allows you to define the format of the resulting label.
// The format is defined via string where variable parts are enclosed in square brackets [].
// For example labelFormat: "my-classname--[local]", where [local] will be replaced with the name of the variable the result is assigned to.
labelFormat: '[local]',
},
*/
// React 18
// @link https://nextjs.org/docs/advanced-features/react-18
reactRoot: true,
// React 18 streaming
// @link https://nextjs.org/docs/advanced-features/react-18/streaming
runtime: undefined,
// React 18 server components
// @link https://nextjs.org/docs/advanced-features/react-18/server-components
serverComponents: false,
// Standalone build
// @link https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files-experimental
outputStandalone: false,
// @link https://nextjs.org/docs/advanced-features/output-file-tracing#caveats
outputFileTracingRoot: undefined, // ,path.join(__dirname, '../../'),
// Prefer loading of ES Modules over CommonJS
// @link {https://nextjs.org/blog/next-11-1#es-modules-support|Blog 11.1.0}
// @link {https://github.com/vercel/next.js/discussions/27876|Discussion}
esmExternals: true,
// Experimental monorepo support
// @link {https://github.com/vercel/next.js/pull/22867|Original PR}
// @link {https://github.com/vercel/next.js/discussions/26420|Discussion}
externalDir: true,
},

// @link https://nextjs.org/docs/basic-features/image-optimization
images: {
loader: 'default',
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
disableStaticImages: false,
// https://nextjs.org/docs/api-reference/next/image#caching-behavior
minimumCacheTTL: 60,
// Allowed domains for next/image
domains: ['source.unsplash.com'],
},

typescript: {
ignoreBuildErrors: NEXTJS_IGNORE_TYPECHECK,
},

eslint: {
ignoreDuringBuilds: NEXTJS_IGNORE_ESLINT,
dirs: ['src'],
},

// async headers() {
// return [{ source: '/(.*)', headers: secureHeaders }];
// },

/**
* @link https://nextjs.org/docs/api-reference/next.config.js/rewrites
async rewrites() {
return [
{
source: `/`,
destination: '/demo',
},
];
},
*/

webpack: (config, { isServer }) => {
// Fixes npm packages that depend on `fs` module
// @link https://github.com/vercel/next.js/issues/36514#issuecomment-1112074589
config.resolve.fallback = { ...config.resolve.fallback, fs: false }

// config.module.rules.push({
// test: /\.svg$/,
// issuer: /\.(js|ts)x?$/,
// use: [
// {
// loader: '@svgr/webpack',
// // https://react-svgr.com/docs/webpack/#passing-options
// options: {
// svgo: true,
// // @link https://github.com/svg/svgo#configuration
// svgoConfig: {
// multipass: false,
// datauri: 'base64',
// js2svg: {
// indent: 2,
// pretty: false,
// },
// },
// },
// },
// ],
// });

return config
},
env: {
APP_NAME: packageJson.name,
APP_VERSION: packageJson.version,
BUILD_TIME: new Date().toISOString(),
},
serverRuntimeConfig: {
// to bypass https://github.com/zeit/next.js/issues/8251
PROJECT_ROOT: __dirname,
},
}

let config

if (tmModules.length > 0) {
const withNextTranspileModules = require('next-transpile-modules')(tmModules, {
resolveSymlinks: true,
debug: false,
})
config = withNextTranspileModules(nextConfig)
} else {
config = nextConfig
}

config = withSentryConfig(config, {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
// silent: isProd, // Suppresses all logs
dryRun: NEXTJS_SENTRY_UPLOAD_DRY_RUN,
})

if (process.env.ANALYZE === 'true') {
// @ts-ignore
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: true,
})
config = withBundleAnalyzer(config)
}

module.exports = config

整个 nextjs 项目详见:https://github.com/belgattitude/nextjs-monorepo-example/tree/main/apps/nextjs-app

10 配置七牛云存储

TODO

[1] 使用七牛云 CDN 为你的网站加速.https://huayig.cn/index.php/archives/18/

[2] 原创】picgo 使用七牛云图床.https://www.yinxiang.com/everhub/note/365dd665-440a-4f37-93b2-1e5b557a9d2f

11 Sentry 在 Nextjs 中的使用初探

TODO

[1] Sentry.https://sentry.io/organizations/ginlink/projects/

[2] Docs.https://docs.sentry.io/platforms/javascript/guides/nextjs/

12 npm 发布包问题 | 发包 | 发版

发包流程请 google 或者 baidu

注意两个问题:1.登录 2.包的配置

问题一:登录

先切换到 npm 服务器

npx nrm use npm

# 切换来可以用
npx nrm use taobao

再尝试登录

npm login

问题二:包的配置

给一个示例配置,注意 publishConfig 权限配置为 public

{
"name": "@ginlink/eslint-config",
"version": "0.1.0",
"description": "React common eslint config",
"main": "lib/index.js",
"private": false,
"publishConfig": {
"access": "public"
},
"files": ["lib"],
"scripts": {},
"repository": {},
"author": "ginlink",
"license": "ISC",
"bugs": {
"url": "https://github.com/ginlink/cool-uilib/issues"
},
"homepage": "https://github.com/ginlink/cool-uilib#readme",
"devDependencies": {},
"dependencies": {
"@typescript-eslint/eslint-plugin": "^5.22.0",
"@typescript-eslint/parser": "^5.22.0",
"eslint": "^8.14.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-lodash": "^7.4.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.5.0"
},
"peerDependencies": {
"eslint": "^7.2.0",
"prettier": "^2.1.2"
}
}

版本问题

增加版本
// version = v1.0.0

npm version prepatch --preid=alpha
// v1.0.2-alpha.0

npm version patch
// v1.0.1

npm version minor
// v1.1.0
npm version major
// v2.0.0
发布测试版
npm publish --tag beta
解决发错版本

不小心将测试版发布到latest解决方法:

latest: 1.0.1-beta.0

// 将1.0.1-beta.0设置为beta
// 该操作会直接生效
npm dist-tag add my-package@1.0.1-beta.0 beta
npm dist-tag add my-package@1.0.0 latest

[1] npm 发包者必读.https://juejin.cn/post/6844903870678695943

13 ethcall

发送请求时与 Promise.all 类似,但 ethcall 会将多个请求封装在同一个 http 包中,从而加快请求速度

注意:其请求通过 multicall 合约读取数据,也可以通过 Deployless Multicall 进行,Deployless Multicall 指无部署 multicall 就能读取到数据。

示例

官方示例

import { InfuraProvider } from '@ethersproject/providers'
import { Contract, Provider } from 'ethcall'

import erc20Abi from './abi/erc20.json'

const infuraKey = 'INSERT_YOUR_KEY_HERE'
const provider = new InfuraProvider('mainnet', infuraKey)

const daiAddress = '0x6b175474e89094c44da98b954eedeac495271d0f'

async function call() {
const ethcallProvider = new Provider()
await ethcallProvider.init(provider)

const daiContract = new Contract(daiAddress, erc20Abi)

const uniswapDaiPool = '0x2a1530c4c41db0b0b2bb646cb5eb1a67b7158667'

const ethBalanceCall = ethcallProvider.getEthBalance(uniswapDaiPool)
const daiBalanceCall = daiContract.balanceOf(uniswapDaiPool)

const data = await ethcallProvider.all([ethBalanceCall, daiBalanceCall])

const ethBalance = data[0]
const daiBalance = data[1]

console.log('eth balance', ethBalance.toString())
console.log('dai balance', daiBalance.toString())
}

call()

结论

可以在任意链上使用 ethcall 读取数据,如果该链存在 multicall 合约,则用该合约读取,否则用 Deployless Multicall 读取

[1] https://www.npmjs.com/package/ethcall

14 react-popper 位置展示错误

情景

image-20220516114621704

解决方案

切换状态时,更新位置

const { styles, attributes, update } = usePopper(referenceElement, popperElement, {
placement: placement,
modifiers: [
{ name: 'arrow', options: { element: arrowElement } },
{ name: 'offset', options: { offset: [0, 3] } },
],
})

const toggleDropdown = (e) => {
e.preventDefault()
e.stopPropagation()

setVisible(!visible)
update()
}

[1] react-popper incorrect position on mount.https://stackoverflow.com/questions/65585859/react-popper-incorrect-position-on-mount

15 src 和 href 的区别

项目区别
src(Source)是指向物件的来源地址,是引入,在 img、script、iframe 等元素上使用
href(Hypertext Reference)是超文本引用,指向需要连结的地方,是与该页面有关联的,是引用,在 link 和 a 等元素上使用。

16 加载脚本时 defer 和 async 的区别

请输入图片描述

defer 是最后解析的

17 面试相关题目

Html

  • src 和 href 的区别?
  • 加载脚本时 defer 和 async 的区别?
  • 图片懒加载实现原理?
  • 标签语义化的理解?

Css

  • css 常见选择器和它们的优先级
  • 隐藏元素的几种方式?它们有什么区别?
  • 盒模型的理解
  • 布局:如何对一个元素实现水平和垂直居中?
  • 场景:如何实现 0.5px 的线条?
  • 场景:如何实现一个渐变边框?

Js

运行时

  • 事件循环模型

React

  • 组件通讯方式有什么?

  • 什么是受控组件和非受控组件?

  • 我们在渲染数组的时候,为什么要提供 key?

  • 如何避免不必要的渲染?

网络

  • 从输入 url 到页面呈现,中间发生了什么?
  • http 协议结构是怎么样的?

算法

  • 常见排序算法(选择排序、插入排序)
  • 两数之和
  • 反转链表

18 如何关闭 react/react-in-jsx-scope

react17 以上可以关闭

.eslintrc.json

{
"extends": [
"@ginlink/eslint-config",
"plugin:react/jsx-runtime"
]
}

https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md

19 CSS 实现渐变色边框(Gradient borders)

.border-box {
border: 4px solid transparent;
border-radius: 16px;
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
background-image: linear-gradient(to right, #222, #222), linear-gradient(90deg, #8f41e9, #578aef);

/*
linear-gradient(to right, #222, #222) 控制前景色
linear-gradient(90deg, #8F41E9, #578AEF) 控制背景色
*/
}

[1] CSS 实现渐变色边框(Gradient borders)的 5 种方法.https://segmentfault.com/a/1190000040794056

20 CSS实现渐变文字