字节面试官不想录取的暗示,从零开始配置 TypeScript 项目,全网首发

本项目会构建输出 CommonJS 工具包(npm 包)供外部使用,采用 TypeScript 设计并输出声明文件有助于外部更好的使用该资源包进行 API 的提示。TypeScript 编译采用官方文档推荐的 Gulp 工具并配合 gulp-typescript 和 tsconfig.json 配置文件。在根目录下新建 tsconfig.json 文件并新增以下配置:

{

“compilerOptions”: {

// 指定 ECMAScript 目标版本 “ES3”(默认), “ES5”, “ES6” / “ES2015”, “ES2016”, “ES2017” 或 “ESNext”。

“target”: “ES5”,

// 构建的目标代码删除所有注释,除了以 /!* 开头的版权信息

“removeComments”: true,

// 可配合 gulp-typescript 生成相应的 .d.ts 文件

“declaration”: true,

// 启用所有严格类型检查选项。启用 --strict 相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict, --strictNullChecks, --strictFunctionTypes 和 --strictPropertyInitialization

“strict”: true,

// 禁止对同一个文件的不一致的引用

“forceConsistentCasingInFileNames”: true,

// 报错时不生成输出文件

“noEmitOnError”: true

}

}

温馨提示:这里没有新增 module 配置信息,因为默认输出 CommonJS 规范,更多关于 TypeScript 配置信息可查看TypeScript 官方文档 / 编译选项。如果对于 CommonJS 和 ES modules 的区别不是很清晰,这里有一些非常好的文档可以供大家阅读:ES modules: A cartoon deep-dive、ES6 modules。如果想了解如何对外提供 ES Module 可以查看 pkg.module。

同时在根目录下新建 gulpfile.js 文件:

const gulp = require(“gulp”);

const ts = require(“gulp-typescript”);

const tsProject = ts.createProject(“tsconfig.json”);

// 输出 CommonJS 规范到 dist 目录下

gulp.task(“default”, function () {

const tsResult = tsProject.src().pipe(tsProject());

return tsResult.js.pipe(gulp.dest(“dist”));

});

package.json 中新增 npm script 脚本:

“scripts”: {

“build”: “rimraf dist && gulp”

},

其中 rimfaf 用于在构建之前清除 dist 目录文件内容。此时在 src 目录下新增 TypeScript 源码并使用 npm run build 命令可以进行项目构建并输出 CommonJS 规范的目标代码到 dist 目录下。

除此之外,此项目希望可以快速生成声明文件供外部进行代码提示,此时仍然可以借助 gulp-typescript 工具自动生成声明文件。在 gulpfile.js 中新增以下配置

const gulp = require(“gulp”);

const ts = require(“gulp-typescript”);

const tsProject = ts.createProject(“tsconfig.json”);

const merge = require(“merge2”);

// 输出 CommonJS 规范到 dist 目录下

gulp.task(“default”, function () {

const tsResult = tsProject.src().pipe(tsProject());

return merge([

tsResult.dts.pipe(gulp.dest(“types”)),

tsResult.js.pipe(gulp.dest(“dist”)),

]);

});

修改 build 命令使其在构建之前同时可以删除 types 目录:

“scripts”: {

“build”: “rimraf dist types && gulp”,

},

再次执行 npm run build 会在项目根目录下生成 types 文件夹,该文件夹主要存放自动生成的 TypeScript 声明文件。

需要注意发布 npm 包时默认会将当前项目的所有文件进行发布处理,但这里希望发布的包只包含使用者需要的编译文件 disttypes,因此可以通过package.json 中的 files(用于指定发布的 npm 包包含哪些文件) 字段信息进行控制:

“files”: [

“dist”,

“types”

],

温馨提示:发布的 npm 包中某些文件将忽视 files 字段信息的配置,包括 package.jsonLICENSEREADME.md 等。

除此之外,如果希望发布的 npm 包通过 require('algorithms-utils')import 形式引入时指向 dist/index.js 文件,需要配置 package.json 中的 main 字段信息:

“main”: “dist/index.js”

温馨提示:对于工具包使用全量引入的方式并不是一个好的选择,可以通过具体的工具方法进行按需引入。

ESLint

ESLint 背景

TypeScript 的代码检查工具主要有 TSLint 和 ESLint 两种。早期的 TypeScript 项目一般采用 TSLint 进行检查。TSLint 和 TypeScript 采用同样的 AST 格式进行编译,但主要问题是对于 JavaScript 生态的项目支持不够友好,因此 TypeScript 团队在 2019 年宣布全面转向 ESLint(具体可查看 TypeScript 官方仓库的 .eslintrc.json 配置),更多关于转向 ESLint 的原因可查看:

  • https://medium.com/palantir/tslint-in-2019-1a144c2317a9

  • https://github.com/microsoft/TypeScript/issues/30553

