行业知识
前端架构: 脚手架之包管理工具的案例对比及workspaces特性的使用与发布过程
2026-10-20 16:40:26
来源:互联网转载
npm的workspaces 特性
1 )使���或不使用包管理工具的对比
- vue-cli 这个脚手架使用 Lerna 管理,它的项目显得非常清晰
- 在 vue-cli 中包含很多 package 点开进去,每一个包都有package.json
- 它里面有很多项目,再没有 Lerna 之前去维护和管理这么多包是会非常困难的
- 而 webpack 至今还没有用任何的包管理工具,在其 lib 下会有非常多的模块
- 而且它还自己写了很多脚本来进行管理各种功能
- 同上上述正反两个例子,可见,不使用包管理工具,整个项目维护起来会很麻烦
- 比如说你想去给 webpack 做一些贡献,很麻烦很困难,因为你不太清楚,你的改动对整体一个影响
- 如果使用包管理以后,它就会拆的很清楚,你的改动就是聚合在一个package里面的,这个就是用包管理一些好处
- 包管理目前流行的两种方式是 workspaces 和 Lerna
2 )workspaces 的基本使用
- 在一个脚手架项目中,比如xyzcli项目中(之前一直用这个脚手架演示)创建workspaces 目录
- $ mkdir workspaces && cd workspaces
- 在 workspaces 目录中执行
- $ npm init -y
- 其实,在使用 npm init 的过程中,通过 $ npm init --help
- 可以看到 Options 中存在 [-w|--workspace [-w|--workspace ...]]
- 也就是 -w 的参数, 比如:$ npm init -w a -w b 默认一路回车
- 这样,就会在 workspaces 目录下新建了两个包:a 和 b,每个包中,都存在package.json,其name属性分别为 a 和 b
- 在 workspace/node_modules下 生成a和b的两个软链
- 在 workspace/package.json 中,存在 workspaces 的配置
"workspaces": [ "a", "b"]
- 好,现在结构基本搭建完成,现在我要在 workspaces 目录对a包进行安装依赖
- $ npm i vue -w a
- 这时候,a包中安装了 chalk 的依赖,但是a包中没有生成 node_modules 目录
- 在 workspaces 目录下的 node_modules 中安装了 chalk, 而 a 的 package.json 中的 dependencies 是 chalk
- 同时,b包中的package.json中是没有的
- 这是 workspace 非常有意思的特性,它把各个内层包的依赖抽象到了最外层来进行管理
- 这里借助了 commonjs 中对 node_moduels 查找的特性,如果当前查找不到,去上一层目录中去查找
- 由于此特性,可以通过最外层来管理依赖包,这样的好处是非常明显的
- 现在在a包中使用chalk, 在package.json中添加 "type": "module" 在 a/index.js 中编写
import chalk from 'chalk';export default { print() { console.log(chalk.red('Hello workspace')) }} - 现在继续修改 a/package.json 中的 name属性,修改为:“@somegroup/a”
- 这时候,a包就会在后续发布中,自动在 somegroup 分组中了,这个 somegroup 可以是自己起的任意组名
- 好现在在workspaces目录中新增一个具有cli功能的包,比如就叫做 cli 这个脚手架包
- $ npm init -w cli 一路回车, 创建了 cli 这个脚手架包
- 将 cli 包的 package.json 目录中的name属性改成和a包同组,如:"name": "@somegroup/cli"
- 同时在 workspaces/cli 的package.json中添加 bin 属性
{ "bin": { "cli": "bin/cli.mjs" }} - 因为这时候 cli 脚手架包的 name 不是在一开始创建的,而是一路回车之后,要确定和a同组的,需要执行下 $ npm i -ws 来更新下分组
- 这时候可以看到 workspaces/node_modules/@somegroup/下存在 a 和 cli 两个软链
- 同时,可以删除 workspaces/node_modules/cli 这个软链
- 这时候,想要在 cli 这个脚手架包中引用 a包来调试,需要 在 workspaces 目录下执行
- $ npm i @somegroup/a -w cli
- 这时候,会在 cli 脚手架目录中添加了 @somegroup/a 这个 dependencies
- 新建 bin/cli.mjs 编写
#!/usr/bin/env nodeimport * as a from '@somegroup/a'const { print } = a.default;print(); - 最后,可以将 这个 cli 工具在workspaces下配置使用, 因为在 workspace/node_modules/.bin 下有这个cli的软链
- 所以在 workspaces/package.json 中添加配置
"scripts": { "cli": "cli"}, - 这时候在 workspaces 下执行 $ npm run cli, 这样,我们的脚手架就可以直接使用了,如下图
-
这里演示了脚手架包cli如何使用包a,在不发布的场景下进行调试,并且对cli包本地的调试
-
同时,可以参考之前的文章:https://blog.csdn.net/Tyro_java/article/details/136112045
-
好,现在发布之前, 还需要处理一下b包,毕竟建立这个包是有用的,不在远程发布有问题的包
-
将b包的name修改成 "name": "@somegroup/b", 目前这三个包都在 @somegroup 组中了
-
在b中新建 index.js, 在b/package.json中同步"main": "index.js", 并添加 "type": "module"
-
给b包安装 ora 依赖,在 workspaces 目录下执行 $ npm i ora -w b
-
编写 b/index.js
import ora from 'ora';export default function() {const spinner = ora().start('loading');setTimeout(() => {spinner.stop();}, 3000)} -
因为修改了 b 的package.json的name属性,需要同步下 $ npm i -ws
-
并且注意删除下之前 workspaces/node_modules/b 这个叫b的软链
-
好,现在b包作为工具库为 cli 脚手架提供方法,为cli安装b包, 回到 workspaces 目录下
-
执行 $ npm i @somegroup/b -w cli, 修改 cli/bin/cli.js 文件
#!/usr/bin/env nodeimport a from '@somegroup/a'import bLoading from '@somegroup/b'const { print } = a;print();console.log('----------');bLoading(); -
这时候万事俱备了,就可以发布上线了, 在 worksapces 目录中
- npm publish -ws 发布所有 workspace 包内容,这个是全部包发布的举例
- npm publish -w a 发布a包,这个是单个包发布的举例
-
注意,如果包存在发布报错,可能是因为权限问题,可修改对应包的package.json
{"publishConfig": {"access": "public"}} -
这样就顺利发布成功了,注意,Lerna 使用时会帮助我们考虑到这一点,Lerna 会省事一些
- 在一个脚手架项目中,比如xyzcli项目中(之前一直用这个脚手架演示)创建workspaces 目录
下一篇:ftp服务器怎么搭建多个目录?