15

你真的懂package.json吗

 4 years ago
source link: https://juejin.im/post/5dea1095e51d4558083322e2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
2019年12月06日阅读 10295

你真的懂package.json吗

在Node.js中,模块是一个库或框架,也是一个Node.js项目。Node.js项目遵循模块化的架构,当我们创建了一个Node.js项目,意味着创建了一个模块,这个模块的描述文件,被称为package.json。

我之前看别人项目中package.json文件的scripts这样写:

"dev": "rimraf \"config/.conf.json\" && rimraf \"src/next.config.js\" && cpx \".conf.json\" \"config/\" && nodemon server/index.ts",
"clean": "rimraf ./dist && mkdir dist",
"prebuild": "npm run clean",
"build": "cross-env NODE_ENV=production webpack"
复制代码

当时看的有点懵, 于是又补了下相关知识, 发现原来package.json有很多地方被我们忽略了呀, 如果有道友和我一样有点懵的话, 本文不容错过。

它是一个命令名和本地文件名的映射。在安装时,如果是全局安装,npm将会使用符号链接把这些文件链接到prefix/bin,如果是本地安装,会链接到./node_modules/.bin/。

通俗点理解就是我们全局安装, 我们就可以在命令行中执行这个文件, 本地安装我们可以在当前工程目录的命令行中执行该文件。

"bin": {
    "gynpm": "./bin/index.js"
}
复制代码

要注意: 这个index.js文件的头部必须有这个#!/usr/bin/env node节点, 否则脚本将在没有节点可执行文件的情况下启动。

通过npm init -y创建一个package.json文件。

{
    "name": "cc",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "bin": {
        "mason": "./index.js"
    },
    "scripts": {},
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {}
}
复制代码

在package.json的同级目录新建index.js文件

#!/usr/bin/env node

console.log('cool')
复制代码

然后在项目目录下执行: mac下: sudo npm i -g, window下: npm i -g

接下来你在任意目录新开一个命令行, 输入mason, 你讲看到

cool字段。

不知道通过这个小实验能不能帮助大家更好的理解这个bin的作用。像我们常用的vue-clicreate-react-app等都是通过bin属性将命令映射到了全局上。

main很重要, 它是我们项目的主要入口。

"main": "app.js"
复制代码

像这样, 我们项目就会以根目录下的app.js文件作为我们的项目入口文件了。

scripts

npm 允许在package.json文件里面,使用scripts字段定义脚本命令。 优点: 项目的相关脚本,可以集中在一个地方。

不同项目的脚本命令,只要功能相同,就可以有同样的对外接口。用户不需要知道怎么测试你的项目,只要运行npm run test即可。

可以利用 npm 提供的很多辅助功能。
复制代码

npm 脚本的原理非常简单。每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。

比较特别的是,npm run新建的这个 Shell,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。

这意味着,当前目录的node_modules/.bin子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写mocha test就可以了。

*表示任意文件名,**表示任意一层子目录。


"lint": "jshint *.js"
"lint": "jshint **/*.js"

复制代码

如果要将通配符传入原始命令,防止被 Shell 转义,要将星号转义。

"test": "tap test/\*.js"
复制代码

脚本传参符号: --

"server": "webpack-dev-server --mode=development --open --iframe=true ",
复制代码

脚本执行顺序

并行执行(即同时的平行执行),可以使用&符号

$ npm run script1.js & npm run script2.js
复制代码

继发执行(即只有前一个任务成功,才执行下一个任务),可以使用&&符号

$ npm run script1.js && npm run script2.js
复制代码

npm 脚本有pre和post两个钩子, 可以在这两个钩子里面,完成一些准备工作和清理工作

"clean": "rimraf ./dist && mkdir dist",
"prebuild": "npm run clean",
"build": "cross-env NODE_ENV=production webpack"
复制代码

npm 默认提供下面这些钩子:

prepublish,postpublish
preinstall,postinstall
preuninstall,postuninstall
preversion,postversion
pretest,posttest
prestop,poststop
prestart,poststart
prerestart,postrestart
复制代码

拿到package.json的变量

npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。

首先,通过npm_package_前缀,npm 脚本可以拿到package.json里面的字段。比如,下面是一个package.json。

// package.json
{
  "name": "foo", 
  "version": "1.2.5",
  "scripts": {
    "view": "node view.js"
  }
}

复制代码

我们可以在自己的js中这样:

console.log(process.env.npm_package_name); // foo
console.log(process.env.npm_package_version); // 1.2.5
复制代码

// 删除目录
"clean": "rimraf dist/*",

// 本地搭建一个 HTTP 服务
"serve": "http-server -p 9090 dist/",

// 打开浏览器
"open:dev": "opener http://localhost:9090",

// 实时刷新
 "livereload": "live-reload --port 9091 dist/",

// 构建 HTML 文件
"build:html": "jade index.jade > dist/index.html",

// 只要 CSS 文件有变动,就重新执行构建
"watch:css": "watch 'npm run build:css' assets/styles/",

// 只要 HTML 文件有变动,就重新执行构建
"watch:html": "watch 'npm run build:html' assets/html",

// 部署到 Amazon S3
"deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/",

// 构建 favicon
"build:favicon": "node scripts/favicon.js",

复制代码

介绍几个在npm脚本中好用的模块

cpx全局复制

一个很好用的模块, 可以监视全局文件变化, 并将其复制到我们想要的目录

我们使用npm安装就可以在npm的脚本中使用了:

"copy": "cpx \".conf.json\" \"config/\" "
复制代码

这样我们运行npm run copy就可以将根目录下的.conf.json文件拷贝到config文件夹下了, 如果没有config文件夹就会新建一个。

cpx "src/**/*.{html,png,jpg}" app --watch
复制代码

当src目录下的任意.html, .png, .jpg等文件发生变化就拷贝到app目录下。

cross-env能跨平台地设置及使用环境变量

大多数情况下,在windows平台下使用类似于: NODE_ENV=production的命令行指令会卡住,windows平台与POSIX在使用命令行时有许多区别(例如在POSIX,使用$ENV_VAR,在windows,使用%ENV_VAR%。。。)

cross-env让这一切变得简单,不同平台使用唯一指令,无需担心跨平台问题:

"start": "cross-env NODE_ENV=production node server/index.js",
复制代码

dependencies和devDependencies

这两个主要就是存放我们项目依赖的库的地方了, devDependencies主要是存放用于本地开发的, dependencies会在我们开发的时候带到线上。

通过npm i xxx -S会放在dependencies, npm i xxx -D会放在devDependencies。所以我们在装包的时候一定要考虑这个包在线上是否用的到, 不要全都放到dependencies中,增加我们打包的体积和效率。

peerDependencies

我们在一些项目的package.json中看到这个属性, 它主要是考虑兼容问题,通俗点理解, 我们通过这个属性可以告诉要使用我们这个模块的人:

你要使用我, 最好把xxx1, xxx2也带上, 不然我可能会给你带来麻烦的。

"peerDependencies": {
        "xxx1": "1.0.0",
        "xxx2": "1.0.0",
    }
复制代码

这样在装包的时候同时也会, 带上xxx1和xxx2这两个包。

个人觉得比较重要的就是这几个了。还有一些, 像: author, version, keywords, description这些就很好理解了。

npmjs

阮一峰博客


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK