乐趣区

npm(你怕吗) 全局安装与本地安装、开发依赖和生产依赖

npm(你怕吗)
npm(Node Package Manager) 是 JavaScript 世界的包管理工具, 并且是 Node.js 平台的默认包管理工具。通过 npm 可以安装、共享、分发代码, 管理项目依赖关系。(与其有同样功能的另一个包管理工具 yarn,速度用体验比旧版本的 npm 好,但 npm 最近的新版本也做出很大努力,与 yarn 速度和体验差距越来越小,有兴趣可以了解下)。
npm 这几年可以说是前端猿日常离不开的工具了,刚开始学习使用 node、npm 来进行前端项目构建的时候,有很多概念需要理解,各种命令行、各种新 js 语法、各种环境依赖 … 就问你怕吗?:

讲真,刚开学时我怕。废话不多扯,现在我们进入主题,聊聊 npm 全局安装与本地安装、开发依赖和生产依赖,先抛两常见疑惑:

什么是全局安装、什么是本地安装 (或叫局部安装,下文统一叫本地安装)?
为什么要全局安装?为什么又要本地安装?全局安装和本地安装有什么区别?
什么叫开发依赖、生产依赖?什么又是开发环境、生产环境?

全局安装与本地安装
一、全局安装:
npm install <pageName> -g//(这里 - g 是 -global 的简写)
通过上面的命令行(带 - g 修饰符)安装某个包,就叫全局安装。通常全局包安装在 node 目录下的 node_modules 文件夹。可以通过执行下面几条命令查看 node、npm 的安装目录和全局包的安装目录。
which node // 查看 node 的安装目录
which npm // 查看 npm 的安装目录
npm root -g // 查看全局包的安装目录
npm list -g –depth 0 // 查看全局安装过的包
二、本地安装:
npm install <pageName> (后面可以加几种修饰符,主要有两种 –save-dev 和 –save)
通过上面的命令行安装某个包,就叫本地安装。包安装在你当前项目文件夹下的 node_modules 文件夹中。
三、全局安装的作用:
全局安装的包可提供直接执行的命令 (例:gulp - h 可以查看 gulp 定义了什么命令)。比如 gulp 全局安装后,可以在命令行上直接执行 gulp -v、gulp - h 等(原理:全局安装的 gulp 会将其 package.json 中的 bin 命令注入到了全局环境,使得你可以全局执行:gulp xxx 命令,这另一个话题了,不深入)。倘若只在本地安装了 gulp,未在全局安装 gulp,直接执行这些命令会报错。你想要执行相应的命令则可能需要例如:node ./node_modules/gulp/bin/gulp.js -v(查看版本) 这样用一大串命令来执行。因此全局安装就发挥到他的好处了,一个 gulp - v 就搞定
当然,不是每个包都必须要全局安装的,一般在项目中需要用到该包定义的命令才需要全局安装。比如 gulp <taskName> 执行 gulp 任务 … 等,所以是否需要全局安装取决于我们如何使用这个包。全局安装的就像全局变量有点粗糙,但在某些情况下也是必要的,全局包很重要,但如果不需要,最好避免使用。
四、可以全局安装,那么直接全局安装到处使用就行了,干嘛还需要本地安装?

如果只是全局安装了而没本地安装,就得 require(‘<pagePath>’) 例:引入一个全局的包可能就是 requirt(‘/usr/local/….’) 通过全局包的路径引入,这样显然十分的不灵活。如果安装了本地包,那么就可以直接 require(‘<pageName>’) 引入使用。
一个包通常会在不同的项目上会重复用到,如果只全局安装,那么当某个项目需要该包更新版本时,更新后可能就会影响到其他同样引用该包的项目,因此本地安装可以更灵活地在不同的项目使用不同版本的包,并避免全局包污染的问题,

一个经验法则:要用到该包的命令执行任务的就需要全局安装,要通过 require 引入使用的就需要本地安装(但实际开发过程中,我们也不怎么需要考虑某个包是全局安装还是本地安装,因为这一点在该包的官网上一般会明确指出,以上是为了理解全局安装和本地安装)
开发依赖和生产依赖
顺着上面讲到的本地安装,本地安装有两种主要的安装方式:

保存到开发依赖 (devDependencies): npm install <pageName> –save-dev(等同 npm install <pageName>)
保存到生产依赖 (dependencies): npm install <pageName> –save

“ 开发依赖 ” 顾名思义在开发环境中用到的依赖,” 生产依赖 ” 在生产环境中用到的依赖。那么这里又延伸出个问题什么是开发环境、什么是生产环境?
一、开发环境和生产环境
【开发环境】:指的是你的项目尚且在编码阶段时的环境。你在代码可能还有各种 console.log()、注释、格式化等。【生产环境】:指的是你的项目已经完成编码,并发布上线可供用户浏览的阶段时的环境。代码可能经过了压缩、优化等处理。
这些概念其实并没有一个很明确的定义,接下来我们举例个场景,将 ” 开发环境 ”、” 生产环境 ” 和上面的 ” 开发依赖 ”、” 生产依赖 ” 联系起来就会比较容易理解的了。假如我们在开发过程中使用 jQuery。在以往,可能就是把 jQuery 这个插件下载的本地,再通 <script> 引入 html 中。但这有个不方便的地方,我们每次进行一个项目的时候就得手动复制这个 jQuery 文件到我们的项目中,如果想要换个版本又得官网上下载、随着项目越来越多。用到的插件、库也随之越繁杂 … 这样会造成自家用的插件管理繁琐的问题。因此就出现了 npm(包管理工具) 你需要用到什么,直接通过一条命令行就可以将想要的插件下载下来,并直接引入到项目中,目前几乎所有的 js 插件都能在 npm 上直接下载。
二、生产依赖
回到环境和依赖话题,我们下载的 jQuery,在开发时参与源码编写,在发布上线的生产环境中也是需要它的。不仅在开发环境编写代码时要依赖它、线上环境也要依赖它,因此将它归类为 ” 生产依赖 ”,安装时执行 npm install jquery –save,它就会被记录在 package.json 的 dependencies。当进行代码打包时,会将这里的 jQuery 打包入我们的项目代码中。
三、开发依赖
接着,假如我们用 gulp 对 html 进行压缩,我们通常会用到一个插件 gulp-htmlmin。我们只希望它把 html 压缩完就 ok 了,并不希望它融入我们的项目代码中,即只存在于开发环境,因此把他归类为 ” 开发依赖 ”。安装时执行 npm install gulp-htmlmin –save-dev 它就会被记录在 package.json 的 devependencies 下,当进行代码打包时,不会将这里的 gulp-htmlmin 插件源码打包入我们的项目代码中
devDependencies 只会在开发环境下使用,生产环境不会被打入包内;而 dependencies 不仅在开发环境中要使用,生产环境也需要使用到。根据以上规则,我们就很容易区分哪些插件是用 –save-dev 模式安装,哪些用 –save 模式安装。
最后
文章开头的问题以上已经一一回答了。刚开始时自己也会有很多类似这样的疑问,哪怕已经使用 npm 的各种包构建过不少项目,对这些概念还是会有点模糊,使用当然是会使用的,但没有一个比较清晰的总结。所有花了点时间,到各社区、node、npm 官网搜集关于以上问题的一些答案、简单做个笔记和总结。毕竟总结并记录下来的东西才是自己的。也希望可以帮助有同样疑问的朋友,如发现文章有不对的地方望指出,谢谢

退出移动版