前端新技术群 pnpm turbo vitepress vercel
本篇文章涉及:pnpm workspace特性,turbo的任务编排与缓存效率,vitepress搭建博客,vercel快速部署。
技术分为:
-
pnpm + turbo
-
vitepress
-
vercel
这里面的方案,可以解决什么需求呢?
- A:我开发了小程序,博客,个人网站,但有个功能是我更新了,就得在三个项目了,把代码更新一下。这样做,我感觉很费时间,还不如我把这个功能做成一个工具包,每个需要它得项目都依赖它。
- B:我只想写文章,想要vue官网的风格,想要快速搭建一个博客,但我不想做后端,不想写交互。
- C:我在开发阶段就花了很多时间了,再到部署到服务器,还要配置服务器信息(当然这是运维工作),还不如我提交代码那一刻就部署了呢。
很好!来吧!
pnpm + turbo
pnpm
npm就是Node Package Manager,即包管理工具。
对比一些当前的包管理工具:
Node Package Manager | 有package-lock | 安装依赖方式 | 依赖扁平化 | Workspace |
---|---|---|---|---|
pnpm | ⭐ | 并行且有硬链接 | ⭐⭐⭐ | ⭐ |
yarn | ⭐ | 并行 | ⭐ | ⭐ |
npm | ⭐ | 串行 | ❌ | 幽灵依赖问题 | ❌ |
cnpm |
注意:都不能混用
tip:
- 硬链接: 就是文件本身,是文件在硬盘中的区块。文件不存在,硬链接就不存在
- 软链接:是文件/目录的路径,类似于win里的快捷方式。
pnpm最直观的理解:快,有Workspace。
我在tst项目里首次添加一个依赖需要时间2.6秒。
然后删掉node_modules再下载,只需要868毫秒。
npm一些问题参考:pnpm 解决我哪些痛点? - 掘金 (juejin.cn)
turbo
先了解一下Monorepo(单一代码库),Monorepo的意思是在版本控制系统的单个代码库里包含了许多项目的代码。这些项目虽然有可能是相关的,但通常在逻辑上是独立的,并由不同的团队维护。简单的理解,比如我的一个github仓库里存着web端项目,后端项目,移动端项目,博客项目等等多个项目代码文件。
也比如:我写了个vue3的前端项目叫:myVue,目录如下:
--myVue
--node_modules
--src
--App.vue
--index.html
--package.json
同时我也写了个node后端叫:serve,目录如下:
--serve
--node_modules
--src
--App.vue
--index.js
--package.json
这个时候我将两个项目放在一个文件夹下:
--project
--myVue
--serve
--.git
project里面的每个项目(myVue,serve)都是可以单独运行的。但是我放在同一个代码库中。
Turborepo就是Monorepo管理工具的其中一种,简称turbo。
它有着:
- 依赖管理能力,保证安装的效率。
- 任务编排能力,能够按正确的顺序执行Monorepo内的项目的任务。
- 版本发布额能力,能够结合项目之间的依赖关系,正确地进行版本号更变及项目发布。
这里主要讲讲任务编排能力。
Monorepo里有三个项目A,B,C。A和C还需要依赖于B。也就是说B项目需要先构建好后,A和C才能构建。
传统的任务编排是:lint->build->test->deploy。即检查规范->构建项目->测试项目->部署项目。
- lint:执行检查代码规范任务,比如tsc,Eslint这种检查代码是否符合规范。
- build:构建项目,比如用vue3框架,vite框架,都需要构建,一般都会生成dist文件。
- test:测试自定义的命令。
- deploy:部署项目。
看上图,虽然每个项目都是并行执行任务的,但是lerna管理中里面,每个项目的build任务在lint任务之后,test任务在build任务之后。
但是turbo能够将每个项目里的任务进行拓扑排序再执行。
即图中B项目并行执行lint,test,build,之后A和C就可以更快的执行构建,大大提高了整体的效率。
使用turbo需要在monorepo项目下添加turbo依赖,并且新建turbo.json配置文件即可。
--project
--myVue
--serve
--package.json
--turbo.json
--.git
``turbo.json
"devDependencies": {
"turbo": "^1.6.3"
}
项目之间依赖
那么pnpm如何与turbo配合呢?
答案就是pnpm workspace,这使得pnpm天生支持monorepo。
workspace 可以使项目之间有依赖关系,在monorepo根目录里只需要有pnpm-workspace.yaml,并且在里面配置packages,pnpm就可以识别出workspace的区域。
``pnpm-workspace.yaml
packages:
- "packages/*"
在根目录建立一个packages目录来使用pnpm workspace,packages下有两个项目,一个是docs前端,一个project-one。project-one作为docs工具依赖(注意:project-one是自己编写的,不是node_modules)。
--project
--package.json
--packages
--docs
--package.json
--project-one
--package.json
--pnpm-workspace.yaml
使用以下命令,给docs添加project-one依赖。这样就完成了项目之间的依赖。
接下来看看如何运行项目,然后测试项目之间的依赖是否成功。
pnpm add project-one --workspace --filter docs
tip:
- –filter 后加上项目名称是指定对某个项目进行操作。
- **“项目名称”**是package.json里name对应的内容。
- 在根目录运行pnpm install命令即可将每个项目安装对应的依赖。
根目录中执行项目内命令
现在要在根目录执行packages里面的项目dev任务。在根目录的package.json里配置任务即可运行相应项目的dev任务,同时docs和project-one项目里的package.json:
``package.json
"scripts": {
"dev-docs": "pnpm --filter \"docs\" dev",
"dev-one": "pnpm --filter \"project-one\" dev"
}
``docs package.json
"scripts": {
"dev": "vitepress dev"
}
``project-one package.json
"scripts": {
"dev":"node index2.js",
}
然后可以在根目录里直接执行命令:
pnpm run dev-one
pnpm run dev-docs
这样它就会去每个项目里执行对应的dev任务。执行结果:
注:
- docs是vitepress项目。
- project-one index2.js里仅是一行代码,用来测试,通过控制台打印输出。
``project-one index2.js
console.log('nihao index2');
我们知道每个项目如何运行后,再来看看项目之间依赖是否成功。
现在在docs里调用一下project-one里的内容,docs的index页面和project-one的index.js:
// docs index.md
<script setup>
import addOne from 'project-one'
addOne(10,'docs')
</script>
// project-one index.js
const addOne = (x=0,msg='未填') => {
console.log('调用project-one的项目是:',msg);
return x + 1;
}
export default addOne
这里在project-one项目中定义了一个addOne函数,docs里执行调用。现在再跑docs项目,看看浏览器控制台有什么输出:
很好,docs项目成功使用了project-one依赖。
pnpm配合turbo任务编排等能力,能够更加高效的运行我们的每一个项目。
turbo任务编排能力
接下来我们要执行多个任务,并且有先后要求:
- docs和project-one都要执行build和test任务
- docs是依赖于project-one的,所以project-one的build在docs的build前面。
- test任务都是在build任务之后。
在这个需求中,我们可以这样解决:先将project-one->build 再docs->build,最后两个test(不分前后)。
接下来用turbo解决这个问题,并再次执行的时候能够更高效。
首先为了方便测试,test任务仅仅是输出内容。看两个项目的任务:
``project-one package.json
"scripts": {
"build":"node index2.js",
"test": "echo \"Error: no test specified\""
},
``docs package.json
"scripts": {
"build": "vitepress build",
"test": "echo \"Error: no test specified\""
},
turbo.json文件的配置:pipeline里面就是自定义的任务名称,如build,test,lint,deploy。
``turbo.json
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["build"],
"outputs": [],
"inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
},
"lint": {
"outputs": []
},
"deploy": {
"dependsOn": ["build", "test", "lint"],
"outputs": []
}
}
}
我们在项目package.json里配置turbo的任务turbo-test(turbo-build这里不做测试),turbo就会按照turbo.json配置文件去执行。
``package.json
"scripts": {
"turbo-test": "turbo run test",
"turbo-build": "turbo run build"
}
比如turbo运行build任务的时候,packages里的每一个项目都会执行build任务。
在turbo.json的pipeline中,build任务里面dependsOn的"^build"含义是指上游的build任务,也就是说,每个项目在执行自己build(构建)任务之前,会先将devDependencies和dependencies里的构建/安装好。
``turbo.json
"build": {
"dependsOn": ["^build"]
},
在这个例子中,就是指docs需要构建之前会等待project-one(“上游”)的构建完成。
而test里的"build"就是pipeline中的build任务,含义是:每个项目要执行自己的test任务,就要先执行build任务。
``turbo.json
"test": {
"dependsOn": ["build"]
},
然后我们通过pnpm run turbo-test命令进行测试,结果图如下(红色框先忽略):
可以看见它的执行过程完全是我们的预期效果。顺序是:project-one build 输出"nihao index2",test输出"Error: no test specified",docs build vitepress成功构建,test输出"Error: no test specified"。
project-one----> build---> test
|--> docs-> build ->test
当我们再次执行pnpm run turbo-test的时候:
因为代码并没有改动,turbo使用缓存能力,将整体的速度优化提高了!
turbo官方文档:Turbo
所以pnpm + turbo两个技术配合起来,就能够更加高效地对多项目的单一代码库进行管理。
vitepress
vite是一个前端构建工具,能够快速重载页面,构建和提供服务端口。vue3是一个前端框架。vite和vue3跟vitepress有什么关系呢?可以说vitepress也是基于vite而来的,所以会继承它的特性,vitepress也支持vue3代码。
要了解vitepress。先来了解CSR(客户端渲染),SSR(服务端渲染)和SSG(静态页面生成)。
- CSR,比如我们的vue,react框架开发的项目。都是浏览器先下载好html文档作为基础文档,再通过下载js来渲染出最终的页面效果。
- SSR,也比如我们的vue,react框架开发的项目(因为这些框架也支持)。是指在服务器端渲染成最终的页面效果。
- SSG,比如vitepress,支持将markdown文件生成静态资源(html),客户端请求的时候,会直接获取到最终的页面效果。
注:vitepress官网slogan就是:满足您一直想要的现代 SSG 框架。
可能你会好奇SSR和SSG区别在哪呢,可以简单的这样理解:SSR在请求页面的时候,页面基本的数据还要动态获取,再渲染成最终效果的页面,再返回给客户端;而SSG是已经构建(build)好了的页面,就是一个静态资源,直接返回给客户端。
在我看来,这些区分的界限越来越不明显,各有优缺点,最终需要怎样的技术,还是看需求。
简单说vitepress,是一个极其简单的框架,有着vite的特性,并且支持vue3语法。
先将vitepress依赖安装好,如果也需要写vue3语法就加上vue3的依赖。
``package.json
"scripts": {
"dev": "vitepress dev",
"build": "vitepress build",
"test": "echo \"Error: no test specified\""
},
"dependencies": {
"vitepress": "1.0.0-alpha.29",
"vue": "^3.2.45"
}
新建index.md文件,在index.md可以加入一些配置:
---
layout: home
hero:
name: VitePress
text: Vite & Vue powered static site generator.
tagline: Lorem ipsum...
actions:
- theme: brand
text: Get Started
link: https://github.com/jkkdeng
- theme: alt
text: View on GitHub
link: https://github.com/jkkdeng
features:
- icon: ⚡️
title: Vite, The DX that can't be beat
details: Lorem ipsum...
- icon: 🖖
title: Power of Vue meets Markdown
details: Lorem ipsum...
- icon: 🛠️
title: Simple and minimal, always
details: Lorem ipsum...
---
直接运行pnpm run dev命令,页面就出来了:
这里主要是layout: home,配置了当前页的布局为home,就可以使用hero和features,layout还可以选择doc,page。
接着试一下vitepress的构建能力,运行pnpm run build。它会在根目录默认生成.vitepress,vitepress里面还有生成文件dist。
我们还可以通过serve对构建结果进行检查,执行pnpm run serve命令
``package.json
"scripts": {
"dev": "vitepress dev",
"build": "vitepress build",
"serve": "vitepress serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
我们可以通过vitepress快速搭建起主题风格与vitepress,vue3等等这些官网一样的个人博客。
更多配置信息还可以在官网查看。
vercel
这里主要是运用到vercel平台的能力。这是它的官网:
现在我们要将vitepress的项目部署到服务器,但我们不需要购买服务器,也不需要配置ssl,我们用vercel就可以搞定这个简单的需求,并且有更快的部署。
vercel解决的总路程:vercel绑定github里的项目并克隆项目,在它的服务器里运行构建,自动配置访问信息即可访问。我们将我们的域名指向vercel给域名,完成重定向访问。
我们通过github账户可以直接注册登录,可以按照它的指引或在官网的指示板中添加项目,导入github里的项目。
点击部署即可完成部署,接下来Domains还可以添加我们的域名。
以后只要更改项目的内容提交到github,vercel都会再次部署。这对于我部署博客是非常快的了。
Serverless
vercel还提供了Serverless技术,简单来讲就像是我们使用的云开发技术(腾讯,阿里,华为云开发),是一个无服务器,降低运维需求,降低运营成本的概念。
vercel的Serverless支持四个官方运行时:node.js,go,python,ruby,也就是说支持js ts go py rb语言代码,可以选择我们熟悉的语言做后端!
本次学习中并没有使用serverless:
- 一是在部署项目后,发现访问很差,毕竟可能是部署在外网,
- 二是接触过云开发的内容,目前还没开发的需求。
好了本次学习,项目里写的都是demo,主要涉及到三板块:
-
pnpm + turbo
-
vitepress
-
vercel
如果你也了解到pnpm workspace特性,turbo的任务编排与缓存效率,vitepress搭建博客,vercel快速部署,那么就差不多啦!下次见。
我的个人博客原文:前端新技术群
https://blog.darkerin.cn/newtech/%E5%89%8D%E7%AB%AF%E6%96%B0%E6%8A%80%E6%9C%AF%E7%BE%A4.html
微信公众号文章:前端新技术群
weixin.qq.com/s/QtBwDO54VqRfzPjCFd2SQg