Giter Site home page Giter Site logo

blog's Issues

渣渣灰手摸手带你提高项目的代码质量

大家好,我是渣渣灰~
本文的目标是为你介绍典型的前端项目中是如何做代码检查(lint)和代码美化(prettier),并说明其原理。 如果你觉得太复杂不想看,那请直接使用 umi-lint

为什么

在协同合作的项目中,如果没有统一的代码规范和约定,每个人都按照自己的心情去写代码,那最终项目将变的很难维护。

保证代码质量是每个工程师应该尽到的责任 @yutingzhao1991

方案

在社区中,常见的最佳实践是分两部分

  1. 全局检查,一般用于手动执行或是 ci(持续集成)时检查,如果有问题会提示 ci 不通过。
  2. 代码提交时检查,只对提交的代码进行检查,并美化和自动修复,如果存在有问题的代码,git 会阻止提交,从根源杜绝垃圾代码入库。

涉及的包

  • eslint js 和 ts 代码检查工具
  • stylelint css 代码检查工具
  • tslint typescript 代码检查工具,已不再推荐。原因
  • prettier 代码美化工具
  • husky git 钩子创建工具,我们使用的是 precommit 钩子,在提交代码(git commit)时候会触发。
  • lint-staged 只对需要提交的代码进行检查

如何做

我们以上一篇教程渣渣灰手摸手带你开发一个组件库代码为示例项目,接入代码质量规范相关工具。

配置 eslint

代码界的纪检委,eslint 的核心是通过一系列的 rules 规则来定制代码规范,在社区中已经沉淀很多典型的规则集,形成了不同的风格。umi 的规则集 eslint-config-umi 主要是基于 create-react-app,再沉淀了一部分我们自己的规则,并且支持 ts,推荐使用。

Tips: 为了更好的使用 eslint,在代码编辑器安装相应插件会实时显示错误

安装

$ yarn add eslint eslint-config-umi --dev

新建配置文件 .eslintrc

{
    "extends": "umi"
}

package.json 添加 scripts,让 eslint 扫描 src/ 目录

"scripts": {
+    "lint": "eslint src/"
}

执行命令

$ yarn run lint

因为没有不规范写法,所以执行完没有错误,但我们修改 src/Foo/index.js,随便写一句 hello = 1 再执行

yarn run v1.13.0
$ eslint src

/Users/puwei/Code/github.com/clock157/umi-library-demo/src/Foo/index.js
  3:1  error  'hello' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)

error Command failed with exit code 1.

就会提醒你 no-undef 未定义错误,通过这个错误码你可以在 eslint 官网找到相应解决方案。

配置 prettier

代码界的美图秀秀,可以自动的帮你处理一些格式问题,诸如 tab,单双引号,换行,空格等。

安装

$ yarn add prettier --dev

新建配置文件 .prettierrc, 我们常用的配置

{
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100
}

package.json 添加 scripts,自动美化 src/

"scripts": {
	"lint": "eslint src",
+   "prettier": "prettier --write 'src/**/*.{js,jsx}'"
}

运行一次

yarn run v1.13.0
$ prettier --write 'src/**/*.{js,jsx}'
src/Foo/index.js 66ms
src/Foo/index.test.js 15ms
src/index.js 8ms
✨  Done in 0.37s.

快去看看,代码是否已经闪闪发亮 😁

提交时检查代码

社区最佳的实践是在代码提交时进行检查,这样就杜绝了垃圾代码进入代码库,具体的配置需要涉及两个工具:huskylint-staged

安装

$ yarn add husky lint-staged --dev

Tips: husky 在安装时会在 .git/hooks 下创建一系列钩子,请确保安装时你的项目已经 git init 过,否则可能不会生效。

配置 package.json

"scripts": {
    "lint": "eslint src",
    "prettier": "prettier --write 'src/**/*.{js,jsx}'",
+   "precommit": "lint-staged"
},
+"lint-staged": {
+    "*.{js,jsx}": ["eslint --fix", "prettier --wirte", "git add"]
+}

