前言
1.vue2和vue3区别介绍
- 源码采用
monorepo
方式进行管理,将模型拆分到package目录中 - vue3采用
ts
开发,增强类型管理,vue2则采用flow
- vue3的性能优化,支持tree-shaking,不使用则不会被打包
- vue2后期引入RFC,使得每个版本改动可控rfcs(Request For Comments, 征求意见)
2.vue3内部优化
- vue3劫持数据采用
proxy
,vue2数据劫持采用defineProperty
,defineProperty
有性能缺陷问题 - vue3中对模块编译进行了优化,编译时生成了Block tree,可以对子节点的动态节点进行收集,可以减少比较,并且采用
patchFlag
标记动态节点 - vue3采用
compositionApi
进行组织功能,解决反复横跳,优化复用逻辑(mixin带来数据来源不清晰,命名冲突等),相比optionsApi
类型推断更加方便 - 增加了
Fragment
,Teleport
,Suspense
组件
3.monorepo的介绍
Monorepo
是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(packages)
- 一个仓库可维护多个模块,不用到处找仓库
- 方便版本管理和依赖管理,模块之间相互引用,调用都非常方便
缺点
:仓体积会变大
4.vue3的项目架构
reactivity
:响应式平台runtime-core
:与平台无关的运行时的核心(可以创建针对特定平台的运行时-自定义渲染器)runtime-dom
:针对浏览器运行时,包括DOM API
属性,事件处理等runtime-test
:用于测试server-renderer
:用于服务器端渲染compiler-core
:与平台无关的编译器核心compiler-dom
:针对于浏览器的编辑模块compiler-ssr
:针对于服务器端渲染的编译模块compiler-sfc
:针对单文件解析size-check
:用来测试代码体积template-explorer
:用于调试编译器输出的开发工具shared
:多个包之间的共享内容vue
完整版本,抱愧运行时和编译器
项目打包流程构建
1.安装依赖
依赖 | |
---|---|
typescript | 支持typescript |
rollup | 打包工具 |
rollup-plugin-typescript2 | rollup和ts的桥梁 |
@rollup/plugin-node-resolve | 解析node第三方模块 |
@rollup/plugin-josn | 支持引入json |
execa | 开启子进程方便执行命名 |
- 初始化项目,安装对应的依赖
yarn init -y
yarn add @rollup/plugin-json @rollup/plugin-node-resolve execa rollup rollup-plugin-typescript2 typescript
2.初始化typescript
npm i typescript -g
tsc --init // 生成tsconfig.json
-
tsconfig.json文件内容(对于其中每一项的含义,后面补充)
-
在tsconfig.json文件中添加对packages包中项目文件的检验
.......
"moduleResolution":"node",
"baseUrl":".",
"paths": {
"@vue/*":[
"packages/*/src"
]
}
.........
3.初始化项目目录
- 新建shared和reactivity包和启动脚本目录,项目结构如下
- 修改总目录中package包中配置
"private": true, //表述属性是私有的
"workspaces": [ //工作空间,表示找到packages下面的所有包
"packages/*"
],
"scripts": {
"dev" : "node scripts/dev.js",
'build': "node scripts/build.js"
},
- 配置好workspaces的目的是为了,在node_modules下面创建下软链接,以便每个包之间都可以相互引用
- 修改reactivity和shared包中package.js中的配置
- reactivity中packjson中配置
{
"name": "@vue/reactivity",
"version": "1.0.0",
"main": "index.js", //主要给commonjs使用
"license": "MIT",
"module": "dist/reactivity.esm-bundler.js", //保证在webpack工程化 import时候使用
"buildOptions": {
"name": "VueReactivity",
"formats": [ //这里表示需要打包的种类
"cjs",
"esm-bundler",
"global"
]
}
}
- shared中packge.json配置
{
"name": "@vue/shared",
"version": "1.0.0",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
"license": "MIT",
"buildOptions":{
"name":"VueShared",
"formats":[
"cjs",
"esm-bundler"
]
}
}
4.编写打包脚本中build.js中的打包方法
- 读取packages下面所有的文件夹,并且异步调用打包方法,进行打包
- build就做了一件事情,就是传值到rollup环境变量中
// 把package目录下面的所有都打包
const fs = require('fs')
const execa = require('execa')
// [ 'reactivity', 'shared' ] 可以筛出这两个模块
const targets = fs.readdirSync('packages').filter(f => { //找到packages下面的所有包,筛选出文件夹
if(fs.statSync(`packages/${f}`).isDirectory()){
return false
}
return true
})
//对我们的目标依次进行打包
async function build(target){
//启用rollup打包
await execa('rollup',['-c','--environment',`TARGET:${target}`],{stdio:'inherit'}) //当子进程打包的信息共享给父进程
}
function runParallel(targets,iteratorFn){
const res = []
for(item of targets){
const p = iteratorFn(item)
res.push(p)
}
return Promise.all(res)
}
//异步执行所有打包
runParallel(targets,build).then(res => {
//打包完毕后执行的操作
})
5.新增rollup.config.js编写打包脚本
- 打印rollup中的环境变量,可以看到是传过来的变量
console.log('rollup',process.env.TARGET)
//process.env.TARGET reactivity process.env.TARGET reactivity
- 写rollup.config.js中的配置
- 首先到对应包中package.json的配置
- 然后根据buildOptions中要生成选项生成对应的rollup打包配置
// rollup的配置
import path from 'path';
import json from '@rollup/plugin-json';
import resolvePlugin from '@rollup/plugin-node-resolve'
import ts from 'rollup-plugin-typescript2'
// 根据环境变量中的target属性 获取对应模块中的 pakcage.json
const packagesDir = path.resolve(__dirname,'packages'); // 找到packages
console.log('process.env.TARGET',process.env.TARGET);
// packageDir 打包的基准目录
const packageDir = path.resolve(packagesDir,process.env.TARGET) // 找到要打包的某个包
// 永远针对的是某个模块
const resolve = (p)=>path.resolve(packageDir,p)
const pkg = require(resolve('package.json'));
const name = path.basename(packageDir); // 取文件名
// 对打包类型 先做一个映射表,根据你提供的formats 来格式化需要打包的内容
const outputConfig = { // 自定义的
'esm-bundler':{
file: resolve(`dist/${name}.esm-bundler.js`),
format:'es'
},
'cjs':{
file:resolve(`dist/${name}.cjs.js`),
format:'cjs'
},
'global':{
file:resolve(`dist/${name}.global.js`),
format:'iife' // 立即执行函数
}
}
const options = pkg.buildOptions; // 自己在package.json中定义的选项
function createConfig(format,output) {
output.name = options.name;
output.sourcemap = true; // 生成sourcemap
// 生成rollup配置
return {
input: resolve(`src/index.ts`),
output,
plugins:[
json(),
ts({ // ts 插件
tsconfig:path.resolve(__dirname,'tsconfig.json')
}),
resolvePlugin() // 解析第三方模块插件
]
}
}
// rollup 最终需要到出配置
export default options.formats.map(format=>createConfig(format,outputConfig[format]))
6.运行yarn run build打包
- 运行打包命令,可以看到在每个包下面都生成对应的打包文件(根据package.json中配置项生成)
总结
- vue3打包流程就是找到每个包然后循环package.json中配置,然后生成不同的配置文件