Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

npm: Node Package Manager #2

Open
@playing

Description

npm: Node Package Manager

从学Node开始,到现在也差不多过去两年了,眼睁睁的看着版本号像坐了火箭一样,从0.10.x跑到了5.1.1.中间虽然也经历了诸如io.js这样的分裂和0.12系列的徘徊,但是不可否认的是,今天的Node.js,已经成为了一个成熟完善的生态,而且从语言本身到上下游的工具链,从开发者到社区支持,都在快速的发展和进步.我相信在可以预见的未来,Node.js不光会推动前端开发,更有希望在更多的领域,产生更多优秀的项目和实践!

回顾Node的发展,不得不提的就是npm.随着Node一路走来的npm,已经成为了社区中的事实标准,虽然npm最初的用途其实是更倾向于用来管理Server-side的包,Client-side的包管理更多的依赖其他工具(例如Component,Bower).但是开发者们并不满足,既然都是JavaScript的代码,为什么不能通用的解决呢?于是在对前端组件化和前后端无界限的渴求中,催生了Browserify,Webpack这样优秀的构建工具,实现了包的前后端共用.有了通用的包,就需要通用的包管理器,于是在短短几年之内,Component已经停止开发,Bower也停止了新的Feature,在寻求维护者和变化,被替代也只是时间问题.而npm随着2015年中3.0的推出,在通过flatten解决依赖树过于复杂和过深的同时,也在努力为Client-side的包管理做更多的优化和提升.

那么如何才能更好的利用npm这个工具,方便我们的日常开发,提升我们的工作效率和体验,下面会有三个小话题来讲述这个问题.

npm是个好包管理器

想要用好npm,首先要正确认识npm,npm到底是什么?通俗的讲,就是一个开放的代码仓库,人们可以发布自己的代码到上面,然后别人就可以通过方便的方式去引入并使用你的代码.类似的工具比如Python中的pip,Ruby中的gem,iOS开发中的pod.核心解决的问题都是类似的.

  • 包的上传下载
  • 包的版本控制和管理
  • 包的依赖树的管理

包管理器一方面让你可以方便的引入别人成熟的框架或者模块,一方面又不需要你在你自身的代码或者版本库中真实的存储大量的第三方组件.他们都通过一个简单的package.json来引入和定义.同时npm鼓励开发者尽量小的拆分模块和功能,把依赖树全部交给npm去做,让开发者只需要关注自己的代码本身和一层依赖,至于依赖的依赖,全部都通过npm来管理.虽然这样的结果就是在windows下稍微复杂一点的包,就容易超过路径248个字符的限制...

所以npm在常规的项目中的实践一般都遵从

  • 尽可能但是合理(遵循逻辑或者模块,但是尽量不要涉及业务)的拆分你的工程
  • 维护好你依赖的包的版本,如果需要精确的控制可以使用npm shrinkwrap
  • 合理利用npm提供的其他功能,例如用scripts来实现发布前自动测试等功能,npm dedupe可以解决一个模块被多个模块依赖的问题.
  • 如果这些都做不到,没关系,会npm install就行了

私有npm仓库的搭建

虽然npm如此的好用,但是毕竟整个源在国外,而且依赖很多github上的内容,在GFW的不懈努力之下,一些很大的包例如phantomJS或者node-sass之类需要编译的包,往往会在安装时遇到各种莫名其妙的问题.

同时整个npm都是open source的,虽然现在也提供private的源,类似于GitHub的private repo.但是国内的大部分公司,还是更需要一个内部的系统来方便管理和使用.

于是在这种需求之下,淘宝贡献了一个国内的镜像源npm.taobao.org,同时发布了自己的npm源实现cnpmjs.org.感谢这些工具和开源代码,我们得以很方便的在自己的服务器上搭建一个完整的npm源以及配套的实现.

必要环境

  • node 推荐最新的4.2.3(LTS)版本,但是对系统版本要求较高,我们目前是在CentOS7之上搭建的.
  • Databases sqlite3或者MySQL(MariaDB)都可以,官方最新版本默认使用sqlite3.

官方提供了一个很好的基础实现版本custom-cnpm-example,其中的sfs实现比较符合一般团队的需求,即文件存储在本地,但是需要注意的是,官方案例中的cnpmjs.org版本很低.如果需要更新至最新的2.5.1版本,配置文件和数据库都要做相应的变更.这里提供一个latest版本的项目,方便部署cnpmjs@latest