TypeScript 和 ESLint 使用不同的 AST 进行解析,因此为了在 ESLint 中支持 TypeScript 代码检查需要制作额外的自定义解析器(Custom Parsers,ESLint 的自定义解析器功能需要基于 ESTree),目的是为了能够解析 TypeScript 语法并转成与 ESLint 兼容的 AST。@typescript-eslint/parser 在这样的背景下诞生,它会处理所有 ESLint 特定的配置并调用 @typescript-eslint/typescript-estree 生成 ESTree-compatible AST(需要注意不仅仅兼容 ESLint,也能兼容 Prettier)。

@typescript-eslint 是一个采用 Lerna 进行设计的 Monorepo 结构仓库,除了上述提到的 npm 包之外,还包含以下两个重要的 npm 包:

  • @typescript-eslint/eslint-plugin: 配合 @typescript-eslint/parser 一起使用的 ESLint 插件,可以设置 TypeScript 的校验规则。

  • @typescript-eslint/eslint-plugin-tslint: TSLint 向 ESLint 进行迁移的插件。

温馨提示:如果你正在使用 TSLint,并且你希望兼容 ESLint 或者向 ESLint 进行过渡(TSLint 和 ESLint 并存), 可查看 Migrating from TSLint to ESLint。除此之外,以上所介绍的这些包发布时版本一致(为了联合使用的兼容性),需要额外注意@typescript-eslint 对于 TypeScript 和 ESLint 的版本支持性,更多可查看 @typescript-eslint/parser 的仓库信息。

ESLint 配置

从背景的介绍中可以理解,对于全新的 TypeScript 项目(直接抛弃 TSLint)需要包含解析 AST 的解析器 @typescript-eslint/parser 和使用校验规则的插件 @typescript-eslint/eslint-plugin,这里需要在项目中进行安装:

npm i --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

在根目录新建 .eslintrc.js 配置文件,并设置以下配置:

module.exports = {

root: true,

parser: “@typescript-eslint/parser”,

plugins: [“@typescript-eslint”],

extends: [“eslint:recommended”, “plugin:@typescript-eslint/recommended”],

};

其中:

  • parser: '@typescript-eslint/parser':使用 ESLint 解析 TypeScript 语法

  • plugins: ['@typescript-eslint']:在 ESLint 中加载插件 @typescript-eslint/eslint-plugin,该插件可用于配置 TypeScript 校验规则。

  • extends: [ ... ]:在 ESLint 中使用共享规则配置,其中 eslint:recommended 是 ESLint 内置的推荐校验规则配置(也被称作最佳规则实践),plugin:@typescript-eslint/recommended 是类似于 eslint:recommended 的 TypeScript 推荐校验规则配置。

温馨提示:如果你稍微阅读一下 recommanded 源码你会发现,其实内部可以理解为推荐校验规则的集合。因此如果想基于 @typescript-eslint/eslint-plugin 进行自定义规则,则可参考 TypeScript Supported Rules。

配置完成后在 package.json 中设置校验命令

“scripts”: {

“lint”: “eslint src”,

}

此时如果在 src 目录下书写错误的语法,执行 npm run lint 就会输出错误信息:

eslint src

C:\Code\Git\algorithms\src\greet.ts

2:16 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types

✖ 1 problem (0 errors, 1 warning)

温馨提示:输出的错误信息是通过 ESLint Formatters 生成,查看 ESLint 源代码并调试可发现默认采用的是 stylish formatter 。

ESLint 插件

如果不使用插件,很难发现代码可能存在 TypeScript 格式错误,因为在书写代码的时候除了手动执行 npm run lint 以外没有任何的实时提示信息(你当然也可以通过 gulp监听文件的变化并执行 npm run lint)。为了可以实时看到 TypeScript 错误信息,可以通过 VS Code 插件进行处理。安装 ESLint 插件后可进行代码的实时提示,具体如下图所示:

当然为了防止不需要被校验的文件出现校验信息,可以通过 .eslintignore 文件进行配置(例如以下都是一些不需要格式校验的配置文件):

gulp

gulpfile.js

eslint

.eslintrc.js

commitizen

commitlint.config.js

jest

jest.config.js

build

dist

此时可以发现之前执行 lint 命令的错误通过插件的形式可实时在 VS Code 编辑器中进行显示。除此之外,一些 ESLint 的格式校验错误(例如多余的; 等)可通过配置 Save Auto Fix 进行保存自动格式化处理。具体 VS Code 的配置可参考 ESLint 插件 的文档说明,这边应该需要进行如下配置:

“editor.codeActionsOnSave”: {

“source.fixAll”: true,

“source.fixAll.eslint”: true

}

