Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

杂七杂八问题以及解决方案记录 #20

Open
creeperyang opened this issue Apr 25, 2016 · 28 comments
Open

杂七杂八问题以及解决方案记录 #20

creeperyang opened this issue Apr 25, 2016 · 28 comments

Comments

@creeperyang
Copy link
Owner

creeperyang commented Apr 25, 2016

工作,日常学习,阅读文章等过程中的问题记录,包括解决方案(如果有)或者相关探索。

相关:

  1. 框架和库的使用问题
  2. 浏览器相关问题(如调试)
  3. 系统相关问题(如兼容性问题)
  4. 各种工具(如 git)问题
  5. ...

注意:

由于水平有限,不保证100%正确,欢迎讨论,共同进步。

@creeperyang
Copy link
Owner Author

creeperyang commented Apr 25, 2016

1. Koa之context.is

app.use((ctx, next) => {
    if (ctx.is('html')) {
    // do something
    }
});

// assume browser opens `localhost:3000/`

context.is跟我们期待的行为很不一样。我们以为只要content-type符合,那么这个方法就要返回正确的typeNaive!!!

context.is的内部实现是jshttp/type-is这个库,查看源码可知:

function typeofrequest(req, types_) {
  var types = types_

  // no body
  if (!hasbody(req)) {
    return null
  }

在代码检查content-type前,已经因为request没有body被打断了。更明确一点,所有的GET请求context.is一律返回null

呵呵...

为什么这么处理?查到的一个比较官方的解释是 koajs/koa#440

并且官方推荐context.accepts这个API。

结论: 怎么说呢,限制必须有body好像也不是完全没道理,不过还是 呵呵 。

@creeperyang
Copy link
Owner Author

creeperyang commented Apr 26, 2016

2. path的API在windows平台的行为

unix/linux/osx下,path的API的执行结果都是简明一致的。由于windows的盘符概念,这些API返回的结果则需要特别注意了。

path.resolve('/dir/subdir/index.html')
// returns 'D:\\dir\\subdir\\index.html'  返回了D盘(工作盘)作为根目录

path.join('/root', 'dir/index.html')
// returns '\\root\\dir\\index.html'  `/`被替换为了`\\`

请记住,windows下这些API的执行结果很多时候不符合预期

然后在操作路径前使用path.normalize可能是比较好的行为。

@creeperyang
Copy link
Owner Author

3. windows上0.0.0.0:3000无法访问

nodejs server跑在0.0.0.0,让同事本机部署时,0.0.0.0:3000竟然无法访问,报错**ERR_ADDRESS_INVALID**。

解决:

原来windows上0.0.0.0被当作无效/未知的域名,服务器跑在0.0.0.0:3000后,其实可以

  • 本地用localhost:3000访问
  • 外部用ip:3000访问

@creeperyang
Copy link
Owner Author

creeperyang commented Aug 24, 2016

4. html中的是什么鬼??

工作中需要分割项目,从原来代码(windows系统中写的)中拷贝了页面到新仓库(Mac开发),浏览器中浏览页面,Elements面板发现head中的内容漏到body里了,然后body内第一个字符就是!!

资料:

zero width no-break space ,windows用来做 byte order marks。果然是windows的锅。

除资料里的方法外,可以这样去除65279:

const re = new RegExp(String.fromCharCode(65279), 'g')
str.replace(re, '')

@creeperyang
Copy link
Owner Author

5. shebang line(#!) 与node.js工具

写脚本已经是node.js的一个主流功能,比如gulp-cli, webpack-cli等等。今天用一个小工具突然报了一个莫名其妙的错误,错误原因比较有意思,这里记录下。

#!/usr/bin/env node

var xxx...

一般情况下,脚本都是上面的格式,表示用node去执行下面的js代码。其中第一行叫shebang line,指明用来执行脚本的解释程序。

而使用的小工具报了这样的错误信息:

env: node\r: No such file or directory

❓❓❓

一番排查,问题出在shebang line:

fs.readFileSync('脚本所在路径').toString().slice(0, 30)

// --->

'#!/usr/bin/env node\n\n\'use stri'  // 正常的
'#!/usr/bin/env node\r\n\r\n\'use st' // 报错的

是不是看出什么了?对的,问题就出在\r上。

unix/linux 下,换行符是\n,于是,有问题的shebang line被解析后,env是node\r,而不是node。所以系统根本没法找到一个叫node\r的程序来执行这段脚本...

最后问了工具的开发者,他在windows上开发,😭 😭 , 这就是\r\n哪里来的....

@creeperyang
Copy link
Owner Author

creeperyang commented Oct 27, 2016

6. socket 之 ECONNRESET

资料:

  1. http.Agent: idle sockets throw unhandled ECONNRESET
  2. Node js ECONNRESET

可能的原因:

  1. socket 的 ECONNRESET 错误一般是因为TCP连接的一方突然关闭连接。http agent不能自己吞下(swallowed)这个错误,因为吞下后,比如你就不能通过这个错误分清由unclean termination造成的empty reply。
  2. socket 抛出未处理的 ECONNRESET,在不同版本的node中,有些版本这个错误是silent的,有些则直接抛出。
  3. ECONNRESET是因为连接的一方突然关闭连接。为什么要关闭的原因有很多,可能是因为各种应用层协议错误,可能是达到硬件/软件支持的连接上限等等。

@creeperyang creeperyang changed the title 各类框架/库使用过程中的问题和其它 框架/库使用问题和Node.js API Oct 28, 2016
@creeperyang creeperyang added Q & A and removed Q&A labels Dec 9, 2016
@creeperyang creeperyang changed the title 框架/库使用问题和Node.js API 框架/库使用问题,系统问题及其它问题 Dec 14, 2016
@creeperyang
Copy link
Owner Author

creeperyang commented Dec 14, 2016

7. Chrome(或其它浏览器)中请求canceled问题

问题描述:

image

公司流量全面切向 https ,有用户上报bug:pad中浏览我们新上的某个功能时,页面只出现了背景,没内容...

排查问题,手机看起来没问题,新版iPad没问题,安卓pad有问题。

  1. 由于是内部测试域名,安装证书后安卓平板正常。
  2. 定位到iOS7.x的iPad出现上述问题。

问题描述就到这里,回到要关注的焦点:为什么大量GET请求被浏览器canceled了?

答案:

What does status=canceled for a resource mean in Chrome Developer Tools?

请求是否被浏览器主动cancel掉,取决于 机器(computer) 和/或 网速

  1. 引起请求的DOM被删除。如img正在加载,但在加载完成前被删除。
  2. 做了一些事,使得正在发生的请求(的数据)已经不需要了。比如你加载一个iframe,但加载完成前你改了iframesrc
  3. 向同一个服务器发起了大量请求,然后比较早的某个请求(指向该服务器的请求)遇到了网络问题——表明接下来的请求都不会work了,所以会主动cancel。网络问题包括:DNS错误,HTTP 4xx 错误等。

@creeperyang
Copy link
Owner Author

8. git hook 未执行的一个可能原因

  1. 某个库,开发时watch代码并实时编译。
  2. 然后内部有个服务器会同步库所在的repo,并需要用网页展示该库的文档(依赖编译后的资源)。

服务器上直接watch仓库内代码可能会有性能问题,那么,在服务器上的repo直接写个post-merge的本地hook更合适——每当代码同步后跑编译命令(包括build出文档)。

然后碰到一个问题:.git/hooks/post-merge这个hook就是不执行,包括试过直接git pull而不是用已有的webhook API同步,包括把hook脚本改为最简单的echo——就是没反应。

想了又想,会不会是权限问题?

ls -al .git/hooks

# post-merge 果然和其它的妖艳贱货不一样 😂 

chmod -R 777 .git/hooks/post-merge

然后再测试,果然可以了....

@kkshaq
Copy link

kkshaq commented Dec 25, 2016

hi,你好。请教一下ECONNRESET的问题,按理说如果收到RST报文之后去read,就会报ECONNRESET的错误,那么在node中是怎么处理的?
我如果想catch到这个error,是否用.on('error‘,callback)去监听?你说的有些版本这个错误是silent的,有些则直接抛出是什么意思?能否更详细的解释一下。
我试过server 发送rst给client,client那边用.on('error‘’,callback)去监听,但是并不能catch到error,
只能catch到ECONNREFUSED之类的错误。
谢谢!

@creeperyang
Copy link
Owner Author

@kkshaq silent是指这个错误不会向上抛出,比如uncaughtException不能捕获到这个错误。另外,http上是捕获不到这个错误的,必须在socket上监听。

@creeperyang
Copy link
Owner Author

9. socket 之 ECONNABORTED

收到这样一个错误截图:

error

没有什么思路,看起来应该又是一个socket相关的错误,于是查相关资料。

ECONNABORTED错误的含义是 "software caused connection abort",看起来就是连接被意外关闭导致的错误。然后看到下面一段解释:

考虑这种情况: TCP连接被客户端夭折,即在服务器调用accept之前,客户端主动发送RST终止连接,导致刚刚建立的连接从就绪队列中移出 ,如果套接口被设置成阻塞模式,服务器就会一直阻塞在accept调用上,直到其他某个客户建立一个新的连接为止。但是在此期间,服务器单纯地阻塞在accept调用上,就绪队列中的其他描述符都得不到处理。

解决办法是把监听套接口设置为非阻塞,当客户在服务器调用accept之前中止某个连接时,accept调用可以立即返回-1,这时源自Berkeley的实现会在内核中处理该事件,并不会将该事件通知给epool,而其他实现把errno设置为ECONNABORTED或者EPROTO错误,我们应该忽略这两个错误。

看起来比较可信的解释(符合我所遇到的情况)是socket刚建立,客户端立即发送了RST;而这个错误看起来可以忽略?


资料:

  1. Epoll在LT和ET模式下的读写方式
  2. libuv源码分析
  3. What does ECONNABORTED mean when trying to connect a socket?

@creeperyang
Copy link
Owner Author

creeperyang commented Apr 8, 2017

10. 怎么处理 unhandled Promise rejections ?

2017-04-10 6 53 36

如图所示,程序执行时console里输出了两段警告,一个是UnhandledPromiseRejectionWarning,一个是PromiseRejectionHandledWarning

参考https://nodesource.com/blog/the-10-key-features-in-node-js-v6-lts-boron-after-you-upgrade/ 第4点:

  1. node.js v6.6.0 开始,未处理的Promise rejections除了触发unhandledRejection事件,同时会在console输出警告信息。(可以--no-warnings禁止输出警告,但不建议)
  2. catchthen(cb1, cb2) 可以处理rejection,并不再输出警告信息。
  3. 因为rejection handler可以在Promise创建后调用(catch),所以warning不会在reject之后event loop下个tick前输出或触发事件。(The 'unhandledRejection' event is emitted whenever a Promise is rejected and no error handler is attached to the promise within a turn of the event loop. )
var pm4 = Promise.reject(new Error('4'))
var pm5 = Promise.reject(new Error('5'))
var pm6 = Promise.reject(new Error('6'))

setTimeout(() => {
  pm4.catch((err) => {
    console.log(err.message);
  })
}, 0)
setImmediate(() => {
  pm5.catch((err) => {
      console.log(err.message);
  })
})
process.nextTick(() => {
  pm6.catch((err) => {
      console.log(err.message);
  })
})

// output
/*
6
(node:18580) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: 4
(node:18580) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: 5
(node:18580) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
4
(node:18580) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 2)
5
*/

看上面的例子,可以重点理解下第3点。

此外,更多信息 nodejs/node#830

@creeperyang
Copy link
Owner Author

creeperyang commented May 24, 2017

11. https.get/request 请求 self-signed 的 https 服务器的失败问题。

leader想做个内部工具,需要接入公司的cas系统做用户登陆验证,内部文档提供的示例并不包括node.js

  1. 摸索了几十分钟,用connect-cas搭配express.js做个demo,总是显示unauthorized,看起来就像验证未通过,但跳转登陆的页面却没有显示(这种情况应该是已经登陆了)。
  2. 换用node-cas,检索源码,发现https.get有个rejectUnauthorized的配置。联想到公司内网都是自签名证书,于是明白,应该是证书校验没通过,直接失败了。果然,设置为false后成功拿到了用户信息。

rejectUnauthorized If true the server will reject any connection which is not authorized with the list of supplied CAs. This option only has an effect if requestCert is true. Defaults to false.


如果CAS (Central Authentication Service) SSO Server提供了SSL证书,那么我们可以设置ca选项来进行验证,而不用设置rejectUnauthorizedfalse

https.get({
      host: 'cas.xxxxx.com',
      port: 443,
      path: '/cas/validatePath?service=xxx',
      ca: [fs.readFileSync('./RootCertificateAuthority.crt')], // 证书
      rejectUnauthorized: true
}, callback)

参考:

  1. How to create required .pem certificates for HTTPS connection in node web server
  2. tls.connect(options[, callback])

@creeperyang
Copy link
Owner Author

creeperyang commented Jun 13, 2017

12. child_process.execError: stdout maxBuffer exceeded

最近为交互部门写的axure文档预览工具,需要从 gitlab 同步仓库。发现有时交互们 push 后网页显示的目录列表没有同步。

查看错误日志:

{ Error: stdout maxBuffer exceeded
     at Socket.<anonymous> (child_process.js:255:14)
     at emitOne (events.js:96:13)
     at Socket.emit (events.js:188:7)
     at readableAddChunk (_stream_readable.js:172:18)
     at Socket.Readable.push (_stream_readable.js:130:10)
     at Pipe.onread (net.js:542:20)
   cmd: 'cd /root/projects/UXD/lt && git reset HEAD --hard && git pull origin master' }

看起来是 exec 执行 pull 后报错,更新目录的逻辑执行不到了。

搜索后可知:child_process.exec 默认的 maxBuffer200KB ,而交互们提交文档的改动可能比我们想象的大多了(终端输出很多,超出了限制),修改 maxBuffer 后解决问题。

@creeperyang
Copy link
Owner Author

creeperyang commented Jun 14, 2017

13. The header content contains invalid characters

基于 koa 的 http server 跳转时遇到这样一个错误:

TypeError: The header content contains invalid characters
     at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:348:11)
     at Object.set (/root/projects/axure-site/node_modules/koa/lib/response.js:440:16)
     at Object.redirect (/root/projects/axure-site/node_modules/koa/lib/response.js:261:10)
     at Object.proto.(anonymous function) [as redirect] (/root/projects/axure-site/node_modules/delegates/index.js:40:31)
     at Promise.then (/root/projects/axure-site/server/middlewares/cas.js:34:22)
     at process._tickDomainCallback (internal/process/next_tick.js:129:7)

检查 _http_outgoing.js 的 348 行,可以知道 setHeader 报错,NODE_DEBUG=http node xxxxx.js 拿到更详细的报错信息:

HTTP 24366: Header "Location" contains invalid characters

到 koa 相关代码打日志:

-----koa----- Location http://0.0.0.0:5000/repos/htt/主流程_APP_1小时快速起飞预订流程_20170614_HTT/

所以错误的地方找到了,至于为什么错,直接看 node 源码:

/**
 * True if val contains an invalid field-vchar
 *  field-value    = *( field-content / obs-fold )
 *  field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
 *  field-vchar    = VCHAR / obs-text
 *
 * checkInvalidHeaderChar() is currently designed to be inlinable by v8,
 * so take care when making changes to the implementation so that the source
 * code size does not exceed v8's default max_inlined_source_size setting.
 **/
var validHdrChars = [
  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ...
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1  // ... 255
];

function checkInvalidHeaderChar(val) {
  val += '';
  if (val.length < 1)
    return false;
  if (!validHdrChars[val.charCodeAt(0)])
    return true;
  if (val.length < 2)
    return false;
  if (!validHdrChars[val.charCodeAt(1)])
    return true;
  if (val.length < 3)
    return false;
  if (!validHdrChars[val.charCodeAt(2)])
    return true;
  if (val.length < 4)
    return false;
  if (!validHdrChars[val.charCodeAt(3)])
    return true;
  for (var i = 4; i < val.length; ++i) {
    if (!validHdrChars[val.charCodeAt(i)])
      return true;
  }
  return false;
}
exports._checkInvalidHeaderChar = checkInvalidHeaderChar;


if (checkInvalidHeaderChar(value)) {
    debug('Header "%s" contains invalid characters', name);
    throw new TypeError('The header content contains invalid characters');
  }

最终发现是因为 Location 里有 汉字 报错了....

  1. 可以看到 header 的 value 只支持 部分 ascii 码
  2. encodeURI 转换 uri 后再 redirect 即可解决该错误。

@creeperyang
Copy link
Owner Author

creeperyang commented Dec 8, 2017

14. typescript 对 umd 的支持问题

详情见 microsoft/TypeScript#8436

一句话,"module": "umd" 时,编译后的代码里,umd 只有 commonjsamd 的兼容代码,并没有最后的 fallback:挂载到全局对象。

@creeperyang
Copy link
Owner Author

creeperyang commented Jun 20, 2018

15. npm 的 dependencies vs peerDependencies

  • dependencies很好理解,就是字面意思的依赖,一般会通过require在代码中引入使用;它是一种实现细节,是 "private" 的,即不会暴露给使用者。

  • 相反,peerDependencies是主动暴露给使用者知晓的,并且,一般情况下使用者也被预期会(需要)使用这些peerDependencies

下面以库 A 作为例子来解释:

比如你要写一个库 A,你想使用 lodash 提供的一些工具函数,那么,你会把lodash 加到 dependencies中(作为依赖)。但是,别人使用你的库 A 时,是不(用)知道你依赖了lodash的,因为这是一种实现细节,只要npm自动帮你安装lodash即可(A可以正常运行)。

但是,当你想写当库 A 是一个插件(比如 webpack 插件,或者 react 组件,或者其它类似),A 需要依赖某个框架 K 才能正常工作,通常情况下,(库 A)的使用者也会同时使用框架 K。这通常也没什么大问题,但是如果你依赖 K@v2 而使用者用了 K@v1,这可能会不兼容!所以,你需要通过一种方式告诉 A 的使用者,A 依赖K@v2 才能正常工作,这就是peerDependencies的作用。

npm@3之前,peerDependencies会被自动安装,但从3开始不会自动安装,只会输出警告信息。

@creeperyang
Copy link
Owner Author

16. [email protected] 的一个安全问题以及提高警惕

事件:[email protected]postinstall有一段可疑代码,会把用户本地的.npmrc 上传到远程服务器,即偷取token。

详情:Virus in eslint-scope?

结论:这个版本并不是官方团队所发布,很可能eslint团队的发布token被盗了... 目前该版本已被撤除,但值得大家警惕。

@creeperyang
Copy link
Owner Author

creeperyang commented Oct 22, 2018

17. git 快捷命令一览

  • 怎么查看stash中文件有哪些变化?

    git stash show -p stash@\{0\}

  • 怎么查看本次提交里的文件列表(改动/新增的文件,仅显示文件名)?

    git show --pretty="" --name-only

  • 增强的 git log --oneline (增加提交者名字)

    git log --pretty=format:'%h %Cgreen%ad %Cblue%an %Creset %s' --date=format:'%m-%d %H:%M:%S'

  • diff 时去除不必要的文件的内容细节

    比如diff两个独立开发很久的分支,我们可能不需要删除/新增文件的细节,这个时候,我们可以git diff --diff-filter=ACMRTUXB branch1..branch2 。具体细节可参考https://stackoverflow.com/questions/6894322/how-to-make-git-diff-and-git-log-ignore-new-and-deleted-files/41730200

@creeperyang
Copy link
Owner Author

creeperyang commented Feb 27, 2019

18. unix-like 系统的文件权限

image

我们用 chmod 修改权限:

rwx rwx rwx = 111 111 111
rw- rw- rw- = 110 110 110
rwx --- --- = 111 000 000

---

rwx = 111 in binary = 7
rw- = 110 in binary = 6
r-x = 101 in binary = 5
r-- = 100 in binary = 4

---

chmod 777 test  # test 文件权限改为 rwx rwx rwx

@creeperyang
Copy link
Owner Author

19. windows 安装某些 native 包时报错 ...\.node-gyp\10.12.0\x64\node.lib : fatal error LNK1127: 库已损坏

解决方案:替换 node.lib

去官网下载对应版本的 node.lib,比如我们这里是 https://nodejs.org/download/release/v10.12.0/win-x64/node.lib,替换C:\Users\name\.node-gyp\10.12.0\x64\node.lib即可。

@creeperyang
Copy link
Owner Author

20. windows 上查看端口占用和杀进程

查看 3000 端口占用,并显示 PID

# https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/netstat
netstat -ano | findstr "3000"

强行终止进程6620

taskkill -PID 6620 -F

@creeperyang creeperyang changed the title 框架/库使用问题,系统问题及其它问题 杂七杂八问题以及解决方案记录 Jun 12, 2019
@creeperyang
Copy link
Owner Author

creeperyang commented Jun 12, 2019

21. semver 版本控制规范的问题

[major, minor, patch]

Tilde Ranges ~1.2.3 ~1.2 ~1

波浪线(~),允许更新指定版本(位数)的后一位

  • 指定一位,允许更新第2位和第3位,~1 --> >=1.0.0 <2.0.0;
  • 指定2位,允许更新第3位,~1.2 --> >=1.2.0 <1.3.0;
  • 指定3位,允许更新第3位,~1.2.3 --> >=1.2.3 <1.3.0。

Caret Ranges ^1.2.3 ^0.2.5 ^0.0.4

Caret(^),允许不修改从左开始的第一位非零位的变动。

  • ^1.2.3 --> >=1.0.0 <2.0.0;
  • ^0.2.3 --> >=0.2.3 <0.3.0;
  • ^0.0.3 --> >=0.0.3 <0.0.4;

特别是对 ^0.2 这种而言,和我理解的 >=0.2 <1.0 不一致,需要特别注意。

@creeperyang
Copy link
Owner Author

21. React hydrate() 的问题

对服务器端渲染,我们通常要在客户端使用 hydrate() 复用SSR结果,并去处理事件绑定等。在实际使用时,碰到一个问题:客户端渲染得到的DOM有问题,元素的class/style和预期不一致。

查找原因后发现,问题出在服务端渲染和客户端渲染得到的VDOM tree不一致,而这个在hydrate()的使用中被视为bug。

@creeperyang
Copy link
Owner Author

22. localStorage 存满导致的问题

查一个线上问题,感觉代码没任何问题:

function run() {
doA(); // 理解为当且仅当全局变量 GGG 没值时提示操作
localStorage.setItem('key', value);
doB();  // 理解为设置GGG的值(当且仅当该变量GGG未赋值时设置值)
}

上面的 run 多次执行时反复提示操作,开始觉得代码没任何问题。排除所有的可能后,唯一的不可能就是可能:localStorage.setItem 出错了,导致 doB 没执行。

  • 可能浏览器隐私模式导致报错?测试后发现不是;
  • 最后得出 localStorage 达到容量上限,直接报错了,一查,果然有极少量 setitem exceeded the quota 报错。

@creeperyang
Copy link
Owner Author

23. Error: ES Modules may not assign module.exports or exports.*, Use ESM export syntax

babel 的报错,解决办法:代码中不要混用import/exportrequire/module.exports

@18boys
Copy link

18boys commented Feb 18, 2023 via email

@creeperyang
Copy link
Owner Author

24. webpack@5 和 @babel@7 的问题

For the selected environment is no default script chunk format available:
JSONP Array push can be chosen when 'document' or 'importScripts' is available.
CommonJs exports can be chosen when 'require' or node builtins are available.

image

image
删除browserslist 中node相关配置即可,从错误来看,node和browser都配置,会让webpack无法确定默认的script chunk format

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants