Monorepo 是什么?

简单的来说,Monorepo 的核心观点是所有的项目在一个代码仓库中。这并不是说代码没有组织都放在 ./src 文件夹里面,二是在一个packages文件夹下分割成一个个相对独立的项目,在vue3.0中就是将各个功能单独抽离出一个个单独的模块,各自打包,又能互相引用。vue2中是只打一个包。
类似于在这里插入图片描述
最终的效果vue3.0的打包效果:在这里插入图片描述
下面我们来大致实现下整个 monorepo模式的打包过程,大致了解下这种模式

1.安装需要的插件

yarn add typescript rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa --ignore-workspace-root-check(忽略工作空间)因为monorepo方式只支持yarn
依次插件的功能:
支持typeScript
1.打包工具
2.rollup和ts的桥梁
3.解析node第三方模块
4.支持引入json
5.开启子进程方便执行命令

2.简单讲下目录
在这里插入图片描述

shared中的package 和reactivity差不多(名字对应换下就行),主要有两个参数 buildOptions 这个参数 名字自定义的打包的时候取获取配置就行,这个后面说

src下的index.ts :const shared = {} export { shared} 没什么东西
dist 文件夹忽略这是我们打包出来的结果

build.js 全局打包,这个打包命令就是一次性讲packages中的各模块分别单独打包
dev.js 是单个模块打包

3.我们看下build.js

  • 总结下面的带来来说就是干了几件事
  • 1.通过fs模块找到packages下的几个可以打包的目标文件夹名字的数组
  • 2.通过runParallel方法,依次调用build并行打包
  • 3.build方法中其实就用到了execa开启子进程使用rollup打包
  • 4.下面我们就要去看下rollup的配置 rollup.config.js
/*
 * @Author: your name
 * @Date: 2021-12-09 16:04:21
 * @LastEditTime: 2021-12-13 16:22:09
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \vue3.0\scripts\build.js
 */
// 将package目录下得所有包打包
const fs = require("fs");
const execa = require("execa"); //开启子进程,进行打包,最终还是使用rollup打包
// 找到目标模块
const target = fs.readdirSync("packages").filter((f) => {
    // 判断是否是个目录
    if (!fs.statSync(`packages/${f}`).isDirectory()) {
        return false;
    } else {
        return true;
    }
});

// 依次并行打包 
runParallel(target, build).then((res) => {});

function runParallel(targets, iteratorFn) {
    let res = [];
    // 异步并行打包
    for (const item of targets) {
        const p = iteratorFn(item);
        res.push(p);
    }
    return Promise.all(res);
}
// 核心打包模块build
async function build(target) {
    // 调用rollup.config.js
    await execa("rollup", ["-c", "--environment", `TARGET:${target}`], {
        stdio: "inherit", //子进程共享给父进程
    });
    console.log(target, "build:打包");
}

4.rollup.config.js配置

  • 总结
  • 1.通过上面代码传入的参数process.env.target包名,取package.json
  • 2.在这里插入图片描述
  • buildOption 中的参数name 就是用来坐全局变量,打包后script 引入就能直接使用这个值
  • formats:打包出的类型 下面代码中outputConfig 就是针对这些类型的枚举,比如:format: “cjs”, //commondJS 是给node使用 因为node 不支持import es6语法 弄得使用这个项目就会引用cjs结尾的文件
  • 最后export 就行了下面带面有注释,至于rollup怎么打包的我们暂时不用管
import path from "path";
import json from "@rollup/plugin-json";
import resolvePlugin from "@rollup/plugin-node-resolve";
import ts from "rollup-plugin-typescript2";
// rollup配置
console.log(process.env.target);

// 根据环境变量中得target属性获取对应模块中得package.json
// 找目标
const packagesDir = path.resolve(__dirname, "packages");
// 找具体哪个包
const packageDir = path.resolve(packagesDir, process.env.TARGET);

const resolve = (p) => path.resolve(packageDir, p);

// 取package.json
const pkg = require(resolve("package.json"));
// 取i文件名
const name = path.basename(packageDir);

// 对打包类型 先做一个映射表(枚举表),根据你提供得fromats来格式化需要打包得内容
const outputConfig = {
    //自定义得
    "esm-bundler": {
        file: resolve(`dist/${name}.esm-bundler.js`),
        format: "es", //es模块 第三方模块引用 支持import
    },
    cjs: {
        file: resolve(`dist/${name}.cjs.js`),
        format: "cjs", //commondJS  是给node使用 因为node 不支持import es6语法
    },
    global: {
        file: resolve(`dist/${name}.global.js`),
        format: "iife", //全局模块  立即执行   比如script 标签直接引入
    },
};

// 自已在每个包中定义得 buildOptions
const options = pkg.buildOptions;

// 从映射表中找到配置 生成rollup 配置
function createdConfig(format, output) {
    output.name = options.name;
    output.sourcemap = true; ///生成map文件

    // 生成rollup 配置
    return {
        input: resolve("src/index.ts"),
        output,
        plugins: [
            json(),
            ts({
                tsconfig: path.resolve(__dirname, "tsconfig.json"),
            }), //解析ts
            resolvePlugin(), //第三方解析
        ],
    };
}

// rollup 最终需要导出一个配置变量
export default options.formats.map((format) =>
    createdConfig(format, outputConfig[format])
);

console.log(pkg);

5,因为是ts文件,需要ts的配置文件

npx tsc --int
修改里面的几个值
“target”: “es2016”,
“module”: “ESNext”,
“moduleResolution”: “node”, /* Specify how TypeScript looks up a file from a given module specifier. /
“baseUrl”: “.”, /
Specify the base directory to resolve non-relative module names. /
“paths”: {
"@vue/
":[“packages/*/src”]
},
“esModuleInterop”: true,
“forceConsistentCasingInFileNames”: true,
“strict”: false,
“skipLibCheck”: true

6.最后打包,npm run build*
在这里插入图片描述
7.相互引用

执行yarn install 在项目根目录下,只要package.json配置了workspaces,他自动会将packages中的项目建立软链接到modules中

{
    "private": true,
    "workspaces": [
        "packages/*"
    ],
    "name": "vue3.0",
    "version": "1.0.0",
    "main": "index.js",
    "license": "MIT",
    "scripts": {
        "dev": "node scripts/dev.js",
        "build": "node scripts/build.js"
    },
    "dependencies": {
        "@rollup/plugin-json": "^4.1.0",
        "@rollup/plugin-node-resolve": "^13.0.6",
        "execa": "^5.0.0",
        "rollup": "^2.60.2",
        "rollup-plugin-typescript2": "^0.31.1",
        "typescript": "^4.5.2"
    }
}

在这里插入图片描述

Logo

前往低代码交流专区

更多推荐