温馨提示:VS Code 的配置分为两种类型(用户和工作区),针对上述通用的配置主要放在用户里,针对不同项目的不同配置则可以放入工作区进行处理。

ESLint 确保构建

VS Code 插件并不能确保代码上传或构建前无任何错误信息,此时仍然需要额外的流程能够避免错误。在构建前进行 ESLint 校验能够确保构建时无任何错误信息,一旦 ESLint 校验不通过则不允许进行源码的构建操作:

“scripts”: {

“lint”: “eslint src --max-warnings 0”,

“build”: “npm run lint && rimraf dist types && gulp”,

}

需要注意在构建时进行校验的严格控制,一旦 lint 抛出 warning 或者 error 则立马终止构建(详情可查看 ESLint 退出代码)。

温馨提示:需要注意 Shell 中的 &&& 是有差异的,&& 主要用于继发执行,只有前一个任务执行成功,才会执行下一个任务,& 主要用于并发执行,表示两个脚本同时执行。这里构建的命令需要等待 lint 命令执行通过才能进行,一旦 lint 失败那么构建命令将不再执行。

ESLint 确保代码上传

尽管可能配置了 ESLint 的校验脚本 以及 VS Code 插件,但是有些 ESLint 的规则校验是无法通过 Save Auto Fix 进行格式化修复的(例如质量规则),因此还需要一层保障能够确保代码提交之前所有的代码能够通过 ESLint 校验,这个配置将在 Lint Staged 中进行讲解。

Prettier

Prettier 背景

Prettier 是一个统一代码格式风格的工具,如果你不清楚为什么需要使用 Prettier,可以查看 Why Prettier?。很多人可能疑惑,ESLint 已经能够规范我们的代码风格,为什么还需要 Prettier?在 Prettier vs Linters 中详细说明了两者的区别,Linters 有两种类型的规则:

  • 格式规则(Formatting rules):例如 max-len、keyword-spacing 以及 no-mixed-spaces-and-tabs 等

  • 质量规则(Code-quality rules):例如 no-unused-vars、no-implicit-globals 以及 prefer-promise-reject-errors 等

ESLint 的规则校验同时包含了 格式规则质量规则,但是大部分情况下只有 格式规则 可以通过 --fix 或 VS Code 插件的 Sava Auto Fix 功能一键修复,而 质量规则 更多的是发现代码可能出现的 Bug 从而防止代码出错,这类规则往往需要手动修复。因此 格式规则 并不是必须的,而 质量规则 则是必须的。Prettier 与 ESLint 的区别在于 Prettier 专注于统一的格式规则,从而减轻 ESLint 在格式规则上的校验,而对于质量规则 则交给专业的 ESLint 进行处理。总结一句话就是:Prettier for formatting and linters for catching bugs!(ESLint 是必须的,Prettier 是可选的!)

需要注意如果 ESLint(TSLint) 和 Prettier 配合使用时格式规则有重复且产生了冲突,那么在编辑器中使用 Sava Auto Fix 时会让你的一键格式化哭笑不得。此时应该让两者把各自注重的规则功能区分开,使用 ESLint 校验质量规则,使用 Prettier 校验格式规则,更多信息可查看 Integrating with Linters。

温馨提示:在 VS Code 中使用 ESLint 匹配到相应的规则时会产生黄色波浪线以及红色文件名进行错误提醒。Prettier 更希望你对格式规则无感知,从而不会让你觉得有任何使用的负担。如果想要了解更多 Prettier,还可以查看 Prettier 的背后思想 Option Philosophy,个人认为了解一个产品设计的哲学能更好的指导你使用该产品。

Prettier 配置

首先安装 Prettier 所需要的依赖:

npm i prettier eslint-config-prettier --save-dev

其中:

  • eslint-config-prettier: 用于解决 ESLint 和 Prettier 配合使用时容易产生的格式规则冲突问题,其作用就是关闭 ESLint 中配置的一些格式规则,除此之外还包括关闭 @typescript-eslint/eslint-plugineslint-plugin-babeleslint-plugin-reacteslint-plugin-vueeslint-plugin-standard 等格式规则。

理论上而言,在项目中开启 ESLint 的 extends 中设置的带有格式规则校验的规则集,那么就需要通过 eslint-config-prettier 插件关闭可能产生冲突的格式规则:

{

“extends”: [

“plugin:@typescript-eslint/recommended”,

// 用于关闭 ESLint 相关的格式规则集,具体可查看 https://github.com/prettier/eslint-config-prettier/blob/master/index.js

“prettier”,

// 用于关闭 @typescript-eslint/eslint-plugin 插件相关的格式规则集,具体可查看 https://github.com/prettier/eslint-config-prettier/blob/master/%40typescript-eslint.js

“prettier/@typescript-eslint”,

]

}