这段代码的意思就是在代码提交前执行 lint-staged, 检查待提交的 jsjsx 文件,对它们分别执行 eslint, prettier, 会尝试修复比如少个分号这种,如果不能修复就会报错阻断提交。

Let's Try

$ git add src/Foo/index.js
$ git commit -m 'test'

结果,提交失败,你需要改到没有错误才能提交。

husky > pre-commit (node v8.11.1)
  ↓ Stashing changes... [skipped]
    → No partially staged files found...
  ❯ Running linters...
    ❯ Running tasks for *.{js,jsx}
      ✖ eslint
        prettier --wirte
        git add

✖ eslint found some errors. Please fix them and try committing again.

/Users/puwei/Code/github.com/clock157/umi-library-demo/src/Foo/index.js
3:1  error  'hello' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)

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

至此,代码的检查与美化就处理好了。本篇完整示例代码

结语

lint 的确可以让代码更好看和维护,但是配置过程还是有点麻烦,特别是每次新开一个项目都需要重新配置一次,极其繁琐,那我们怎么简化操作呢?

答案就是封装,我们封装了umi-lint,你只需要两步就可以做到这一切,乃至更多。

安装

yarn add umi-lint --dev

使用

package.json 添加

"scripts": {
+   "lint": "umi-lint src/",
+   "precommit": "umi-lint --staged --stylelint --prettier --fix",
}

收工👏

交流

有什么疑问,可以在钉钉群交流

渣渣灰手摸手带你开发一个组件库

大家好, 我是渣渣灰~
本文的目标是带你开发一个组件库,并走通开发、测试、文档、打包还有发布流程。

准备环境

如果你想快速开始,也可以直接使用我们的脚手架

涉及工具:umi-library

初始化项目

# 创建目录
$ mkdir umi-library-demo && cd umi-library-demo

# 初始化
$ yarn init -y

# 安装依赖
$ yarn add umi-library --save-dev

添加配置文件 .umirc.library.js

export default {
  entry: 'src/index.js',
  esm: 'rollup',
  cjs: 'rollup'
}

package.json 添加 script:

+ "scripts": {
+    "doc:dev": "umi-lib doc dev"
+ },

这时, 你已经可以通过以下命令跑起来:

$ yarn run doc:dev

浏览器访问 http://127.0.0.1:8001/,即可看到我们的组件开发环境。

开发组件

规划目录结构, 入口为 src/index.jsFoo为我们的第一个组件

.
├── .umirc.library.js		# 配置
├── package.json
└── src
    ├── Foo					# 组件
    │   └── index.js
    └── index.js			# 入口

Foo 组件代码如下:

// src/Foo/index.js
import * as React from 'react';

export default function(props) {
  return (
    <button
      style={{
        fontSize: props.size === 'large' ? 40 : 20,
      }}
    >
      { props.children }
    </button>
  );
}

接下来跑一下我们的组件,在 src/Foo 目录下创建 index.mdx,基于 mdx,你可以使用 markdownjsx 语法来组织文档。

---
name: Foo
route: /
---

import { Playground } from 'docz';
import Foo from './';

# Foo Component

## Normal Foo

<Foo>Hi</Foo>

## Large Foo with playground

<Playground>
    <Foo size="large">Hi</Foo>
</Playground>

再看下我们的开发环境,可以看到组件效果
屏幕快照 2019-02-06 23.26.51

组件测试

为了保证组件质量,我们需要引入组件测试,测试方案可以直接使用 umi-test

$ yarn add umi-test --save-dev

src/Foo 目录新建测试文件 index.test.js

import { shallow } from 'enzyme';
import Foo from './index.js';

describe('<Foo />', () => {
    it('render Foo', () => {
        const wrapper = shallow(<Foo size="large">hello, umi</Foo>);
        expect(wrapper.prop('style').fontSize).toEqual(40);
        expect(wrapper.children().text()).toEqual('hello, umi');
    });
});

然后在 package.jsonscripts 添加测试命令

  "scripts": {
    "doc:dev": "umi-lib doc dev",
+   "test": "umi-test"
  },

执行测试命令

$ yarn run test

