nodejs 中的 NODE_PATH

在使用 nodejs 开发中我们都免不了要去安装一些第三方模块。

那么你或多或少的遇到过以下一些问题

再继续阅读之前,我们先来弄清楚一个概念。

npm install --global xxx 属于全局安装
npm install xxx 属于本地安装

安装的模块太多项目太臃肿,模块没能复用

你写一个项目 A 需要安装一个 express 模块,又开发一个项目 B 又需要安装一个 express 模块

项目中依赖包太多,文件过多,模块没法复用,各种问题浮现

由于 安装的依赖包过多(而且依赖包嵌套依赖包),如果一个项目依赖多的话,(比如依赖 gulp 系列 或 grunt 系列的项目构模块)那么一个项目可以说轻轻松松上百兆。如果想给想项目更换一个目录,都发现是痴心妄想了。(基本都是1-10KB的小文本文件组成了一个100多MB的项目,那得有多少个文件啊!想想如果像java那样,模块都是以jar包存在的压缩归档文件可能也好一点)。更别提部署了。

其实这里面的代码也就是 几十KB到1兆 是我们自己写的代码。这些文件想实现 复制,移动,部署是很方面的。

给部署带来的困扰

如果你部署过 node 项目到远程服务器,node_modules 目录的上传将是一件恐怖的事情

NODE_PATH 出现,模块复用,最佳实践方案

NODE_PATH 是干什么的呢?

操作系统中都会有一个PATH环境变量,想必大家都知道,当系统调用一个命令的时候,就会在PATH变量中注册的路径中寻找,如果注册的路径中有就调用,否则就提示命令没找到。

-> export PATH=$PATH: # 将 /usr/bin 追加到 PATH 变量中
-> export NODE_PATH="/usr/lib/node_modules;/usr/local/lib/node_modules" #指定 NODE_PATH 变量

那 NODE_PATH 就是NODE中用来寻找模块所提供的路径注册环境变量。我们可以使用上面的方法指定NODE_PATH环境变量。并且用;分割多个不同的目录。

加载时机

关于 node 的包加载机制我就不在这里废话了。NODE_PATH中的路径被遍历是发生在

从项目的根位置递归搜寻 node_modules 目录,直到文件系统根目录的 node_modules,如果还没有查找到指定模块的话,就会去 NODE_PATH中注册的路径中查找

解决问题

基于 nodejs 的包加载路径搜索算法,我们可以 采用全局安装的方式,将我们的包安装到全局。

这样,我们的项目就可以共享全局中的依赖包。

了解全局

npm root -g 查看在你的系统中全局的路径。

我们也可以通过
npm config ls -l | grep prefix (*nix) 系统中

或是
npm config get prefix

来查看全局路径。

是的 prefix 字段就是全局base path

怎么设置全局路径呢?

# in *nix
npm config set prefix /path/to/global # in windows
npm config set prefix C:\\Users\\pc\\global

求同存异,解决模块版本问题

差异性的解决方法

如果 项目A 使用了,express的3.x版本,项目B 使用了 express的4.x版本,那这种情况该怎么办呢?

可以将 NODE_PATH 指定的位置中存放 express的4.x版本,再将 项目B的 node_modules 目录中放置 3.x 版本。

这样就解决了模块版本差异性问题。

所以说,两种安装方式我们并不是只是用其中的一种,他们可以结合使用,根据 nodejs 的包加载机制,我们可以灵活使用。

部署不再是问题

在部署之前,我们可以将我们项目的所有可以全局安装的模块,都以全局的安装方式安装到服务器中。接下来我们就可以轻松,上传我们的项目到服务器中了。这样上传也会变得的很快。

然后配置我们的 NODE_PATH 环境变量。怎么配置上面也谈过,这里就不用多说了。(因为项目的部署方式多种多样,所以具体情况可以自行决定。)

本人是使用 PM2 部署管理Nodejs项目,所以我写在 配置文件中。

带来的问题

是的这种方式也有缺点。因为在使用 --global 参数的时候 --save 或 --save-dev参数是无效的。

这样就带来一个问题。此时 package.json 中的 dependenciesdevDependencies 将无法享受到npm自动更新带来的便利,不使用 dependenciesdevDependencies 字段对我们的项目管理来说是不可接受的。

如何解决

我有一个不是很优雅地解决方法,但是也算是解决了这个问题,希望有更好解决办法的同学给我留言。

我写了一个小工具(npmafter),它的使用方法很简单, 它是跨平台的。兼容(Mac,Windows,Linux)。(我没有发布到github上,因为感觉会有更好的办法)

$ npm install -g http://yinchangsheng-blog.qiniudn.com/blog/nodejs/npmafter.tgz # install
# 然后我们安装任何模块就可以这样
$ npm install express -g | npmafter
$ npm install request q -g | npmafter --save
$ npm install mocha chai -g | npmafter --save-dev