配置完成后,可以通过命令行接口运行 Prettier:

“scripts”: {

“prettier”: “prettier src test --write”,

},

--write 参数类似于 ESLint 中的 --fix(在 ESLint 中使用该参数还是需要谨慎哈,建议还是使用 VS Code 的 Save Auto Fix 功能),主要用于自动修复格式错误。此时书写格式的错误代码:

import great from “@/greet”;

// 中间这么多空行

export default {

great,

};

执行 npm run prettier 进行格式修复:

PS C:\Code\Git\algorithms> npm run prettier

algorithms-utils@1.0.0 prettier C:\Code\Git\algorithms

prettier src test --write

src\greet.ts 149ms

src\index.ts 5ms

test\greet.spec.ts 11ms

修复之后的的文件格式如下:

import great from “@/greet”;

export default {

great,

};

需要注意如果某些规则集没有对应的 eslint-config-prettier 关闭配置,那么可以先通过 CLI helper tool 检测是否有重复的格式规则集在生效,然后可以通过手动配置 eslintrc.js 的形式进行关闭:

PS C:\Code\Git\algorithms> npx eslint --print-config src/index.ts | npx eslint-config-prettier-check

No rules that are unnecessary or conflict with Prettier were found.

例如把 eslint-config-prettier 的配置去除,此时进行检查重复规则:

PS C:\Code\Git\algorithms> npx eslint --print-config src/index.ts | npx eslint-config-prettier-check

The following rules are unnecessary or might conflict with Prettier:

  • @typescript-eslint/no-extra-semi

  • no-mixed-spaces-and-tabs

The following rules are enabled but cannot be automatically checked. See:

https://github.com/prettier/eslint-config-prettier#special-rules

  • no-unexpected-multiline

此时假设 eslint-config-prettier 没有类似的关闭格式规则集(例如本项目中配置的 plugin:jest/recommended 可能存在规则冲突),那么可以通过配置 .eslintrc.js 的形式自己手动关闭相应冲突的格式规则。

温馨提示:ESLint 可以对不同的文件支持不同的规则校验, 因此 --print-config 只能对应单个文件的冲突格式规则检查。由于通常的项目是一套规则对应一整个项目,因此对于整个项目所有的规则只需要校验一个文件是否有格式规则冲突即可。

Prettier 插件

通过命令行接口 --write 的形式可以进行格式自动修复,但是类似 ESLint,我们更希望项目在实时编辑时可以通过保存就能自动格式化代码(鬼知道 --fix 以及 --write 格式了什么文件,当然更希望通过肉眼的形式立即感知代码的格式化变化),此时可以通过配置 VS Code 的 Prettier - Code formatter 插件进行 Save Auto Fix,具体的配置查看插件文档。

Prettier 确保代码上传

和 ESLint 一样,尽管可能配置了 Prettier 的自动修复格式脚本以及 VS Code 插件,但是无法确保格式遗漏的情况,因此还需要一层保障能够确保代码提交之前能够进行 Prettier 格式化,这个配置将在 Lint Staged 中讲解,更多配置方案也可以查看 Prettier - Pre-commit Hook。

Lint Staged

Lint Staged 背景

在 Git Commit Message 中使用了 commitlint 工具配合 husky 可以防止生成不规范的 Git Commit Message,从而阻止用户进行不规范的 Git 代码提交,其原理就是监听了 Git Hook 的执行脚本(会在特定的 Git 执行命令诸如 commitpushmerge 等触发之前或之后执行相应的脚本钩子)。Git Hook 其实是进行项目约束非常好用的工具,它的作用包括但不限于:

  • Git Commit Message 规范强制统一

  • ESLint 规则统一,防止不符合规范的代码提交

  • Prettier 自动格式化(类似的还包括 Style 样式格式等)

  • 代码稳定性提交,提交之前确保测试用例全部通过

  • 发送邮件通知

  • CI 集成(服务端钩子)

Git Hook 的钩子非常多,但是在客户端中可能常用的钩子是以下两个:

  • pre-commit:Git 中 pre 系列钩子允许终止即将发生的 Git 操作,而post 系列往往用作通知行为。pre-commit 钩子在键入提交信息(运行 git commitgit cz)前运行,主要用于检查当前即将被提交的代码快照,例如提交遗漏、测试用例以及代码等。该钩子如果以非零值退出则 Git 将放弃本次提交。当然你也可以通过配置命令行参数 git commit --no-verify 绕过钩子的运行。

  • commit-msg:该钩子在用户输入 Commit Message 后被调用,接收存有当前 Commit Message 信息的临时文件路径作为唯一参数,因此可以利用该钩子来核对 Commit Meesage 信息(在 Git Commit Message 中使用了该钩子对提交信息进行了是否符合 Angular 规范的校验)。该钩子和 pre-commit 类似,一旦以非零值退出 Git 将放弃本次提交。

