前端工程化:有效地进行拼写检查

check.png

拼写错误导致的问题

在项目开发过程中,即使我们再细心,也难免忙中出错,犯下很多低级的错误。

比如这样:

https://cdn.nlark.com/yuque/0/2021/png/187192/1637554381755-7a93e5fa-4d56-4c45-8a7e-a3ee8afaf120.png

我们错把 field 拼写成 filed,这样打印出来的是 undefined,而不是预期的 name。

ESLint 的基本介绍

但是幸运的是,有一些 Lint 工具会在这方面提供一些帮助。

比如在 TypeScript 中,会有一个错误提示。虽然这个提示提供的消息并不是我们需要的。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637554498186-c63a984c-8bd1-47db-9cae-da887f8c6419.png

当然我们可以选择一些更专业的 Linter 来完成这项工作。

目前来说,最流行的 JavaScript Linter 是 ESLint。

如果配合 VSCode 这个编辑器使用的话,可以安装 vscode-eslint 这个插件。

然后在项目的根目录下创建 .eslintrc.js 文件,编写一些配置。

/** @type {import('eslint').Linter.Config} */
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  rules: {
    "no-undef": ["error"],
  },
};

env 属性指定项目的运行环境。

rules 是具体的规则。

no-undef 这条规则的意思是不可以使用未定义的变量。

no-undef 属性的值是一个数组,数组的第一个元素是这条规则的级别。

ESLint 中的所有规则都有 3 个等级,off 表示关闭,wran 表示警告和 error 表示错误。

你可以根据自己对代码要求的严格程度自定义规则等级。

当我们配置好了这条规则之后,编辑器的错误提示就会发生变化。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637556545092-7b9d2f2c-5762-415f-a1f7-2c81f5497a73.png

ESlint 会给我们提示 filed 这个变量没有被定义,而被直接使用了。

这样就可以帮助我们发现这个问题,从而更早的解决掉这个问题。

这是一种比较容易发现的问题。

声明变量时的单词拼写错误

另一个更加隐秘晦涩的错误是,我们在定义变量时就把变量的单词拼写错了。

比如下面这样:

https://cdn.nlark.com/yuque/0/2021/png/187192/1637556762829-d7c0de00-6b98-4d32-8020-32a453d18a24.png

这种问题 ESLint 是没有办法检测到的,而且真正运行起来也不会有什么问题。

最大的问题在于维护。

假设这段代码的维护者换成了别人,他很难一眼看出这段代码究竟在表达什么意思。

filed?是文件的过去式,表达的意思是归档吗?

他压根就不可能会朝 field,也就是字段的含义上去考虑。

这会让接下来的整个逻辑流程阅读起来变得非常费解。

这种问题属于根源性的问题。

人工解决方案

解决办法当然存在,建立业务术语表,然后经过人工代码审查(CodeReview)。

但是,人在真正意义上是不靠谱的。

即使再强大、再细致的人,也会有焦急、疲倦、松懈的时候。所以即使是通过人工代码审查后的代码,也未必不会存在上面提到的这种问题。

机器解决方案

那么能够有一种更好的方式来避免这类问题呢?

比如能否依靠在真正意义上靠谱的机器来协助人类做这件事情?

当然是可以的。

ESLint 有一套插件机制,可以通过插件来扩展 ESLint 原本的功能。

其中有一个比较常用的插件,eslint-plugin-spellcheck。

这个插件的作用是帮助我们检查单词的拼写错误。

安装也非常简单。

npm install eslint-plugin-spellcheck

之后需要更新 ESLint 的配置。

/** @type {import('eslint').Linter.Config} */
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  plugins: [
    "spellcheck",
  ],
  rules: {
    "no-undef": ["error"],
    "spellcheck/spell-checker": ['warn']
  },
};

这样就可以对代码中单词拼写错误的。

拼写错误与意图表达错误

但是,讲了这么多,像上面提到的反例,spell-checker 仍然是无能为力的。

