monorepo
方式进行管理,将模型拆分到package目录中ts
开发,增强类型管理,vue2则采用flow
proxy
,vue2数据劫持采用defineProperty
,defineProperty
有性能缺陷问题patchFlag
标记动态节点compositionApi
进行组织功能,解决反复横跳,优化复用逻辑(mixin带来数据来源不清晰,命名冲突等),相比optionsApi
类型推断更加方便Fragment
,Teleport
,Suspense
组件Monorepo
是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(packages)
缺点
:仓体积会变大
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
完整版本,抱愧运行时和编译器依赖 | |
---|---|
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
npm i typescript -g
tsc --init // 生成tsconfig.json
.......
"moduleResolution":"node",
"baseUrl":".",
"paths": {
"@vue/*":[
"packages/*/src"
]
}
.........
"private": true, //表述属性是私有的
"workspaces": [ //工作空间,表示找到packages下面的所有包
"packages/*"
],
"scripts": {
"dev" : "node scripts/dev.js",
'build': "node scripts/build.js"
},
{
"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"
]
}
}
{
"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"
]
}
}
// 把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 => {
//打包完毕后执行的操作
})
console.log('rollup',process.env.TARGET)
//process.env.TARGET reactivity process.env.TARGET reactivity
// 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]))