除了上述常用的客户端钩子,还有两个常用的服务端钩子:

  • pre-receive:该钩子会在远程仓库接收 git push 推送的代码时执行(注意不是本地仓库),该钩子会比 pre-commit 更加有约束力(总会有这样或那样的开发人员不喜欢提交代码时所做的一堆检测,他们可能会选择绕过这些钩子)。pre-receive 钩子可用于接收代码时的强制规范校验,如果某个开发人员采用了绕过 pre-commit 钩子的方式提交了一堆 ??? 一样的代码,那么通过设置该钩子可以拒绝代码提交。当然该钩子最常用的操作还是用于检查是否有权限推送代码、非快速向前合并等。

  • post-receive:该钩子在推送代码成功后执行,适合用于发送邮件通知或者触发 CI 。

温馨提示:想了解更多 Git Hook 信息可以查看 Git Hook 官方文档 或 Git 钩子:自定义你的工作流。

需要注意初始化 Git 之后默认会在 .git/hooks 目录下生成所有 Git 钩子的 Shell 示例脚本,这些脚本是可以被定制化的。对于前端开发而言去更改这些示例脚本适配前端项目非常不友好(大多数前端开发同学压根不会设计 Shell 脚本,尽管这个对于制作工具是一件非常高效的事情),因此社区就出现了类似的增强工具,它们对外抛出的是简单的钩子配置(例如 ghooks 在 package.json 中只需要进行简单的钩子属性配置),而在内部则通过替换 Git 钩子示例脚本的形式使得外部配置的钩子可以被执行,例如 husky、ghooks 以及 pre-commit 等。

温馨提示:Git Hook 还可以定制脚本执行的语言环境,例如对于前端而言当然希望使用熟悉的 Node 进行脚本设计,此时可以通过在脚本文件的头部设置 #! /usr/bin/env node 将 Node 作为可执行文件的环境解释器,如果你之前看过 使用 NPM 发布和使用 CLI 工具 可能会对这个环境解析器相对熟悉,这里也给出一个使用 Node 解释器的示例:ghooks - hook.template.raw,ghooks 的实现非常简单,感兴趣的同学可以仔细阅读一些源码的实现。

介绍 Git Hook 是为了让大家清晰的认知到使用 Hook 可以在前端的工程化项目中做很多事情(本来应该放在 Git Commit Message 中介绍相对合适,但是鉴于那个小节引用了另外一篇文章,因此将这个信息放在本小节进行科普)。

之前提到使用 Git Hook 可以进行 ESLint 规范约束,因此大家其实应该能够猜到使用 pre-commit 钩子(当然需要借助 Git Hook 增强工具,本项目中一律选择 husky)配合 ESLint 可以进行提交说明前的项目代码规则校验,但是如果项目越来越大,ESLint 校验的时间可能越来越长,这对于频繁的代码提交者而言可能是一件相对痛苦的事情,因此可以借助 lint-staged 工具(听这个工具的名字就能够猜测 lint 的是已经放入 Git Stage 暂存区中的代码,ed 在英文中表明已经做过)减少代码的检测量。

Lint Staged 配置

使用 commitlint 工具可以防止生成不规范的 Git Commit Message,从而阻止用户进行 Git 代码提交。但是如果想要防止团队协作时开发者提交不符合 ESLint 规则的代码则可以通过 lint-staged 工具来实现。lint-staged 可以在用户提交代码之前(生成 Git Commit Message 信息之前)使用 ESLint 检查 Git 暂存区中的代码信息(git add 之后的修改代码),一旦存在 ??? 一样不符合校验规则的代码,则可以终止提交行为。需要注意的是 lint-staged 不会检查项目的全量代码(全量使用 ESLint 校验对于较大的项目可能会是一个相对耗时的过程),而只会检查添加到 Git 暂存区中的代码。根据官方文档执行以下命令自动生成配置项信息:

npx mrm lint-staged

需要注意默认生成的配置文件是针对 JavaScript 环境的,手动修改 package.json 中的配置信息进行 TypeScript 适配:

// 我们的哈士奇再次上场,这次它是要咬着你的 ESLint 不放了,这里我简称它的动作为 “咬 ???” ~~~

“husky”: {

“hooks”: {

“pre-commit”: “lint-staged”

}

},

“lint-staged”: {

// 这里需要注意 ESLint 脚本的 --max-warnings 0

// 否则就算存在 warning 也不会终止提交行为

// 这里追加了 Prettier 的自动格式化,确保代码提交之前所有的格式能够修复

“*.ts”: [“npm run lint”, “npm run prettier”]

}

