开发笔记

前言

本博客用来记录在工作中遇到的各种疑难杂症及对应的解决方案,方便遇到同样问题时的检索。
问题及解决方案汇总:

  1. React.js + Next.js + i18next 报错:Module parse failed: Unexpected token (290:73) You may need an appropriate loader to handle this file type.
  2. 利用 JSON.parse 进行解析的时候报错 ‘Unexpected token i in JSON at position 1’.
  3. 使用 forEach 对数组进行循环改变数组本身的值,然后并没有生效.
  4. React.js + Next.js 跳转页面没问题,使用 safari 前进后退键的时候报错,使用 chrome 没问题.
  5. 部分浏览器打开页面时报错:Object.assign is not a function.
  6. 发送请求时控制栏报错:TypeError: Failed to execute ‘fetch’ on ‘Window’: Value is not a valid ByteString.

正文

1. React.js + Next.js + i18next 报错:Module parse failed: Unexpected token (290:73) You may need an appropriate loader to handle this file type.

问题描述

官网个人版的数据直接放到重构的机构版时系统报错。由于分工不同,机构版将不同功能分割出来了,把共用部分放在了 common 中,其余不同模块分为了不同的项目,每个项目都是一个单独的 next.js 项目。需要引用项目外的共用文件的时候就利用 bindfs 来进行映射。
errorImg

1
2
3
4
5
6
7
8
9
10
11
|--- common
| - file
| - file
|--- project A
| - file
| - file
| - next.conf.js
|--- project B
| - file
| - file
| - next.conf.js

解决方案

由于和之前的项目相比并没有做过多的改动,但只要一启动就报这种错误,然后用关键词 Module parse failed: Unexpected token (290:73) You may need an appropriate loader to handle this file type。搜出来结果很多,基本上都是和 webpack 配置相关,然后我反思了下这两个项目都没有配置过 webpack,所以应该不是这里面出现的问题。左看右看,终于找到一条让我眼前一亮的答案:

1
Next only compiles files inside of the next root, which in your case is root/server. You can probably use something like 3732 to compile files outside of the root.

原文链接:Spread Operator not building – Webpack #3819
看到这个答案后,将所有链接到项目外的路径改成项目内就好了。

2. 利用 JSON.parse 进行解析的时候报错 ‘Unexpected token i in JSON at position 1’

问题描述

系统有部分数据保存在 mongoDB 中,取出的数据很多时候会是字符串形式,这时候最普遍的得到具体数据的方式是利用 JSON.parse 来进行解析。大部分的时候都能成功解析,也存在有些时候会出现描述中的错误,这时候就需要分析其中的原因了。

解决方案

这个问题其实是因为需要解析的不是一个有效的 JSON 对象导致的,以下引用自 JSON.parse unexpected token s :

What you are passing to JSON.parse method must be a valid JSON after removing the wrapping quotes for string.
so something is not a valid JSON but “something” is.
A valid JSON is -

1
2
3
4
5
6
7
8
9
10
> JSON = null
> /* boolean literal */
> or true or false
> /* A JavaScript Number Leading zeroes are prohibited; a decimal point must be followed by at least one digit.*/
> or JSONNumber
> /* Only a limited sets of characters may be escaped; certain control characters are prohibited; the Unicode line separator (U+2028) and paragraph separator (U+2029) characters are permitted; strings must be double-quoted.*/
> or JSONString
/* Property names must be double-quoted strings; trailing commas are forbidden. */
or JSONObject
or JSONArray

Examples -

1
2
3
4
5
6
JSON.parse('{}'); // {}
JSON.parse('true'); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null'); // null
JSON.parse("'foo'"); // error since string should be wrapped by double quotes

You may want to look JavaScript and JSON differences

说了这么多,那我们应该怎么去处理这种情况呢?其实很简单,用 try…catch 就行了。如果是合法的 JSON 对象就解析,如果不是则不进行处理。

3. 使用 forEach 对数组进行循环改变数组本身的值,然后并没有生效

问题描述

利用 forEach 进行循环然后遍历改变原数组的需求非常常见,但稍有使用不当就会造成并没有改变原数据的结果,这主要是因为下面这个原因。

4. React.js + Next.js 跳转页面没问题,使用 safari 前进后退键的时候报错,使用 chrome 没问题

问题描述