为什么呢?因为上面提到的反例,表面上看只有一个错误,但无形之中还存在另一个错误。

  1. 拼写错误,field 拼写成了 filed。
  2. filed 仍然是个正确的单词。如果将 filed 认为是一个正确的单词,那么第二个错误将是意图表达错误

机器只能解决拼写错误,但是意图表达错误这类问题明显超越了机器目前的能力边界。

所以我们可以把反例稍微改一下。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637561785501-5360d42c-9c69-41a8-8abe-24e9e1ea8d15.png

filde 不是一个合法单词,所以就得到 spell-checker 的警告提示。

spell-checker 的实现原理

spell-checker 的实现原理就是罗列出超过 4 万个英文单词进行匹配,如果不在这个范围内的英文单词就认为是拼写错误。

当然我们也可以扩展这个单词列表。

ESLinter 的 rules 中属性值都是一个数组。第一个元素是规则级别,第二个元素就是一个对象,表示这个规则对应的配置项。

spell-checker 的配置项中有一个 skipWords,表示可以跳过一些单词。

跳过特殊单词

比如你在使用 ESModule 的方式来开发应用,其中用到了 Vue 这个库。

我们需要在 .eslintrc.js 中添加一项配置,让 ESLint 的解释器以模块的方式解释代码。

module.exports = {
  // ...
  parserOptions: {
    sourceType: 'module'
    }
}

但是 Vue 并不是一个合法的单词。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637562416234-72841ced-645c-44e3-9886-2cb8efb1d6b7.png

我们就可以通过配置这个配置项来跳过对 Vue 的检测。

module.exports = {
  rules: {
    "spellcheck/spell-checker": [
      "warn",
      {
        skipWords: ["Vue"],
      },
    ],
}

这样代码就不会再出现警告了。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637562561650-591c1dbc-3306-4986-ae03-45ed37b6c1e4.png

但是到目前为止,问题还是没有完全解决。

因为一些库中提供的 API 仍然不是合法单词。比如 Teleport。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637562760129-273fcca8-cc7d-472c-83cc-ac503d7f84d3.png

我们可以选择手动添加 Teleport 这个单词到 skipWords 中。

但问题是,Vue 中仍然提供了很多 API 不在合法单词范围内,比如 withCtx:

https://cdn.nlark.com/yuque/0/2021/png/187192/1637564045719-5bc4b334-e06f-4d8f-b270-6abff1db7c5a.png

如果我们碰到哪个单词就朝 skipWords 里面添加哪个单词,在使用的库比较少的时候还可以接受。如果我们的项目中依赖了大量的库,而这些库中又存在了大量的不合法单词 API,这会让我们感到非常的繁琐和痛苦。

另外一个问题就是,Node.js 很多内置模块的 API 同样不是合法单词。比如常用的 fs 和 readdir。

https://cdn.nlark.com/yuque/0/2021/png/187192/1637597758485-ee2d4fbd-3d7b-4ef8-9919-5538ee87f83e.png

那有没有什么方法可以解决上面的两个问题呢?

答案是有的。

modules-words

modules-words 是一个获取模块 API 单词的库,通过这个库配合 spell-checker 可以很好的帮助我们跳过很多第三方模块或者 Node.js 内置模块的 API 单词检查。

首先安装这个模块。

npm add modules-words --save-dev

之后修改 .eslintrc.js 配置文件。

const { getWords, getGlobalWords } = require("modules-words");

/** @type {import('eslint').Linter.Config} */
module.exports = {
  // ...
  rules: {
        // ...
    "spellcheck/spell-checker": [
      "warn",
      {
        skipWords: ["", ...getWords("vue"), ...getGlobalWords()],
      },
    ],
  },
};

通过 modules-words 提供的 getWords 和 getGlobalWords 两个函数,成功地将项目中可能使用到的单词过滤出来,让 spell check 能够以更加符合我们预期的方式运行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容