此时如果将要提交的代码有 ??? , 则提交时会提示错误信息且提交会被强制终止:

husky > pre-commit (node v12.13.1)

[STARTED] Preparing…

[SUCCESS] Preparing…

[STARTED] Running tasks…

[STARTED] Running tasks for *.ts

[STARTED] npm run lint-strict

[FAILED] npm run lint-strict [FAILED]

[FAILED] npm run lint-strict [FAILED]

[SUCCESS] Running tasks…

[STARTED] Applying modifications…

[SKIPPED] Skipped because of errors from tasks.

[STARTED] Reverting to original state because of errors…

[SUCCESS] Reverting to original state because of errors…

[STARTED] Cleaning up…

[SUCCESS] Cleaning up…

× npm run lint-strict:

ESLint found too many warnings (maximum: 0).

npm ERR! code ELIFECYCLE

npm ERR! errno 1

npm ERR! algorithms-utils@1.0.0 lint-strict: eslint src --max-warnings 0 "C:/Code/Git/algorithms/src/greet.ts"

npm ERR! Exit status 1

npm ERR!

npm ERR! Failed at the algorithms-utils@1.0.0 lint-strict script.

npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

npm ERR! C:\Users\子弈\AppData\Roaming\npm-cache_logs\2020-07-11T07_25_39_102Z-debug.log

algorithms-utils@1.0.0 lint-strict C:\Code\Git\algorithms

eslint src --max-warnings 0 “C:/Code/Git/algorithms/src/greet.ts”

C:\Code\Git\algorithms\src\greet.ts

2:16 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types

2:34 warning Argument ‘name’ should be typed @typescript-eslint/explicit-module-boundary-types

✖ 2 problems (0 errors, 2 warnings)

husky > pre-commit hook failed (add --no-verify to bypass)

husky 在 package.json 中配置了 pre-commitcommit-msg 两个 Git 钩子,优先使用 pre-commit 钩子执行 ESLint 校验,如果校验失败则终止运行。如果校验成功则会继续执行 commit-msg 校验 Git Commit Message,例如以下是 ESLint 校验通过但是 Commit Message 校验失败的例子:

PS C:\Code\Git\algorithms> git commit -m “这是一个不符合规范的 Commit Message”

// pre-commit 钩子 ESLint 校验通过

husky > pre-commit (node v12.13.1)

[STARTED] Preparing…

[SUCCESS] Preparing…

[STARTED] Running tasks…

[STARTED] Running tasks for *.ts

[STARTED] npm run lint-strict

[SUCCESS] npm run lint-strict

[SUCCESS] Running tasks for *.ts

[SUCCESS] Running tasks…

[STARTED] Applying modifications…

[SUCCESS] Applying modifications…

[STARTED] Cleaning up…

[SUCCESS] Cleaning up…

// commit-msg 钩子 Git Commit Message 校验失败

husky > commit-msg (node v12.13.1)

⧗ input: 这是一个不符合规范的 Commit Message

✖ subject may not be empty [subject-empty]

✖ type may not be empty [type-empty]

✖ found 2 problems, 0 warnings

ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky > commit-msg hook failed (add --no-verify to bypass)

Jest

测试背景

如果对于测试的概念和框架不是特别清楚,这里推荐一些可查看的文章:

  • JavaScript 程序测试 - 全面的测试基础知识

  • New to front-end testing? Start from the top of the pyramid! - 重点可以了解一下测试金字塔和测试置信度

  • [译] JavaScript 单元测试框架:Jasmine, Mocha, AVA, Tape 和 Jest 的比较 - 单元测试框架对比中文版(2018)

  • JavaScript unit testing frameworks in 2020: A comparison - 单元测试框架对比英文版(2020)

除此之外,如果想了解一些额外的测试技巧,这里推荐一些社区的最佳实践:

  • javascript-testing-best-practices

  • ui-testing-best-practices

由于这里只是 Node 环境工具库包的单元测试,在对比了各个测试框架之后决定采用 Jest 进行单元测试:

  • 内置断言库可实现开箱即用(从 itexpect, Jest 将整个工具包放在一个地方)

  • Jest 可以可靠地并行运行测试,并且为了让加速测试进程,Jest 会优先运行之前失败的测试用例

  • 内置覆盖率报告,无需额外进行配置

  • 优秀的报错信息

温馨提示:前端测试框架很多,相比简单的单元测试,e2e 测试会更复杂一些(不管是测试框架的支持以及测试用例的设计)。之前使用过 Karma 测试管理工具配合 Mocha 进行浏览器环境测试,也使用过 PhantomJS 以及 Nightwatch(使用的都是皮毛),印象最深刻的是使用 testcafe 测试框架(复杂的 API 官方文档),除此之外如果还感兴趣,也可以了解一下 cypress 测试框架。

Jest 配置

本项目的单元测试主要采用了 Jest 测试框架。Jest 如果需要对 TypeScript 进行支持,可以通过配合 Babel 的形式,具体可查看 Jest - Using TypeScript,但是采用 Babel 会产生一些限制(具体可查看 Babel 7 or TypeScript)。由于本项目没有采用 Babel 进行转译,并且希望能够完美支持类型检查,因此采用 ts-jest 进行单元测试。按照官方教程进行依赖安装和项目初始化:

npm install --save-dev jest typescript ts-jest @types/jest

npx ts-jest config:init

子啊根目录的 ject.config.js 文件中进行 Jest 配置修改:

module.exports = {

preset: “ts-jest”,

testEnvironment: “node”,

// 输出覆盖信息文件的目录

coverageDirectory: “./coverage/”,

// 覆盖信息的忽略文件模式

testPathIgnorePatterns: [“/node_modules/”],

// 如果测试覆盖率未达到 100%,则测试失败

// 这里可用于预防代码构建和提交

coverageThreshold: {

global: {

branches: 100,

functions: 100,

lines: 100,

statements: 100,

},

},

// 路径映射配置,具体可查看 https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping

// 需要配合 TypeScript 路径映射,具体可查看:https://www.tslang.cn/docs/handbook/module-resolution.html

moduleNameMapper: {

“^@/(.*)$”: “/src/$1”,

},

};

需要注意路径映射也需要配置 tsconfig.json 中的 paths 信息,同时注意将测试代码包含到 TypeScript 的编译目录中。配置完成后在 package.json 中配置测试命令:

“scripts”: {

“lint”: “eslint src --max-warnings 0”,

“test”: “jest --bail --coverage”,

“build”: “npm run lint && npm run jest && rimraf dist types && gulp”,

}

需要注意 Jest 中的这些配置信息(更多配置信息可查看 Jest CLI Options):

  • bail 的配置作用相对类似于 ESLint 中的 max-warnings,设置为 true 则表明一旦发现单元测试用例错误则停止运行其余测试用例,从而可以防止运行用例过多时需要一直等待用例全部运行完毕的情况。

  • coverage 主要用于在当前根目录下生成 coverage 代码的测试覆盖率报告,该报告还可以上传 coveralls 进行 Github 项目的 Badges 显示。

温馨提示:Jest CLI Options 中的 findRelatedTests 可用于配合 pre-commit 钩子去运行最少量的单元测试用例,可配合 lint-staged 实现类似于 ESLint 的作用,更多细节可查看 lint-staged - Use environment variables with linting commands

在当前根目录的 test 目录下新建 greet.spec.ts 文件,并设计以下测试代码:

import greet from “@/greet”;

describe(“src/greet.ts”, () => {

it(“name param test”, () => {

expect(greet(“world”)).toBe(“Hello from world 1”);

});

});

温馨提示:测试文件有两种放置风格,一种是新建 test 文件夹,然后将所有的测试代码集中在 test 目录下进行管理,另外一种是在各个源码文件的同级目录下新建 __test__ 目录,进行就近测试。大部分的项目可能都会倾向于采用第一种目录结构(可以随便找一些 github 上的开源项目进行查看,这里 ts-test 则是采用了第二种测试结构)。除此之外,需要注意 Jest 通过配置 testMatchtestRegex 可以使得项目识别特定格式文件作为测试文件进行运行(本项目采用默认配置可识别后缀为 .spec 的文件进行单元测试)。

Jest 确保构建

单独通过执行 npm run test 命令进行单元测试,这里演示执行构建命令时的单元测试(需要保证构建之前所有的单元测试用例都能通过)。如果测试失败,那么应该防止继续构建,例如进行失败的构建行为:

PS C:\Code\Git\algorithms> npm run build

algorithms-utils@1.0.0 build C:\Code\Git\algorithms

npm run lint-strict && npm run jest && rimraf dist types && gulp

algorithms-utils@1.0.0 lint-strict C:\Code\Git\algorithms

eslint src --max-warnings 0

algorithms-utils@1.0.0 jest C:\Code\Git\algorithms

jest --coverage

PASS dist/test/greet.spec.js

FAIL test/greet.spec.ts

● src/greet.ts › name param test

expect(received).toBe(expected) // Object.is equality

Expected: “Hello from world 1”

Received: “Hello from world”

3 | describe(“src/greet.ts”, () => {

4 | it(“name param test”, () => {

5 | expect(greet(“world”)).toBe(“Hello from world 1”);

| ^

6 | });

7 | });

8 |

at Object. (test/greet.spec.ts:5:28)

----------|---------|----------|---------|---------|-------------------

| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |

| ---------- | --------- | ---------- | --------- | --------- | ------------------- |

| All files | 100 | 100 | 100 | 100 |

| greet.ts | 100 | 100 | 100 | 100 |

| ---------- | --------- | ---------- | --------- | --------- | ------------------- |

Test Suites: 1 failed, 1 passed, 2 total

Tests: 1 failed, 1 passed, 2 total

Snapshots: 0 total

Time: 3.45 s

Ran all test suites.

npm ERR! code ELIFECYCLE

npm ERR! errno 1

npm ERR! algorithms-utils@1.0.0 jest: jest --coverage

npm ERR! Exit status 1

npm ERR!

npm ERR! Failed at the algorithms-utils@1.0.0 jest script.

npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

npm ERR! C:\Users\子弈\AppData\Roaming\npm-cache_logs\2020-07-12T13_42_11_628Z-debug.log

npm ERR! code ELIFECYCLE

npm ERR! errno 1

npm ERR! algorithms-utils@1.0.0 build: npm run lint-strict && npm run jest && rimraf dist types && gulp

npm ERR! Exit status 1

npm ERR!

npm ERR! Failed at the algorithms-utils@1.0.0 build script.

npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

npm ERR! C:\Users\子弈\AppData\Roaming\npm-cache_logs\2020-07-12T13_42_11_673Z-debug.log

需要注意由于是并行(&&)执行脚本,因此执行构建命令时(npm run build)会先执行 ESLint 校验,如果 ESLint 校验失败那么退出构建,否则继续进行 Jest 单元测试。如果单元测试失败那么退出构建,只有当两者都通过时才会进行源码构建。

Jest 确保代码上传

除了预防不负责任的代码构建以外,还需要预防不负责任的代码提交。配合 lint-staged 可以防止未跑通单元测试的代码进行远程提交:

“scripts”: {

“lint”: “eslint src --max-warnings 0”,

“test”: “jest --bail --coverage”,

},

“lint-staged”: {

“*.ts”: [

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

最后

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

“lint-staged”: {

“*.ts”: [

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-n4Z09nLi-1712304907012)]
[外链图片转存中…(img-g2FJO4j3-1712304907012)]
[外链图片转存中…(img-vnsLlEsp-1712304907013)]
[外链图片转存中…(img-XsXnKAK4-1712304907013)]
[外链图片转存中…(img-MPBGiLMU-1712304907013)]
[外链图片转存中…(img-x9v0o1z6-1712304907014)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-d4T183It-1712304907014)]

最后

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TypeScript是一种由微软开发的开源编程语言,它是JavaScript的超集,可以在任何支持JavaScript的地方运行。TypeScript提供了静态类型检查、面向对象编程和模块化等特性,使得开发大型项目更加可靠和高效。 要搭建一个TypeScript项目,可以按照以下步骤进行: 1. 安装Node.js:首先需要安装Node.js,它是运行JavaScript的环境。你可以在Node.js官网上下载并安装适合你操作系统的版本。 2. 初始化项目:在命令行中进入你想要创建项目的目录,并执行以下命令来初始化一个新的Node.js项目: ``` npm init ``` 这将引导你填写一些项目信息,并生成一个`package.json`文件,用于管理项目的依赖和配置。 3. 安装TypeScript:执行以下命令来安装TypeScript: ``` npm install typescript --save-dev ``` 这将在项目中安装TypeScript,并将其添加到`devDependencies`中。 4. 创建TypeScript配置文件:在项目根目录下创建一个名为`tsconfig.json`的文件,并配置TypeScript编译器的选项。以下是一个简单的示例配置: ```json { "compilerOptions": { "target": "es5", "module": "commonjs", "outDir": "dist", "strict": true }, "include": [ "src/**/*.ts" ] } ``` 这个配置文件指定了编译目标为ES5,模块系统为CommonJS,输出目录为`dist`,并启用了严格模式。 5. 创建源代码目录:在项目根目录下创建一个名为`src`的目录,用于存放TypeScript源代码文件。 6. 编写TypeScript代码:在`src`目录下创建你的TypeScript源代码文件,并开始编写你的项目逻辑。 7. 编译TypeScript代码:在命令行中执行以下命令来编译TypeScript代码: ``` npx tsc ``` 这将使用TypeScript编译器将TypeScript代码转换为JavaScript,并将输出文件保存在`tsconfig.json`中配置的`outDir`目录中。 8. 运行项目:使用Node.js来运行编译后的JavaScript代码。例如,如果你的入口文件是`dist/index.js`,可以执行以下命令来运行项目: ``` node dist/index.js ``` 这样,你就成功搭建了一个TypeScript项目。接下来,你可以根据你的需求继续开发和扩展项目

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值