【前端工程化】万字拆解package.json (一)

什么是package

package 指拥有 package.json 的一个文件夹(或压缩包),而 package 的属性就是 package.json 文件的内容,比如:

  • name:这个包叫什么名字,唯一
  • version:这个包的版本号是多少
  • main:这个包默认引入的是哪个文件
  • homepage:这个包的官网或者文档

semver

semver,语义化版本,它由[major,minor,patch]三部分组成,其中

  • major:包中发生Api级别的变化时,递增major版本号
  • minor:新增一个向后兼容的功能时,递增minor版本号
  • patch:修复一个向后兼容的bug时,递增patch版本号
    除此之外,一些大型包的管理中,如果没有正式发布,会选择使用prerelease版本号,例如1.0.0-alpha。在比较小的包就没必要使用。

semver 与语言无关,不仅在 JavaScript 中使用 semver,在其它一些语言中也可以使用 semver 该语义化版本命名版本号。

我们接下来拿vue举一个例子

  • Vue 2 到 Vue 3 的迁移是一个 major 版本更新的例子,涉及了不兼容的重大变化,比如:

    1. Composition API 替代 Options API: 从 Vue 2 的 Options API 到 Vue 3 的 Composition API,组件逻辑写法有较大改变。
    2. 基于 Proxy 的响应式系统: Vue 3 使用 Proxy 取代了 Vue 2 的 Object.defineProperty,影响了响应式数据的更新和追踪。
    3. Fragment 语法: Vue 3 引入了 Fragment 语法,不需要像 Vue 2 一样在模板中使用额外的包装元素。
  • 如果 Vue Router 新增了一个向后兼容的功能,会递增 minor 版本号。假设在 3.0.0 版本中没有的导航守卫的选项被添加到 3.1.0 版本,这个变化不会影响到已有的导航守卫。

  • 当 Vue Router 修复一个向后兼容的 bug 时,会递增 patch 版本号。例如,假设 3.0.0 版本中的一个已知 bug 被修复,就会发布 3.0.1 版本。

版本号范围

当我们手动安装一个包,它写在 package.json 中的是一个版本号范围。

js 复制代码
{
  dependencies: {
    lodash: '~1.8.1'
  }
}

版本号一般有~ ^两种

对于~1.2.3来说,它的版本号范围是>=1.2.3 <1.3.0

对于^1.2.3来说,它的版本号范围是>=1.2.3 <2.0.0

我们在写项目时可以使用 yarn.lock/package-lock.json 锁定版本号。

依赖

依赖分为dependencydevdependency两种

它们两者之间的区别就是一个是项目运行时所需要的依赖,一个是开发时的依赖是不会打包进最终产物的。

除此之外,它们在包开发和项目开发时也有差别。

  • 在开发包时,devdependencydependency需要有严格的区分,因为在npm i xxx时,只会下载xxx包package.json目录下的dependency,如是略有差错,项目就会出错,
  • 在开发项目时,这两者就不必要有很严格区分。不管是使用webapck还是vite打包项目时,这些打包工具都会对项目依赖进行分析,用到的打包,不用的剔除。不过作为一种规范,能遵守还是得遵守。

URI as dependency

复制代码
{
  "dependencies": {
    "npm": "git+ssh://git@github.com:npm/cli.git",
    "foo": "http://q.shanyue.tech/foo.tar.gz",
    "bar": "file:../bar"
  }
}

这种写法常用于一个项目依赖另一个项目,但又不想发包,我们就可以直接用它仓库url作为依赖。

依赖别名

一个项目需要用到一个包的两个版本,此时我们就需要使用依赖别名来区分

js 复制代码
$ npm install <alias>@npm:<name>

$ npm install vue2@npm:vue@2
$ npm install vue3@npm:vue@3

package.json:

复制代码
{
  "dependencies": {
    "vue2": "npm:vue@2",
    "vue3": "npm:vue@3"
  }
}

sideeffects

sideEffects 用于指示npm包是否具有副作用。

副作用指的是模块在导入时会产生除了导出值之外的其他影响,比如修改全局变量、执行一些代码等。在现代的 JavaScript 模块系统中,为了优化打包和代码分割,打包工具(比如Webpack)会尝试去除那些没有副作用的模块,以减小打包后的代码体积。

package.json中,我们可以通过以下方式配置sideEffects

json 复制代码
{
    "name": "redux", 
    "version": "5.0.0-beta.0",
    "sideEffects": false
}
  1. false: 表示模块没有副作用,可以被安全地删除。这通常用于纯粹的导出模块,例如只包含函数、类、对象等,没有执行任何其他操作的模块。
  2. true: 表示模块具有副作用,不会被删除。这是默认值,如果你不在 package.json 中显式设置 sideEffects,那么模块会被认为具有副作用。
  3. 字符串数组:可以列出模块中具有副作用的文件的路径。这些路径会被用于指定哪些模块具有副作用,从而防止它们被删除。

使用场景举例:

json 复制代码
{
  "name": "my-react-app",
  "dependencies": {
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "lodash": "^4.0.0"
  },
  "sideEffects": [
    "node_modules/lodash/*.js"
  ]
}

在这个例子中,我们使用了React和React DOM作为依赖项,并且还使用了Lodash库。但是,我们可能只使用了Lodash的部分功能,其他部分具有副作用。通过设置 sideEffects 字段,我们告诉打包工具只保留Lodash库中我们使用的部分,并且删除没有副作用的部分。这可以显著减小打包后的代码体积,提高应用程序加载速度。

一句话概括它的作用:打包器webpack、vite等通过这个字段进行Tree Shaking优化,它会安全地删除未使用的模块,减小最终打包体积

相关推荐
咖啡の猫40 分钟前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲3 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5814 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路4 小时前
GeoTools 读取影像元数据
前端
ssshooter4 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友4 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry5 小时前
Jetpack Compose 中的状态
前端
百思可瑞教育6 小时前
Git 对象存储:理解底层原理,实现高效排错与存储优化
大数据·git·elasticsearch·搜索引擎
dae bal6 小时前
关于RSA和AES加密
前端·vue.js
柳杉6 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化