虽然我们使用 node 环境,但是对于 package.json
并不一定那么熟悉,这篇讲一下里面一些字段的含义,包托管
到 npmjs
目录
npm 配置
搞懂 CommonJS、AMD、CMD、UMD、ES6 模块化
package.json 字段
nvm 使用
nvm就是可以让你电脑使用多个nodejs版本,要使用哪个版本时切换即可。
如果已经安装过nodejs了,先卸载掉吧
1、下载nvm
https://github.com/coreybutler/nvm-windows/releases
2、使用镜像地址
打开nvm安装目录 setting.txt,把下面两句放到里面
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
3、常用命令
nvm list // 查看当前系统已安装过的node版本
nvm list available // 查看服务器可用node版本,完整查看 https://nodejs.org/en/download/releases/
nvm install v12.22.0 // 安装12.22.0版本
nvm use 12.22.0 // 切换到12.22.0版本
4、nvm切换不成功
exit status 5: �ܾ����ʡ� exit status 1: ���ļ��Ѵ���ʱ�����������ļ���
nvm切换不成功
切换为管理员模式
,重新切换。
npm 配置
- 创建空白文件
npm init -y
- npm源
设置
// 淘宝源
npm config set registry https://registry.npm.taobao.org
// npmjs
npm config set registry https://registry.npmjs.org
查看所有配置项
// 看所有
npm config list -l
// 看源
npm config get registry
一次性安装指定源
npm install --registry https://registry.npm.taobao.org
搞懂 CommonJS、AMD、CMD、UMD、ES6 模块化
前端在之前都使用script引用js脚本,随后各大社区便于出现模块化引用的解决方案,便于代码复用等
-
CommonJS 即 CJS ,运行于
服务端
且只能同步加载
nodejs 使用require
,module.exports
引用/导出模块可写 require |exports , exports是module.exports的引用
// B.js
module.exports.b = 2 或者 exports.b = 2
// C.js
const B from './B.js'
console.log(B.b)
-
AMD 和 CMD 运行于
客户端
且异步加载
,浏览器需要异步加载,而CommonJS只有同步加载,于是这是为了兼容CommonJS在浏览器端的方案 -
UMD 就是结合 CommonJS、AMD、CMD,即 支持服务端 也 支持客户端,组件库一般都是导出这个格式,就达到了跨平台的解决方案。
1、先判断是否支持AMD(define是否存在),存在用AMD模块的方式加载模块 2、再判断是否支持NodeJS的模块(exports是否存在),存在用NodeJS模块的方式, 3、否则挂在window上,当全局变量使用。 这也是目前很多插件头部的写法,就是用来兼容各种不同模块化的写法。
(function(window, factory) {
//amd
if (typeof define === 'function' && define.amd) {
define(factory);
}
//cjs
else if (typeof exports === 'object') {
module.exports = factory();
}
else {
window.jeDate = factory();
}
})(this, function() {
...module..code...
})
- ES6 即 ESM, 使用
import
和export
、export default
引用/导出模块,ES6 有望成为浏览器和服务器通用的模块解决方案,但还需要Webpack等工具转换为CommonJS
// B.js
export const b = 2 或者 export default { b: 2 }
// C.js
import B from './B.js'
console.log(B.b)
注意:
-
CommonJS 输出的是值的拷贝,ES6 输出的是值的引用,于是值的变化对CommonJS没影响,但是对ES6就有影响
-
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
CommonJS 加载的是一个对象,即module.exports对象,该对象只在运行时生成;而ES6模块不是对象, 对外接口只是一种静态定义,在代码静态解析阶段就会生成
-
CommonJS 默认导出对象 module.exports 是 {} 空对象,ES6 默认到处 export default 是 undefined,所以循环引用时,两者表现不一致
结论:
目前三种规范 esm 、cjs 、umd 占据主流,其中:
esm :现代 ECMA 规范,摇树(tree shaking)性能好,首推使用
cjs :node 使用的 require 规范,无摇树
umd :支持 cjs 和 amd 规范,自动挂载导出到 global ,一般用在浏览器中
最好不要使用 browser 字段,永远使用 module 字段支持摇树,如果必须支持 umd ,可以添加至 umd 到 main 字段
package.json 字段
name
项目名
-
发布到 npmjs 的 name 需要全网唯一
-
name必须是字符串,不能以.或_开头,不能有大写字母,因为名称最终成为URL的一部分因此不能包含任何非URL安全字符
-
包含组织时
,如@vue/cli
时,vue表示组织名,需要在 npmjs 上先在账号下创建 vue 这个组织,cli名在该组织下唯一即可
version
版本号
-
通常三段式 遵循 大版本
major
.次要版本minor
.小版本patch
的格式规定 -
在
devDependencies 和 dependencies
中1、指定版本
^3.3.4
表示主版本固定
的最大版本3.x.x2、指定版本
~3.3.4
表示主版本和次版本固定
的最大版本3.3.x3、指定版本
3.3.4
表示所有版本固定
3.3.4
files
是字符串数组,表示允许推送到 npmjs
上的文件或者目录
- 若
files
存在,则只推送包含的文件或目录,同时表示安装时这个包时会有这些文件存在 - 若
files
不存在,则项目所有文件全部推送,但是 npmjs 限制项目最大 100M
main 、browser 、module
这是指明当前包的入口文件地址,回顾前面 【搞懂 CommonJS、AMD、CMD、UMD、ES6 模块化】 这段结论里说清楚了,需要生成ES6(ESM)、CommonJS(CJS)、UMD格式的模块文件,所以main 、browser 、module这三个字段的作用就是指明不同导出格式文件的路径。
一般情况下他们在
package.json
中的对应字段如下:
字段 | 规范 |
---|---|
main | cjs |
module | esm |
browser | umd |
这里最大的问题在于:
对于一个库来说 cjs 和 umd 是需要连带第三方依赖一同打包的,因为很多配置都会默认排除 node_modules ( 比 如 babel ),导致库得不到 polyfill ,特别是 webpack 5 已经去除了自动添加 polyfill 的特性后,对 cjs和 umd 的包更要格外注意,如果依赖中含有 es6 语法,最后得到的产物可能仍未被转换。
这个问题告诉我们 cjs 和 umd 以后必须要连同 polyfill 和第三方依赖一同打进来,这样才能保证兼容,也就是说丢失了摇树性能,整个库要用其中一个函数就需要都引入。
对 webpack 的影响
但 webpack 的 Resolve 机制会默认优先识别 browser 也就是 umd 规范,这就使得你只要使用了该库任何功能都会被整个库打包进来( 配置字段 resolve.aliasFields ),当无 browser 字段时优先使用 module 字段(支持摇树)。
总结
所以毫无疑问,在用户不知情的情况下,永远都不要使用 browser 字段,永远使用 module 字段支持摇树,如果必须支持 umd ,可以添加至 umd 到 main 字段( 详见 Specifying builds in package.json)。
bin
bin 字段用于全局命令,详情看我前面系列 脚手架原理篇
简单说,
- 全局安装时,mybuild会成为命令行可识别命令,会执行全局 mybuild.js 文件
- 项目中安装时 npx mybuild,会执行项目包中 mybuild.js文件
"bin": {
"mybuild": "./bin/mybuild.js"
}
scripts
可执行 npm run xxx 命令
"bin": {
"serve": "vue-cli-service serve",
}
devDependencies 、 dependencies 、peerDependencies
安装依赖包
devDependencies 是 npm i webpack -D
安装的,只出现在打包阶段,最终发布文件中不存在
dependencies 是 npm i axios
安装的,在最终发布文件中存在
peerDependencies 是 让宿主环境去安装满足插件peerDependencies所指定依赖的包。
当我们开发一个模块的时候,如果当前模块与所依赖的模块同时依赖一个第三方模块,
并且依赖的是两个不兼容的版本时就会出现问题,最终解决插件与所依赖包不一致的问题。
从npm 3.0版开始,peerDependencies不再会默认安装了
engines
指明了该模块运行的平台,比如Node``的某个版本,
或者npm
的某个版本或者浏览器。
"engines": {
"node" : ">=8.9.0 <12.x",
"npm" : "~6.14.12"
}
private
指明该项目是否能发布到npmjs上,详情看在 脚手架系列 - lerna和yarn配合单体包
简单说,一般没有这个字段,如果设置 true ,则不能推送到npmjs上
browserslist
代表这个项目的浏览器兼容情况
browserslist 是一个开源项目,具体的影响到前端工具的编译情况,比如 Autoprefixer 可以给css加兼容性前缀 babel-preset-env , eslint-plugin-compat, stylelint-no-unsupported-browser-features 和 postcss-normalize
"browserslist": [
"> 1%",
"last 2 versions",
"Android >= 3.2",
"Firefox >= 20",
"iOS 7"
]
sideEffects
副作用字段,文件数组,因为tree shaking时,会把没用到的文件移除,sideEffects字段的作用就是告诉webpack,依然要保留这些文件