因为在 safari 中没找到简单快捷的操纵 cookie 的方法(在 chrome 中利用扩展 editThisCookie 很方便,在 safari 中可以直接在 console 中加入 cookie,但总归不方便),所以开发的时候一直都是在 chrome 中。项目上线后在 safari 中也测了测,没有发现问题,直到有一天同事告诉我所有的页面在后退的时候都会出现报错页面,而且只会出现在 Safari 中。百思不解,首先想到的是浏览器的兼容性,也找了很多相关的内容来看,有文章提到是因为返回的时候从缓存里面拿数据的原因,并没有提到具体的解决措施。然后想到如果真的是这个原因,那么之前做的个人版应该也会有同样的问题,所以就测了下之前的个人版,发现却并没有这个问题,所以就把思考的重点转移到了分模块打包上。在 next.js 项目的 issue 中找了找也没有找到相关的内容,问题暂时搁置。
大概两天后,老板说点击工商页面的时候也出现了报错页面,好像突然就有灵感了!联想到之前也有同事告诉我点击链接的时候会报错,给了我一个新思路:从链接入手!然后在官方文档上看到这么一句话:For the initial page load, getInitialProps will execute on the server only. getInitialProps will only be executed on the client when navigating to a different route via the Link component or using the routing APIs. 到这其实已经心中有数了。之前一直认为 getInitialProps 只会在服务器端执行,所以为了辨识用户身份,将服务器相关的参数传入到了这个函数中,然后在通过 Link 组件或者前进后退的时候,这个函数也会执行,然而此时找不到在函数中使用的参数(如 process 对象),所以系统持之以恒的报错!想到这点,问题便迎刃而解了。

5. 部分浏览器打开页面时报错:Object.assign is not a function.

问题描述

有客户在微信打开我们的网页时发现空白页,测试发现在safari,chrome,firefox下都是没问题的。分析发现微信内置的浏览器版本对应于chrome43版本左右,版本过低导致不支持es6语法导致。问题分析到这就迎刃而解了,在next.js项目下搜索browser顺利找到解决方案。

1
2
3
4
5
6
7
8
9
10
const originalEntry = newConfig.entry
newConfig.entry = async () => {
const entries = await originalEntry()

if (entries['main.js'] && !entries['main.js'].includes('./polyfills.js')) {
entries['main.js'].unshift('./polyfills.js')
}

return entries
}

1
2
3
4
5
6
7
8
9
10
//  polyfills.js

/* eslint no-extend-native: 0 */
// core-js comes with Next.js. So, you can import it like below

import 'core-js'

// Add your polyfills
// This files runs at the very beginning (even before React and Next.js core)
// console.log('Load your polyfills')

6. 发送请求时报错 TypeError: Failed to execute ‘fetch’ on ‘Window’: Value is not a valid ByteString.

问题描述

组内的一个小伙伴在发送请求的时候发生了这种错误,我拉完代码后却什么问题都没有。

解决方案

推测有可能导致的原因:本地node版本,项目依赖包的版本,浏览器版本,用户信息等等。在一一排除这些因素后,项目启动还是会出现报错。网上搜索了下,没有找到特别符合的同类错误。因为使用的是 isomorphic-fetch 来请求数据的,所以也把源码稍微打开看了下,并没有找到这种类型的报错。几乎放弃的时候想起来有人提过这种错误可能是在请求中有中文导致的,逐一去检查,终于发现了原来是同事在cookie中添加了未编码的中文名,编码后重新尝试,终于好了。

7. 命令行提示本地项目启动,浏览器打开却不行

问题描述

尝试进行接口测试,本地部署的时候需要运行node服务,随便填了个端口:6666。

解决方案

多次重启未果,猜测可能是端口的原因,网上一查还真是。在chrome中6666端口被禁用的,其他被禁用的端口如下:

1: // tcpmux
7: // echo
9: // discard
11: // systat
13: // daytime
15: // netstat
17: // qotd
19: // chargen
20: // ftp data
21: // ftp access
22: // ssh
23: // telnet
25: // smtp
37: // time
42: // name
43: // nicname
53: // domain
77: // priv-rjs
79: // finger
87: // ttylink
95: // supdup
101: // hostriame
102: // iso-tsap
103: // gppitnp
104: // acr-nema
109: // pop2
110: // pop3
111: // sunrpc
113: // auth
115: // sftp
117: // uucp-path
119: // nntp
123: // NTP
135: // loc-srv /epmap
139: // netbios
143: // imap2
179: // BGP
389: // ldap
465: // smtp+ssl
512: // print / exec
513: // login
514: // shell
515: // printer
526: // tempo
530: // courier
531: // chat
532: // netnews
540: // uucp
556: // remotefs
563: // nntp+ssl
587: // stmp?
601: // ??
636: // ldap+ssl
993: // ldap+ssl
995: // pop3+ssl
2049: // nfs
3659: // apple-sasl / PasswordServer
4045: // lockd
6000: // X11
6665: // Alternate IRC [Apple addition]
6666: // Alternate IRC [Apple addition]
6667: // Standard IRC [Apple addition]
6668: // Alternate IRC [Apple addition]
6669: // Alternate IRC [Apple addition]

赠人玫瑰,手有余香