执行结果,测试通过!

 PASS  src/Foo/index.test.js
  <Foo />
    ✓ render Foo (39ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        11.701s
Ran all test suites.
✨  Done in 15.82s.

组件打包

组件开发测试完成后,需要打包成不同的产物以适应不同的场景。默认使用 rollup 打包生成三个格式的包:

  • cjs: CommonJs,能被 Node 和 打包工具如 webpack 使用。
  • esm: ES Module,支持静态分析可以 tree shaking。
  • umd: Universal Module Definition 通用包,既能像 cjs 一样被使用,也可以发布到 cdn,通过 script 的方式被浏览器使用。

修改 package.json

-  "main": "index.js",
+  "main": "dist/index.js",
+  "module": "dist/index.esm.js",
   "scripts": {
    "doc:dev": "umi-lib doc dev",
+   "dev": "umi-lib build --watch",
+   "build": "umi-lib build",
    "test": "umi-test"
  },

使用命令

# 监控文件变化并打包
$ yarn run dev

# 打包
$ yarn run build

打包结果

$ yarn run build
yarn run v1.13.0
$ umi-lib build

ℹ  info      Clean dist directory
ℹ  info      Build cjs with rollup
ℹ  info      Build esm with rollup
✨  Done in 2.75s.

验证产物

为了验证我们的产物是否可用,我们可以基于 umi 创建一个小 demo 使用一下,,在项目下创建目录 example,目录结构:

example/
└── pages
    └── demo-foo
        └── index.js

我们创建了 demo-foo 这个页面, 并使用 Foo 组件,其 index.js 代码:

import { Foo } from '../../../dist';

export default function() {
    return (
        <Foo size="large">hello, world</Foo>
    );
}

我们跑一下

$ cd example
$ umi dev

# 如果没有 umi 这个命令, 请安装
$ yarn global add umi

启动好以后,console 会提示访问地址,打开后访问页面 /demo-foo,就可以看到效果:
组件效果

发布组件

组件开发好,发布到 npm registry 就可以被大家使用,也可以发布到私有 registry 内部使用。如果没有 npm 账号需要先注册,然后登陆 yarn login

修改 package.json,添加发布 script,发布前执行测试用例,并且包里只含 dist 目录:

+ "files": ["dist"],
  "scripts": {
+   "pub": "yarn run test && yarn publish",
    "test": "umi-test"
  },

执行命令

$ yarn run pub

发布成功后,你就可以在 npm 看到 umi-library-demo

对于其他用户,就可以使用以下命令来安装使用这个包。

# 使用 yarn
$ yarn add umi-library-demo --save

#使用 npm
$ npm install umi-library-demo --save

发布文档

在我们的组件开发完毕,文档相应写完后我们需要打包和部署文档,以便使用者查阅。

首先修改 package.json,添加 script:

  "scripts": {
    "doc:dev": "umi-lib doc dev",
+   "doc:build": "umi-lib doc build",
+   "doc:deploy": "umi-lib doc deploy",
  },

umi-library 默认将文档部署到 github.io, url 规则是 https://{yourname}.github.io/{your-repo},我们需要修改 .umirc.library.js 配置一下文档静态资源的前缀base

export default {
  entry: 'src/index.js',
  esm: 'rollup',
  cjs: 'rollup',
+ doc: {
+   base: '/umi-library-demo'
+ }
}

接下来执行命令:

# 打包文档
$ yarn run doc:build

# 部署文档, 速度取决于网速
$ yarn run doc:deploy

部署成功后,以这个项目为例, 文档地址为:

https://clock157.github.io/umi-library-demo/

结语

示例完整代码

至此, 发布一个组件库的流程::搭建、开发、测试、打包、验证、发布、文档整个流程就走通了,在实际的开发过程中,你可能会遇到更多的问题,或者你对这篇教程有不理解的地方,都可以反馈我们。

钉钉群

这是手摸手系列第一篇, 本系列旨在为前端开发者服务, 探索前端开发的最佳实践. 后面会陆续出更多的教程, 欢迎留言提出你宝贵的建议和想了解的点.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.