前言
我们在开发前端项目时通常会使用到别人封装好的代码,比如 demo / 函数 / 组件库 / 框架 / 插件 等,我们通常会选择:npm 方式来安装依赖。那 npm 到底是森么
npm 简介
npm 是 Node.js 标准的软件包管理器。
在 2017 年 1 月时,npm 仓库中就已有超过 350000 个软件包,这使其成为世界上最大的单一语言代码仓库,并且可以确定几乎有可用于一切的软件包。
它起初是作为下载和管理 Node.js 包依赖的方式,但其现在也已成为前端 JavaScript 中使用的工具。
NPM 能很好地和诸如 webpack
或 Browserify
模块打包器配合使用
在用 Vue 构建大型应用时推荐使用 NPM 安装。同时 Vue 也提供配套工具来开发单文件组件
npm 常见的 使用场景 有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
npm 功能
1. 安装软件包(install)
npm 可以管理项目依赖的下载
a. 安装所有依赖
如果项目具有 package.json
文件,则通过运行:
npm install
它会在 node_modules
文件夹(如果尚不存在则会创建)中安装项目所需的所有东西
b. 安装单个软件包
运行以下命令安装特定的软件包:
npm install <package-name> --save
npm install <package-name> --save-dev
--save
安装并添加条目到 package.json 文件的 dependencies【与生产环境中的应用程序相关】--save-dev
安装并添加条目到 package.json 文件的 devDependencies【开发的工具(例如测试的库)】
2. 更新软件包(update)
通过运行以下命令,更新也变得很容易:
npm update
npm 会检查所有软件包是否有满足版本限制的更新版本。
也可以指定单个软件包进行更新:
npm update <package-name>
3. 运行任务(run)
package.json 文件支持一种用于指定命令行任务(可通过使用以下方式运行)的格式:
npm run <task-name>
例如:一个 vue 项目的 package.json 文件中:
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
...
}
}
我们通过在终端运行
npm run serve
可以使得 serve 任务,使得我们的本地 vue-cli 项目可以通过 http://localhost:8080/#/
这个 URL 在浏览器中运行,这常用于我们对前端项目进行调试
如果我们想让我们的前端项目在运行调试前对软件包进行更新,我们可以在 package.json 文件中 scripts 对象的 serve 字段进行修改:
{
"scripts": {
"serve": "node node_modules/<package-name>/update && vue-cli-service serve",
"build": "vue-cli-service build",
...
}
}
如何使用或执行 npm 安装的软件包
假设使用以下命令安装了流行的 JavaScript 实用工具库 lodash:
npm install lodash
这会把软件包安装到本地的 node_modules 文件夹中。
若要在代码中使用它,则只需使用 require / import 将其导入到程序中:
const _ = require('lodash')
或
import _ from 'lodash'
另外,比如使用 vue + webpack 套餐的话,要全局引入组件库,则需要在main.js
中写入:
import Vue from 'vue';
import router from './router';
import store from './store';
// 引入组件库
import PackageName from '<package-name>';
import '<package-name>/lib/index.css';
Vue.use(PackageName);
const app = new Vue({
store,
router,
render: (h) => h(App),
}).$mount('#app');
window.app = app;
npm 版本问题
版本控制
除了简单的下载外,npm
还可以管理版本控制,因此可以指定安装软件包的任何特定版本,或者要求版本高于或低于所需版本。
npm install <package-name> <version>
包版本可以有三种写法:
- "packageName": "
15.2.1
" 只匹配一个版本,表示:只下载15.2.1
的版本- "packageName": "
~15.2.1
" 匹配最近的小版本依赖包,表示下载>= 15.2.1 && < 15.3.0
的版本- "packageName": "
^15.2.1
" 匹配最新的大版本依赖包,表示下载>= 15.2.1 && < 16.0.0
的版本
很多时候,一个库仅与另一个库的主版本兼容。或者,一个库的最新版本中有一个缺陷(仍未修复)引起了问题。
指定库的显式版本还有助于使每个人都使用相同的软件包版本,以便 整个团队运行相同的版本,直至 package.json
文件被更新。
如何查看 npm 包安装的版本
若要查看所有已安装的 npm 软件包(包括它们的依赖包)的最新版本,则:
npm list
例如:
❯ npm list
/Users/joe/dev/node/cowsay
└─┬ cowsay@1.3.1
├── get-stdin@5.0.1
├─┬ optimist@0.6.1
│ ├── minimist@0.0.10
│ └── wordwrap@0.0.3
├─┬ string-width@2.1.1
│ ├── is-fullwidth-code-point@2.0.0
│ └─┬ strip-ansi@4.0.0
│ └── ansi-regex@3.0.0
└── strip-eof@1.0.0
安装历史版本
可以使用 @ 语法来安装 npm 软件包的旧版本:
npm install <package>@<version>
可能还有需要列出软件包所有的以前的版本。 可以使用 npm view <package> versions
:
❯ npm view cowsay versions
[ '1.0.0',
'1.0.1',
'1.0.2',
'1.0.3',
'1.1.0',
'1.1.1',
'1.1.2',
'1.1.3',
'1.1.4',
'1.1.5',
'1.1.6',
'1.1.7',
'1.1.8',
'1.1.9',
'1.2.0',
'1.2.1',
'1.3.0',
'1.3.1' ]
卸载 npm 软件包
若要卸载之前在本地安装(在 node_modules
文件夹使用 npm install <package-name>
)的软件包,则从项目的根文件夹(包含 node_modules
文件夹的文件夹)中运行:
npm uninstall <package-name>
如果使用 -S 或 --save 标志,则此操作还会移除 package.json 文件中的引用。
如果程序包是开发依赖项(列出在 package.json 文件的 devDependencies 中),则必须使用 -D 或 --save-dev 标志从文件中移除:
npm uninstall -S <package-name>
npm uninstall -D <package-name>
如果该软件包是全局安装的,则需要添加 -g 或 --global 标志:
npm uninstall -g <package-name>
package.json 指南
package.json 位于模块的目录下,用于 定义包的属性
package.json 属性说明
- name - 包名。
- version - 包的版本号。
- description - 包的描述。
- homepage - 包的官网 url 。
- author - 包的作者姓名。
- scripts - 执行脚本。
- contributors - 包的其他贡献者姓名。
- dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
- repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
- main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
- keywords - 关键字
看例子
{
"name": "express",
"description": "Fast, unopinionated, minimalist web framework",
"version": "4.13.3",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
},
"contributors": [
{
"name": "Aaron Heckmann",
"email": "aaron.heckmann+github@gmail.com"
},
{
"name": "Ciaran Jessup",
"email": "ciaranj@gmail.com"
}
],
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/strongloop/express.git"
},
"homepage": "http://expressjs.com/",
"keywords": [
"express",
"framework",
"sinatra",
"web",
"rest",
"restful",
"router",
"app",
"api"
],
"dependencies": {
"accepts": "~1.2.12",
"array-flatten": "1.1.1",
"content-disposition": "0.5.0",
"content-type": "~1.0.1",
"cookie": "0.1.3",
"cookie-signature": "1.0.6",
"debug": "~2.2.0",
"depd": "~1.0.1",
"escape-html": "1.0.2",
"etag": "~1.7.0",
"finalhandler": "0.4.0",
"fresh": "0.3.0",
"merge-descriptors": "1.0.0",
"methods": "~1.1.1",
"on-finished": "~2.3.0",
"parseurl": "~1.3.0",
"path-to-regexp": "0.1.7",
"proxy-addr": "~1.0.8",
"qs": "4.0.0",
"range-parser": "~1.0.2",
"send": "0.13.0",
"serve-static": "~1.10.0",
"type-is": "~1.6.6",
"utils-merge": "1.0.0",
"vary": "~1.0.1"
},
"devDependencies": {
"after": "0.8.1",
"ejs": "2.3.3",
"istanbul": "0.3.17",
"marked": "0.3.5",
"mocha": "2.2.5",
"should": "7.0.2",
"supertest": "1.0.1",
"body-parser": "~1.13.3",
"connect-redis": "~2.4.1",
"cookie-parser": "~1.3.5",
"cookie-session": "~1.2.0",
"express-session": "~1.11.3",
"jade": "~1.11.0",
"method-override": "~2.3.5",
"morgan": "~1.6.1",
"multiparty": "~4.1.2",
"vhost": "~3.0.1"
},
"engines": {
"node": ">= 0.10.0"
},
"files": [
"LICENSE",
"History.md",
"Readme.md",
"index.js",
"lib/"
],
"scripts": {
"test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
"test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"
},
"gitHead": "ef7ad681b245fba023843ce94f6bcb8e275bbb8e",
"bugs": {
"url": "https://github.com/strongloop/express/issues"
},
"_id": "express@4.13.3",
"_shasum": "ddb2f1fb4502bf33598d2b032b037960ca6c80a3",
"_from": "express@*",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
},
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
}
],
"dist": {
"shasum": "ddb2f1fb4502bf33598d2b032b037960ca6c80a3",
"tarball": "http://registry.npmjs.org/express/-/express-4.13.3.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/express/-/express-4.13.3.tgz",
"readme": "ERROR: No README data found!"
}