内容简介:首先在npm官网进行注册登录运行
开发流程
初始化
首先在npm官网进行注册登录
运行 npm init ,可以通过命令行进行一些初始化的设置,如果想快速进行设置,可以运行 npm init -y ,会在项目的根目录生成一个package.json的文件,具体包含哪些配置可以参考官方文档,下面介绍一些常用的配置。
-
name:npm包的名称
-
version:包的版本号
-
description:对包的功能进行描述
-
main:包的入口文件,默认是index.js
-
repository:代码的托管信息,一般是github地址
-
keywords:关键字信息,便于包的搜索
-
author:作者
-
license:开源协议,一般是MIT和ISC
-
bugs:提bug的页面,默认是github的issue页面
-
homepage:项目的主页
最好增加README.md,用来对项目进行简单的说明,比如如何安装使用,以及一些api的介绍和例子。
在代码开发完成以后,在命令行进行npm登陆 npm login 。
最后使用 npm publish 对包进行发布。
代码规范
使用eslint,对JavaScript的书写规范做一定的限制,可以在一些通过配置的基础上增加一些团队自己的限制项。
使用stylelint对样式文件做一些规范化的工作,也可以根据团队的需要做一些定制化。
使用.editorconfig来配置编辑器的规范,保证缩进和换行等的一致性。
SemVer
SemVer的中文名称是语义化版本控制规范。npm默认使用SemVer来进行模块的版本控制。一个发布到npm的包要严格遵守SemVer的版本规范,不然会发布失败。
版本格式
主版本号.次版本号.修订号,可以用x.y.z的写法来简单表示。
-
修订号(patch):只有在做了向下兼容的修正时才可以递增,可以理解为bug fix版本
-
次版本号(minor):只有在新增了可以向下兼容的新功能的时候,才可以递增,可以理解为feature版本。
-
主版本号(major):只有在新增了无法向下兼容的API的时候,才可以递增。
先行版本
当要进行大版本迭代的时候,或者增加一些核心的功能,但又不能保证新版本百分之百正常,这个时候就可以发布先行版本。SemVer规范中使用alpha、beta和rc来修饰先行版本。
-
alpha:内部版本
-
beta:公测版本
-
rc:Release candiate,正式版本的候选版本
先行版本的版本号可以使用:1.0.0-alpha、1.0.0-beta.1、1.0.0- rc.1、1.0.0-0.3.7等。
版本号的优先级
进行版本号比较时,x、y、z依次比较
先行版本号的规则是rc > beta > alpha
1.0.0 < 2.0.0 < 2.1.0 < 2.1.1 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0- rc.1 < 1.0.0复制代码
更多内容可以看SemVer
husky & lint-staged
在项目中需要单测和对代码规范的校验,如果每次修改,都对项目的所有代码进行校验,会有性能和时间上的浪费;还有如果老项目没有接入单测和代码规范,那么如果对所有的代码都进行校验的话,会导致错误太多无法提交代码。现在项目中已经使用的方案是husky & lint-staged。
husky在安装的时候,会执行这个包的npm install这个script,对项目的Git钩子进行重写,我们就可以在git的钩子函数中做一些代码方面的校验工作。lint-staged这个库只会新加入暂存区的文件进行相关的操作,这样就可以优化触发操作的文件范围。
package.json
{
...
"scripts": {
"lint": "eslint --fix src/",
"lint:style": "stylelint --fix 'src/**/*.less'",
"test": "cross-env BABEL_ENV=test jest --colors --config .jest.js",
"pre-commit": "lint-staged"
},
"lint-staged": {
"ignore": [
"build/*",
"node_modules"
],
"linters": {
"src/*.js": [
"eslint --fix",
"git add"
],
"src/**/*.less": [
"stylelint --fix",
"git add"
],
"src/components/**/*.js": [
"jest --findRelatedTests --config .jest.js",
"git add"
],
"src/utils/*.js": [
"jest --findRelatedTests --config .jest.js",
"git add"
]
}
}
...
}
复制代码
git commit & changelog
规范化commit信息,有助于将修改的问题进行分类,快速定位修复的问题,并提取出有用的提交信息来生成最终的changelog文件。
社区中比较好的方案是commitizen和conventional-changelog。
commitizen
commitizen 用来规范commit message,比较主流是的是使用AngularJS的规范来编写commit message。
全局安装commitizen
sudo npm install -g commitizen复制代码
然后在项目里执行下面的语句,让commitizen支持AngularJS的message规范。
commitizen init cz-conventional-changelog --save-dev --save-exact复制代码
执行以后,会在项目的devDependencies加入cz-conventional-changelog这个依赖,并在package.json中加入如下的配置项
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}复制代码
完成上面的步骤以后,以后所有的git commit 命令都用git cz来替换。
AngularJS的提交风格如下
<type>(<scope>): <subject> // 空一行 <body> // 空一行 <footer>复制代码
由Header、Body和Footer三个部分组成,其中Header是必须的,Body和Footer都可以省略。
-
type表示commit的类型,有如下七种类型:
-
feat:新功能(feature)
-
fix:修补bug
-
docs:文档(documentation)
-
style: 格式(不影响代码运行的变动)
-
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
-
test:增加测试
-
chore:构建过程或辅助 工具 的变动
-
-
scope表示这次commit的影响范围
-
subject是commit的简单描述,不能超过50个字符
-
body是对这次commit的具体描述,可以是多行的
-
footer只用于两种情况
-
不兼容变动,如果是上个版本不兼容的改动,用BREAKING CHANGE作为开头
-
关闭 Issue,例如 Closes #234
-
生成changelog
如果所有的提交记录都符合AngularJS的规范,那么可以使用命令来自动生成changelog文件。
必须安装conventional-changelog-cli的依赖
npm install --save-dev conventional-changelog-cli
{
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0"
}
}复制代码
生成的文档只会收集type为feat、fix还有Breaking changes这三种类型的提交记录。
如果强制使用的话,可以 validate-commit-msg 来对commit message进行校验,如果格式不符合,就阻止提交。
如果不想使用规范化的提交,也可以使用下面的方法,收集所有的提交信息来生changelog。
gitCommitMsg.js
const { execFile } = require('child_process');
const fs = require('fs');
const path = require('path');
const formatOptions = ['log', '--pretty=format:%ad %cn committed %s %h', '--date=format:%Y-%m-%d'];
const writeStream = fs.createWriteStream(path.join(process.cwd(), 'CHANGELOG.md'));
const child = execFile('git', formatOptions, {
cwd: process.cwd(),
maxBuffer: Infinity,
});
child.stdout
.pipe(writeStream);复制代码
编译和打包
在项目开发的时候都是通过npm去安装第三方包到本地的node_modules里面,而且为了加快项目的构建速度,会忽略对node_modules里面模块的处理,所以这就需要我们在开发npm包的时候提前做好编译打包的工作。
一般来说,用于node环境的包,只要提供符合CMD规范的包即可,但是用于web的包,就需要提供更多的选项。
-
lib:符合commonjs规范的文件,一般放在lib这个文件夹里面,入口是mian
-
es:符合ES module对方的文件,一般放在es这个文件夹里面,入口是module
-
dist:经过压缩的文件,一般是可以通过script标签直接引用的文件
babel VS TypeScript
Babel是JavaScript的一个编译器,用来将ES6的代码转换成ES5的代码,关于babel更多的介绍可以参考之前的文章babel从入门到放弃。
TypeScript是JavaScript的一个超集,支持JavaScript的多有语法和语义,对于一些新的语法也会有及时的跟进,并且在此之上提供了更多额外的特性,比如静态类型和风丰富的语法。TS的代码也可以通过编译转换成正常的JavaScript代码,所有现在也有一种思路是用JavaScript的语法去进行开发,但是用TS的编译器对代码进行转换。
webpack VS rollup
webpack是现在主流的打包工具,有着活跃和庞大的社区支持。rollup号称是下一代打包方案,很多实验性的功能都是它最先实现的,比如scope hoisting 和tree shaking。webpack由于自己实现了一套类似于node的module方案,所以在打包文件的大小上以及文件的可读性上都存在一定的问题,而且相比于webpack复杂的配置文件,rollup的配置相来说更简单。所以库文件的打包比较好的方案是rollup + babel。
持续迭代
在一般的迭代过程中,步骤可能是
-
修改完本地代码以后,提交这次的修改,运行git add . && git commit && git push
-
修改package.json中的version字段,实现版本号的自增
-
运行git add . && git commit && git push
-
给这个版本打一个tag,git tag <package.version> && git push --tags
-
发布到npm,运行npm publish
npm version
npm version用来自动更新npm包的version,对SemVer的版本规范有很好的支持。
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]
例:初始版本为1.0.0
npm version prepatch //预备补丁版本号 v1.0.1-0
npm version prerelease //预发布版本号 v1.0.1-1
npm version patch //补丁版本号 v1.0.2
npm version preminor //预备次版本号 v1.1.0-0
npm version minor //次版本号 v1.1.0
npm version premajor //预备主版本号 v2.0.0-0
npm version major //主版本号 v2.0.0
常用的是 major , minor 和 patch ,分别对应规范中的x,y,z。
当仓库已经被git初始化了,那么运行 npm version 修改完版本号以后,还会运行git add 、git commit和git tag的命令,其中commit的信息默认是自改完的版本号。如果想自定义commit的信息,可以提供 -m 或者 —message 的选项,如果有"%s"的符号,会被替换为版本号。
npm version patch -m "Upgrade to %s for reasons"
npm version还支持pre和post的钩子,可以利用这两个钩子函数做一些自动化的配置。
在preversion这个钩子中,生成changelog文件,并将新生成的文件推入到缓存区中。
在postversion这个钩子中,进行仓库和tag的推送。
简化操作,可以做如下配置
{
"scripts": {
"simple": "node gitCommitMsg.js", //生成简单的changelog文件
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"preversion": "npm run changelog && git add CHANGELOG.md",
"postversion": "git push && git push --tags",
"x": "npm version major -m 'Upgrade version to %s '",
"y": "npm version minor -m 'Upgrade version to %s '",
"z": "npm version patch -m 'Upgrade version to %s '"
},
}复制代码
npm publish
和npm version一样,在执行npm publish这个命令的时候,npm会依次执行scripts中的prepublish、publish、postpublish的命令,如果有定义的话。
npm5的版本中,prepublish用来代替prepublishOnly这个钩子,只在publish之前进行调用,建议npm升级到5及以上的版本,保证钩子的一致性。
在包发布之前和之后,我们可以利用prepublish和postpublish这个两个钩子做一些相关的工作。
在开发中,我们都是使用ES6的语法来进行开发的,所以在发布的时候会涉及到代码的编译。一般的开源项目,比如redux、antd,都会提供最少三种的文件格式
1、经过压缩的dist文件,一般放在dist文件夹中,可以用script进行直接引用 2、符合commonjs规范的文件,一般放在lib文件夹中 3、符合ES6模块规范的文件,一般放在es文件夹中 4、符合umd通过规范的文件,在浏览器和node中都可以使用
所以具体的流程为:
-
prepublish,对包进行打包编译
-
publish,只发布编译后的文件
-
postpublish,删除编译生成的文件
"scripts": {
"es": "tools run es",
"lib": "tools run commonjs",
"dist:umd": "tools run dist:umd",
"dist:cjs": "tools run dist:cjs",
"dist:es": "tools run dist:es",
"dist:min": "tools run dist:min",
"compile": "npm run es && npm run lib",
"dist": "npm run dist:umd && npm run dist:cjs && npm run dist:es && npm run dist:min",
"prepublish": "npm run compile && npm run dist",
"postpublish": "rm -rf es && rm -rf lib && rm -rf dist",
}复制代码
npm tag
使用npm publish发布包的时候,会有一个--tag的选项,如果不提供的话,会默认设置为latest,并且在使用npm install某个包的时候,默认也会安装latest这个tag的包。
但是在进行包的迭代的时候,可能会需要发布不同的版本来做新功能的测试,这时候就需要结合SemVer和--tag来进行相应的处理。
npm publish --tag <tagname>
使用上面的命令,可以发布对应的dist-tag。
如果我们想进行下一个大版本的迭代,并用next的dist-tag来表示
npm publist --tag next
如果用户想安装这个tag下的包,可以使用下面的命令
npm install package@next
可以通过dist-tag来查看某个包的dist-tag
npm dist-tag ls redux latest: 4.0.0 next: 4.0.0-rc.1
当预发版本稳定以后,可以使用 npm dist-tag add beta latest 把预发版本设置为稳定版本。
最终的package#scripts
{
"lint": "eslint --fix src/",
"lint:style": "stylelint --fix 'src/**/*.less'",
"test": "cross-env BABEL_ENV=test jest --colors --config .jest.js",
"pre-commit": "lint-staged",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"preversion": "npm run changelog && git add CHANGELOG.md",
"postversion": "git push && git push --tags",
"x": "npm version major -m 'Upgrade version to %s '",
"y": "npm version minor -m 'Upgrade version to %s '",
"z": "npm version patch -m 'Upgrade version to %s '",
"es": "tools run es",
"lib": "tools run commonjs",
"dist:umd": "tools run dist:umd",
"dist:cjs": "tools run dist:cjs",
"dist:es": "tools run dist:es",
"dist:min": "tools run dist:min",
"compile": "npm run es && npm run lib",
"dist": "npm run dist:umd && npm run dist:cjs && npm run dist:es && npm run dist:min",
"prepublish": "npm run compile && npm run dist"
"postpublish": "rm -rf es && rm -rf lib && rm -rf dist",
}复制代码
Others
files & .npmignore & .gitignore
有三个方法可以控制npm发布的包中包含哪些文件
-
package.json#filesfiles字段是一个数组,用来表示可以包含哪些文件,格式和.gitignore的写法一样
-
.npmignore这个文件用来表示哪些文件将被忽略,格式和.gitignore的写法一样
-
.gitignore也可以用来表示要忽略哪些文件
这三个的优先级是files > .npmignore > .gitignore
files包含的文件,就算出现在.npmignore和.gitignore,也不会被忽略。如果既没有files字段,也没有.npmignore文件,那么npm会读取.gitignore文件,忽略里面的文件。
main & module & sideEffect
package.json#mai n 和 package.json#module 这两个字段是用来指定npm包的入口文件,但是两者有一定的不同。
npm在一开始的时候,是node的包管理平台,所有的包都是基于CommonJS 规范规范的,main这个字段是npm自带的,一般表示符合CommonJS规范的文件入口。
rollup实现了基于ES模块静态分析,对代码进行Tree Shaking,它通过识别package.json中的module字段,将它当成是符合ES模块规范的文件入口。webpack之后也进行跟进,也能识别module字段,并且在webpack的默认配置中,module的优先级要高于main,因此符合ES模块规范的代码能进行Tree Shaking,减少项目最终打包出来的代码。
因为一般的项目在配置babel的时候,为了提高构建速度,都会忽略node_modules里面的文件,所以module入口的文件最好是符合ESmodule规范的ES5的代码,webpack最终会把ESmodule转换为它自己的commonjs规范的代码。
package.json#sideEffect 这个字段是webpack4中新增的一个特性,用来表示npm包的代码是否具有副作用。ES6的代码在经过babel编译为ES5的代码后,就算是符合ES6的模块规范,也会出现UglifyJs无法Tree Shaking的问题。webpack4通过sideEffect这个字段,使UglifyJs强行进行Tree Shaking。
sideEffect可以设置为Boolean或者数组
-
当为false时,表明这个包是没有副作用的,可以进行按需引用
-
如果为数组时,数组的每一项表示的是有副作用的文件
在组件库开发的时候,如果有样式文件,需要把样式文件的路径放到sideEffect的数组中,因为UglifyJs只能识别js文件,如果不设置的话,最后打包的时候会把样式文件忽略掉。
{
"sideEffects": ["components/**/*.less"]
}复制代码
npm register
npm全局安装后,它的register是registry.npmjs.org ,如果你使用淘宝的镜像重写了register,那么可能会在登陆和发布的时候出错。
npm config list @cfe:registry = " mirrors.npm.private.caocaokeji.cn/repository/… "
registry = " registry.npm.taobao.org/ "
可以使用下面的命令进行登陆和发布
npm login --registryregistry.npmjs.org
npm publish --registryregistry.npmjs.org
或者在开发npm包的时候,将registry换成npm的官方地址,开发完以后再换回淘宝的镜像
npm config set set registrywww.npmjs.com/
npm config set registry registry.npm.taobao.org
npm link
在开发包的时候,会遇到调试问题,希望能够一边开发一边调试,不用频繁的去发布版本。
使用npm link可以达到这个效果,它会在在全局的node_modules目录中生成一个符号链接,指向模块的本地目录。
假设你要开发一个包,叫tool,需要在本地的项目work-center中去使用 在命令行中进入tool的目录,运行npm link这个命令,就会生成一个符号链接。
进入项目work-center的目录,运行npm link tool,就可以使用这个包了。
tool的所有改动都会映射到安装的项目中,但是带来的问题就是一处改动多处影响。
在调试结束后,运行npm unlink tool来删除符号链接。
oh-my-zsh
在Mac上使用oh-my-zsh可以提高命令行的开发效率,具体的配置可以参考这篇文章mac下oh-my-zsh的配置
安装了oh-my-zsh以后,可以简化git的命令行操作,提高键盘的寿命,常用命令如下
zsh-git快捷键 gst - git status gl - git pull gp - git push ga - git add gcmsg - git commit -m gco - git checkout gcm - git checkout master
monorepo & lerna
monorepo 是单代码仓库,与之对应的是multirepo,多代码仓库。
monorepo是把所有的module都放在一个代码仓库中,进行统一管理;multirepo是把module拆分开来,单独去管理。multirepo的问题是issue、changelog和版本号不好管理;monorepo的问题是单个仓库代码量比较大。现在一些主流的开发项目,比如babel、react、vue、vue-cli,都是使用monorepo的方式来管理代码仓库的;rollup和antd是使用multirepo。
lerna是babel官方开源的monorepo管理工具。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 3 分布式 Git - 维护项目
- 开发和维护个人开源项目之徽章收集
- 推荐一些维护大型 Python 项目的工具
- 开发和维护个人开源项目之代码仓库管理
- 安卓维护项目小结以及注意事项[个人总结]
- 选择正确的模型来维护和增强物联网项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web 2.0 Architectures
Duane Nickull、Dion Hinchcliffe、James Governor / O'Reilly / 2009 / USD 34.99
The "Web 2.0" phenomena has become more pervasive than ever before. It is impacting the very fabric of our society and presents opportunities for those with knowledge. The individuals who understand t......一起来看看 《Web 2.0 Architectures》 这本书的介绍吧!