【前端工程化】万字拆解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优化,它会安全地删除未使用的模块,减小最终打包体积

相关推荐
程序媛刘刘2 分钟前
uniappx 使用体验
java·服务器·前端
coder阿龙5 分钟前
【UNIAPP】获取视频的第一帧作为封面(基于视频URL,Canvas)复制即用
前端·uni-app·音视频
蘑菇王7 分钟前
无需打包构建?ESM Bundleless 开发的探索与实践
前端·javascript
只会写Bug的程序员11 分钟前
面试之《TypeScript泛型》
前端·面试·typescript
宇寒风暖21 分钟前
HTML嵌入CSS样式超详解(尊享)
前端·css·笔记·学习·html
Starbright.23 分钟前
Git的必要配置
git
秋天的一阵风25 分钟前
‌ES Module 都过十岁生日了,你还不了解它的运行原理吗?
前端·javascript·面试
FreeCultureBoy29 分钟前
本地运行LLM的实用指南
前端
AC使者41 分钟前
解释 Git 的基本概念和使用方式。
git
二川bro1 小时前
前端项目Axios封装Vue3详细教程(附源码)
前端