.gitattributes 是干嘛的
gitattributes 是一个文本文件,文件中的一行定义一个路径的若干个属性,主要用于定义每种文件的属性,以方便 git 帮我们统一管理。
.editorconfig 是干嘛的
.editorConfig和Prettier一样,都是用来配置格式化代码.该文件用来定义项目的编码规范,编辑器的行为会与.editorconfig 文件中定义的一致,并且其优先级比编辑器自身的设置要高,这在多人合作开发项目时十分有用而且必要。
.editorConfig 文件中的设置用于在基本代码库中维持一致的编码风格和设置,例如缩进样式、选项卡宽度、行尾字符以及编码等,而无需考虑使用的编辑器或 IDE。
circle.yml 是如何配置的
在创建.circleci/config.yml文件并将其提交到GitHub储库后,CircleCI会立即检查您的代码并运行配置好的测试代码。
每次job,ci都会启动一个容器来运行该job
version: 你要使用的ci版本 job: 你要执行的 job 清单,集合中的键为 job 的名称,值是具体执行 job 的内容,如果你使用工作流(workflows),则 job 的名称在配置文件中必须唯一,如果你不使用 工作流(workflows),则必须包含名称为build的 job 来作为用户提交代码时的默认 job。 docker : 是用来指定 CircleCI 当前 job 使用 docker, 其值image是指 docker 所使用的镜像,必要时你可以同时指定多个镜像,比如你的项目需要依赖 mysql 或者 redis。 第一个列出的容器为主容器,steps 都会在主容器中进行。 steps: 当前 job 要运行的 命令 (command) 列表 working_directory: 属性是用来定义steps 在哪个目录运行。
构建、测试
1.检出代码
- checkout
2.安装依赖
- run:
name: install dependences
command: yarn
3.缓存依赖
- save_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
paths:
-./node_modules
4.测试
- run:
name: test
command: yarn test:cov
分析一下 package.json 里面的字段都是干嘛的
参考:https://www.jianshu.com/p/39eb5624bad1
package.json文件是一个JSON对象,从后缀名.json就可以看出,该对象的每一个成员就是当前项目的一项设置。
配置字段详细剖析
name
package.json文件中最重要的就是name和version字段,这两项是必填的。名称和版本一起构成一个标识符,该标识符被认为是完全唯一的。对包的更改应该与对版本的更改一起进行。
name必须是字符串,不能以.或_开头,不能有大写字母,因为名称最终成为URL的一部分因此不能包含任何非URL安全字符。 npm官方建议我们不要使用与核心节点模块相同的名称。不要在名称中加js或node。如果需要可以使用engines来指定运行环境。
该名称会作为参数传递给require,因此它应该是简短的,但也需要具有合理的描述性。
"name": "cac",
version
Version项目版本号, x.x.x的格式, 符合语义化版本规则(遵循“大版本.次要版本.小版本”的格式规定),在项目每次发布时需提交新的且唯一版本号
"version": "6.0.0",
exports
exports 字段声明了一个对应关系,用 import "package" 和 import "package/sub/path" 会返回不同的模块。
这替换了默认返回 main 字段文件的行为。
根据模块的引用语法,来引用不同的文件:
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./index-compat.js"
},
"./package.json": "./package.json",
"./": "./"
},
description
项目描述信息,description是字符串,便于用户在npm上搜索到我们的项目
"description": "Simple yet powerful framework for building command-line apps.",
keywords
keywords是一个字符串组成的数组,便于用户在npm上搜索到我们的项目
"keywords":["node.js","vue", "element"],
homepage
homepage项目的主页地址。
"homepage": "https://github.com/owner"
license
项目许可证,让使用者知道如何使用此项目,有何权限来使用我们的模块,以及使用该模块有限制等
"license" : "BSD-3-Clause"
author,contributors
Author表示一个person对象
Contributors表示person的数组,相当于一群person
包含了作者及贡献者(我们的模块开发者以及众多贡献者)
一个对象中包含name、url和email
"author": { "name": "xiaoming", "email": "xiaoming@163.com", "url": " www.xiaoming.cn" } "contributors":[{"name":" xiaoming","email":" xiaoming2016@163.com ","url": " www.xiaoming.cn }] files
files是一个文件数组,描述了将软件包作为依赖项安装时要包括的条目。如果在数组里面声明了一个文件夹,那也会包含文件夹中的文件。某些特殊文件和目录也被包括或排除在外,无论它们是否存在于文件数组中。简而言之,下载依赖包所包含的文件
main
主文件,也是项目的入口文件,默认值是项目根目录下的index.js。
"main": "./index.js",
browser
如果要在客户端使用模块,则应使用browser字段来代替main字段。
bin
bin用来指定各个内部命令对应的可执行文件的位置。
"bin": {
"mybuild": "./bin/mybuild.js"
}
上面代码指定,mybuild命令对应的可执行文件为 bin 子目录下的 mybuild.js。当本地安装myapp时,Npm会寻找这个文件,在./node_modules/.bin/目录下建立符号链接(快捷方式)。在上面的例子中,mybuild.js会建立符号链接./node_modules/.bin/mybuild。 ./node_modules/.bin/`目录会在运行时加入系统的PATH变量,因此在运行npm时,就可以不带路径,直接通过命令来调用这些脚本。
npx mybuild 所有node_modules/.bin/目录下的命令,都可以用npm run [命令]或npx [命令]的格式运行。bin中引用的文件需以#!/usr/bin/envnode开头
man
用来指定当前模块的man文档的位置
"man" :[ "./doc/doc.1" ] directories
用来标识模块结构的方法,类似于commonjs包规范的介绍,想查看npm中的package.json,就可以看到doc、lib、man目录及位置
repository
代码存放的地址
"repository": {
"type" : "git",
"url" : "https://github.com/cacjs/cac"
}
scripts
scripts指定了运行脚本命令的npm命令行缩写
"scripts": {
"test": "jest", //测试
"test:cov": "jest --coverage",
"build:deno": "node -r sucrase/register scripts/build-deno.ts", // deno打包
"build:node": "rollup -c", //打包
"build": "yarn build:deno && yarn build:node",
"toc": "markdown-toc -i README.md",
"prepublishOnly": "npm run build && cp mod.js mod.mjs",
"docs:api": "typedoc --out api-doc --readme none --exclude "**/__test__/**" --theme minimal"
},
config
用于添加命令行的环境变量
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
devDependencies 和 dependencies
dependencies,依赖,这些安装包都是程序所依赖的包,需要发布到生产环境的.
dev即develop开发环境下的依赖。
--save参数表示将该模块写入dependencies属性,--save-dev表示将该模块写入devDependencies属性
例如安装axios
安装到开发环境 npm axios --save-dev
安装到生产环境 npm axios --save
区别:
devDependencies中的插件只用于开发环境,不用于生产环境,而dependencies是要发布到生产环境
的。比如babel有关的转化es6到es5的依赖只是开发环境下转化用,生产过程中是用不到,所以只用写
在devDependencies中,而像vue或element-ui这种实际运行会调用,得写在dependencies中。
版本前可以加上各种限制,主要有以下几种: 指定版本:比如1.2.2,遵循“大版本.次要版本.小版本”的格式规定,安装时只安装指定版本。
波浪号(tilde)+指定版本:比如~1.2.2,表示安装1.2.x的最新版本(不低于1.2.2),但是不安装1.3.x,也就是说安装时不改变大版本号和次要版本号。
插入号(caret)+指定版本:比如ˆ1.2.2,表示安装1.x.x的最新版本(不低于1.2.2),但是不安装2.x.x,也就是说安装时不改变大版本号。需要注意的是,如果大版本号为0,则插入号的行为与波浪号相同,这是因为此时处于开发阶段,即使是次要版本号变动,也可能带来程序的不兼容。
latest:安装最新版本。
举例说明下:
1.0.2 大于当前版本
=1.0.2 大于等于当前版本
<1.0.2 小于当前版本
<=1.0.2小于等于当前版本
~1.0.2 不低于1.0.2,但不改变大版本号和次要版本号
^1.0.2 不低于1.0,2, 但不改变大版本号
1.2.x 表示1.2.3 ,1.2.4版本都支持
peerDependencies
当我们开发一个模块的时候,如果当前模块与所依赖的模块同时依赖一个第三方模块,并且依赖的是两个不兼容的版本时就会出现问题。
比如,你的项目依赖A模块和B模块的1.0版,而A模块本身又依赖B模块的2.0版。
大多数情况下,这不构成问题,B模块的两个版本可以并存,同时运行。但是,有一种情况,会出现问题,就是这种依赖关系将暴露给用户。
最典型的场景就是插件,比如A模块是B模块的插件。用户安装的B模块是1.0版本,但是A插件只能和2.0版本的B模块一起使用。这时,用户要是将1.0版本的B的实例传给A,就会出现问题。因此,需要一种机制,在模板安装的时候提醒用户,如果A和B一起安装,那么B必须是2.0模块。
peerDependencies字段,就是用来供插件指定其所需要的主工具的版本
从npm 3.0版开始,peerDependencies不再会默认安装了
bundledDependencies
bundledDependencies是一个数组,指定发布时将定义的模块一起打包
{
"name": "vue-project",
"version": "1.0.0",
"bundledDependencies": [
"elementui", "echarts"
]
}
optionaldependencies
如果出现包找不到或者安装失败时,但又不影响npm继续运行,可将该包放在optionalDependencies对象中。
"optionalDependencies": {
"echarts": "^4.9.0"
}
表示的是定义的模块如果安装失败,不会在输入npm install时失败
engines
engines字段指明了该模块运行的平台,比如Node``的某个版本,或者npm的某个版本或者浏览器。
"engines": {"node" : ">=8.9.0 <12.x", "npm" : "~6.14.12" } os
指定你的项目将运行在什么操作系统上
"os" : [ "win32", "darwin", "linux" ], private
决定我们的项目是否会发布,如果设置为true,那么npm会拒绝发布
"private": true publishConfig
模块发布时生效,设置一些值的集合
通常publishConfig会配合private来使用,如果你只想让模块被发布到一个特定的npm仓库,如一个内部的仓库
"private": true,
"publishConfig": {
"tag": "1.0.0",
"registry": "https://registry.npmjs.org/",
"access": "public"
}
preferGlobal
表示在不安装为全局时给予显示警告
写一个库的 README 需要哪几个部分?
- 项目介绍
- 代码实现了什么功能?
- 该如何使用? (系统环境参数,部署要素,操作说明等)
- 代码组织架构是什么样的?(目录结构说明等)
- 版本更新内容摘要(这个非常重要)
分析 rollup.config.js
{
input: 'src/index.ts', // 输入
output: { // 输出的文件格式
format: dts || esm ? 'esm' : 'cjs',
file, // 输出的文件
exports: 'named',
},
plugins: [ // 利用插件处理
nodeResolvePlugin({
mainFields: dts ? ['types', 'typings'] : ['module', 'main'],
extensions: dts ? ['.d.ts', '.ts'] : ['.js', '.json', '.mjs'],
customResolveOptions: {
moduleDirectories: dts
? ['node_modules/@types', 'node_modules']
: ['node_modules'],
},
}),
!dts && require('@rollup/plugin-commonjs')(),
!dts &&
esbuildPlugin({
target: 'es2017',
}),
dts && dtsPlugin(),
].filter(Boolean),
}
分析一下 tsconfig 里面的配置项
{
"compilerOptions": {
"target": "es2015", // 目标语言的版本
"declaration": true, // 生成声明文件,开启后会自动生成声明文件
"declarationDir": "types", // 指定生成声明文件存放目录
"esModuleInterop": true, // 允许export=导出,由import from 导入
"pretty": true,
"moduleResolution": "node", // 模块解析策略,ts默认用node的解析策略,即相对的方式导入
"lib": ["es2015", "es2016.array.include"], // TS需要引用的库,即声明文件,es5 默认引用dom、es5、scripthost,如需要使用es的高级版本特性,通常都需要配置,如es8的数组新特性需要引入"ES2019.Array",
"allowSyntheticDefaultImports": true,
"stripInternal": true,
"noImplicitAny": true, // 不允许隐式的any类型
"noImplicitReturns": true, //每个分支都会有返回值
"noImplicitThis": true, // 不允许this有隐式的any类型
"noUnusedLocals": true, // 检查只声明、未使用的局部变量(只提示不报错)
"noUnusedParameters": true, // 检查未使用的函数参数(只提示不报错)
"noFallthroughCasesInSwitch": true, // 防止switch语句贯穿(即如果没有break语句后面不会执行)
"strictNullChecks": true, // 不允许把null、undefined赋值给其他类型的变量
"strictFunctionTypes": true, // 不允许函数参数双向协变
"strictPropertyInitialization": true, // 类的实例属性必须初始化
"alwaysStrict": true, // 在代码中注入'use strict'
"module": "commonjs", // 生成代码的模板标准
"outDir": "lib" // 指定输出目录
},
"include": ["src", "declarations.d.ts"],
"exclude": ["src/deno.ts"]
}
ts-jest 是解决什么问题的
安装依赖
主要就是四个库: jest、typescript自不必说,ts-jest是要用到的预处理器,@types/jest用于测试框架的类型推断。
yarn add -D jest typescript ts-jest @types/jest
生成配置
yarn ts-jest config:init
这里是利用 ts-jest 自动生成 jest.config.js 文件。生成的代码如下
// jest.config.js
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
运行
yarn jest
简单的单元测试用例:
describe("computed", () => {
it("happy path", () => {
const user = reactive({ age: 1 });
const age = computed(() => {
return user.age
});
expect(age.value).toBe(1);
});
});
})
分析一下 jest.config.js 这几个字段都有什么用?
参考:www.bilibili.com/read/cv1048…
module.exports = {
testEnvironment: 'node',
transform: { // 设置哪些文件中的代码是需要被相应的转译器转换成 Jest
'^.+\.tsx?$': 'ts-jest'
},
testRegex: '(/__test__/.*|(\.|/)(test|spec))\.tsx?$',
testPathIgnorePatterns: ['/node_modules/', '/dist/', '/types/'], // 用正则来匹配不用测试的文件
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] // 代表支持加载的文件名
CAC文档
安装CAC
yarn add cac
引入cac
src/cli.ts
import cac from 'cac'
// 从package.json中获取版本及名字
import { name, version } from '../package.json'
// 实例化cac
const cli = cac(name)
/**
* 定义异常处理公共函数
* @param err
*/
const onError = (err: Error): void => {
console.error(err.message)
process.exit(1)
}
// 监听未捕获的异常事件
process.on('uncaughtException', onError)
// 监听Promise未捕获的异常事件
process.on('unhandledRejection', onError)
cli
// 添加命令 ‘<>’ 中为必填项,'[]'中为选填项
.command('<template> [project]', 'Create new project from a template')
// 添加配置 --force 简写为 -f;
// 如果目标存在则覆盖
.option('-f, --force', 'Overwrite if the target exists')
// 添加配置 --offline 简写为 -o ;
// 是否使用本地模板
.option('-o, --offline', 'Try to use an offline template')
// 示例内容配置
.example(' # with an official template')
.example(` $ ${name} <template> [project]`)
.example(' # with a custom github repo')
.example(` $ ${name} <owner>/<repo> [project]`)
// 定义一个动作,传入一个回调函数
.action((template: string, project: string = '.', options) => {
console.log(template, project, options)
})
// -h, --help出现标志时输出帮助信息。
cli.help()
// -v, --version 出现标志时输出版本号。
cli.version(version)
cli.parse()
测试命令
# 默认命令
<projectName> template project -f -o
# 输出结果
# 第一个参数是传入的模板名字 第二个是项目名字 第三个是传入的options
template project { '--': [], f: true, o: true, force: true, offline: true }
# 帮助命令
<projectName> -h
<projectName> --help
# 输出结果
<projectName> v1.0.0
Usage:
$ <projectName> <template> [project]
Commands:
<template> [project] Create new project from a template
For more info, run any command with the `--help` flag:
$ <projectName> --help
Options:
-f, --force Overwrite if the target exists
-o, --offline Try to use an offline template
-h, --help Display this message
-v, --version Display version number
Examples:
# with an official template
$ <projectName> <template> [project]
# with a custom github repo
$ <projectName> <owner>/<repo> [project]
# 查看版本命令
<projectName> -v
<projectName> --version
# 输出结果
# <projectName>/1.0.0 darwin-x64 node-v13.13.0
\