是的 package.json 文件就会得到更新。

好的,如果你不纠结这个问题那么这个问题就算是解决了。

使用 NODE_PATH 可以很好的解决项目开发部署的问题。

NODE_PATH的疑难杂症(转)的更多相关文章

  1. Carousel 旋转画廊特效的疑难杂症

    疑难杂症 该画廊特效的特点就是前后元素有层级关系. 我想很多人应该看过或者用过这个插件carousel.js,网上也有相关的教程.不知道这个插件的原型是哪个,有知道的朋友可以告诉我. 该插件相对完美, ...

  2. TCP协议疑难杂症全景解析

    说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人. ...

  3. [Swift] 疑难杂症

    [Swift] 疑难杂症 1.class  .... has no initializers -->  class 的每一个元素都需要初始化,否则会报错,除了可空元素

  4. nodejs 80端口监听失败及NODE_PATH不起作用的问题

    nodejs做web服务器,打开80时报错:Error: listen EACCES 0.0.0.0:80 80端口监听失败,是因为1024以下的端口需要root权限,需要sudo或su之后执行.但这 ...

  5. 十个Flex/Air疑难杂症及解决方案简略

    十个Flex/Air疑难杂症及解决方案简略 转自http://blog.sban.us/40.html 最近去一家台企,对方给我出了十道“难道”:在TileList中如果選擇檔過多,會出現捲軸,當拖動 ...

  6. C# (事件触发)回调函数,完美处理各类疑难杂症!

    每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客! 废话说多了...... 嘿嘿:本篇标题为:C#  (事件触发)回调函数,完美处理各类疑难杂症.个人理解如下:事件触发也就是触 ...

  7. 使用truss、strace或ltrace诊断软件的“疑难杂症”

    简介 进程无法启动,软件运行速度突然变慢,程序的"Segment Fault"等等都是让每个Unix系统用户头痛的问题,本文通过三个实际案例演示如何使用truss.strace和l ...

  8. 【转载】TCP协议疑难杂症全景解析

    说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人. ...

  9. IE-“无法浏览网页” 教你十招解决疑难杂症

    “无法浏览网页” 教你十招解决疑难杂症 相信大家也有遇到过像IE不能上网浏览的问题.下面就来给大家介绍一下常见原因和解决方法: 一.网络设置的问题 这种原因比较多出现在需要手动指定IP.网关.DNS服 ...

随机推荐

  1. iOS开发之多媒体播放

    iOS开发之多媒体播放 iOS sdk中提供了很多方便的方法来播放多媒体.本文将利用这些SDK做一个demo,来讲述一下如何使用它们来播放音频文件. AudioToolbox framework 使用 ...

  2. 【LeetCode】131. Palindrome Partitioning

    Palindrome Partitioning Given a string s, partition s such that every substring of the partition is ...

  3. 【LeetCode】137. Single Number II (3 solutions)

    Single Number II Given an array of integers, every element appears threetimes except for one. Find t ...

  4. Loading...加载图收集

    收集来源:http://cs.fangjia.com/zoushi/

  5. Eclipse,以及tomcat使用时可能会遇到的几个问题

    http://blog.sina.com.cn/s/blog_56b0cb2d01000a7r.html Eclipse,以及tomcat有几个问题.说明如下 1, 工程不编译的问题 . 有时候,项目 ...

  6. pthread到Win32thread

    一.什么是线程. 线程(thread)是为了提高系统内程序的并发(concurrency)执行程度而提出来的概念,它是比进程更小的能够独立运行的基本单位.在引入线程的系统中,线程是处理器调度(sche ...

  7. java的jdbc简单封装

    在学了jdbc一段时间后感觉自己写一个简单的封装来试试,于是參考的一些资料就写了一下不是多好,毕竟刚学也不太久 首先写配置文件:直接在src下建立一个db.properties文件然后写上内容 < ...

  8. RabbitMQ 远程 IP 访问 解决办法 -摘自网络

    刚刚安装的RabbitMQ-Server-3.3.5,并且也已经开启了Web管理功能,但是现在存在一个问题: 出于安全的考虑,guest这个默认的用户只能通过http://localhost:1567 ...

  9. Java:多线程,线程池,用Executors静态工厂生成常用线程池

    一: newSingleThreadExecutor 创建一个单线程的线程池,以无界队列方式运行.这个线程池只有一个线程在工作(如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它.)此线程池 ...

  10. Oracle学习笔记之五,Oracle 11g的PL/SQL入门

    1. PL/SQL概述 PL/SQL(Procedural Language/SQL)是Oracle的专用语言,是对标准SQL语言的扩展,它允许在其内部嵌套普通的SQL语句,还可以定义变量和常量,允许 ...