一份简单的sfs配置范例,更多的配置文件修改在cnpmjs.org项目的config中.

var config = {
 enableCluster: true,
 sfsConfig: sfsConfig,
 nfs: require('sfs-client').create(sfsConfig), //采用sfs作为文件存储
 bindingHost: '0.0.0.0', //是否需要绑定到广播地址
 npmClientName: 'snpm', //你自己的npm的名称,用来在页面上显示
 database: {
 //数据库配制和老版本差距比较大,这是mysql的版本,sqlite可以直接用默认的.
 db: 'cnpmjs_test',
 username: 'root',
 password: '',
 dialect: 'mysql',
 host: '127.0.0.1',
 port: 3306,
 pool: {
 maxConnections: 10,
 minConnections: 0,
 maxIdleTime: 30000
 },
 logging: !!process.env.SQL_DEBUG,
 },
 syncModel: 'exist', //同步模式,推荐exist,只更新已存在的包,不全量更新
 scopes: ['@playing'] //你的私有package的前缀名,为了避免冲突,所有的私有包都要在这个命名空间之下.
};

部署完成之后,就可以很简单的利用cnpm命令来访问你的私有仓库,或者通过一个别名来快速访问.

# install cnpm cli first
$ npm install cnpm -g
# alias snpm to cnpm for test
$ alias snpm='cnpm \
 --registry=http://registry.foo.com/ \
 --registryweb=http://npm.bar.com/ \
 --cache=$HOME/.npm/.cache/snpm \
 --userconfig=$HOME/.snpmrc'

下文中都以snpm为例来说明,实际中可以替换成任意你想要的名字.其中的registry和registryweb分别为源和web地址,之后就可以用snpm来替代常规的npm了.但是在第一次使用之前,建议同步一些常用的包,通过命令或者web端都可以方便的实现.或者在配置中添加自动同步most popular的100个包的选项

snpm sync gulp
snpm install gulp

如何利用npm管理你的依赖

搭建完了自己的仓库,接下来的问题就是,如何更好的利用它,来管理自己的依赖和私有包,并且方便开发和部署呢?

也非常的简单,首先你需要添加一个用户

snpm adduser

在输入用户名,密码以及邮箱之后,你的snpm命令就绑定了一个用户,这个用户会显示在npm仓库中.

snpm init

init命令可以帮助你快速生成或者修改现有的package.json,成为一个合法的package.json文件,一个简单的范例如下

{
 "name": "@playing/privite",
 "description": "project description",
 "author": "playing",
 "version": "0.0.1",
 "scripts": {},
 "repository": {
 "type": "git",
 "url": "https://www.github.com/foo/bar"
 },
 "dependencies": {
 "abbrev": "^1.0.7",
 "chalk": "^1.1.1",
 "@playing/test" : "~1.0.0"
 },
 "main": "index.js",
 "license": "ISC"
}

注意如果是私有包,name需要以你设置好的前缀开头,对私有包的依赖也要带上scope.

之后就可以把包通过snpm发布到仓库中,方便其他开发者引用,之后每次更新需要修改package.json中的version,然后重新publish.

snpm publish

有了这些工作之后,我们就可以对自己的大项目进行合理的划分和抽取,对于公共的模块,通过npm处理依赖,实现解耦和版本的控制.例如常用的工具集就可以通过这种形式打成包,方便其他项目引用.或者公用的API,也可以通过这种的形式,对外统一暴露一致的接口.以及项目的公用样式或者公用组件库,也可以通过npm仓库进行管理,同时在webpack的帮助下,能和后端组件实现一致的引用和使用方式.极大的增强了代码的统一性.而且在部署的时候,也可以利用npm的特性,源代码通过git部署,其余模块和依赖使用npm.这样在任何标准的node环境下,只需要git clone和npm install两条命令,就可以部署完整的项目.

END

这一次的思考,来源于在内部实践npm的一些经验和感想,同时更加感受到,node和npm为js带来的无限扩展和希望.随着这个文章的出炉,前端工程化终于在我司迈出了一小步,当然后面还有很多艰巨的工作要做,希望能够在明年有更多的成果.最后的最后,谢谢阅读

♥ Made With Love by Playing

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /