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.
问题二: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 [email protected] beta
npm dist-tag add [email protected] 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 位置展示错误
情景
解决方案
切换状态时,更新位置
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