# 环境配置

TIP

vue3.0采用Monorepo管理项目,代码采用ts编写,rollup打包

# 一、安装依赖

依赖 说明
typescript 支持ts
rollup 打包工具
rollup-plugin-typescript2 rollup 和 ts的 桥梁
@rollup/plugin-node-resolve 解析node第三方模块
@rollup/plugin-json 支持引入json
execa 开启子进程方便执行命令
mkdir demo
cd demo
yarn init -y

yarn add typescript rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa -D

tsc --init

# 二、目录结构

├─packages             # N个repo
│  └─reactivity        # 响应式目录
│      │  package.json
│      └─src
│          index.ts
│  └─shared            #公共方法目录
│      │  package.json
│      └─src
│      │  index.ts
└─scripts              # 打包命令
│  │  build.js         # 全部打包
|  |  dev.js           # 单个打包
│  package.json        # 配置运行命令 
│  rollup.config.js    # rollup配置文件
│  tsconfig.json       # ts配置文件 更改为esnext
│  yarn.lock

# 三、代码文件

  • 配置模块名称和打包选项
  • packages/reactivity/package.json
{
  "name": "@vue/reactivity",  // 模块名称
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "module": "dist/reactivity.esm-bundler.js",
  "buildOptions":{  // 打包选项
	"name":"VueReactivity",  // 打包模块的全局变量名称
    "formats":[  // 打包的输出格式
      "cjs",
      "esm-bundler",
      "global"
    ]
  }
}
  • packages/shared/package.json
{
  "name": "@vue/shared",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "module": "dist/shared.esm-bundler.js",
  "buildOptions":{
    "name":"VueShared",
    "formats":[
      "cjs",
      "esm-bundler"
    ]
  }
}
  • package.json
{
  "private": true,  //私有项目
  "workspaces": [   // 工作目录
    "packages/*"
  ],
  "scripts": {  // 打包脚本
    "dev": "node scripts/dev.js",
    "build": "node scripts/build.js"
  }
}
  • scripts/build.js
// 把packages 目录下的所有包都进行打包
// 读取文件
const fs = require('fs');
// 开启子进程 进行打包, 最终还是使用rollup来进行打包
const execa = require('execa');

// 1.读取packages下面的所有文件,并过滤出文件夹
const targets = fs.readdirSync('packages').filter(f => fs.statSync(`packages/${f}`).isDirectory());
// 2. 定义构建函数:开启子进程,构建rollup打包命令
async function build(target) {
	// 当子进程打包的信息共享给父进程 rollup  -c --environment TARGET:shared
	await execa('rollup', ['-c', '--environment', `TARGET:${target}`], {stdio: 'inherit'});
}
// 3.定义并行打包函数:循环进行依次打包,最终返回promise.all的执行结果
function runParallel(targets, iteratorFn) {
	const res = [];
	for (const item of targets) {
		const p = iteratorFn(item);
		res.push(p);
	}
	return Promise.all(res);
}
// 4.并行打包
runParallel(targets, build);
  • scripts/dev.js
// 只针对把packages下具体的某个包打包
// 读取文件
const fs = require('fs');
// 开启子进程 进行打包, 最终还是使用rollup来进行打包
const execa = require('execa');

// 1.手动控制需要打包的目录
const target = 'reactivity';
// 2. 定义构建函数:开启子进程,构建rollup打包命令
async function build(target) {
	// 当子进程打包的信息共享给父进程 rollup  -c --environment TARGET:shared
	await execa('rollup', ['-cw', '--environment', `TARGET:${target}`], {stdio: 'inherit'});
}

// 3.单个打包
build(target);
  • rollup.config.js
// rollup 的配置文件
import path from 'path';
import json from '@rollup/plugin-json';
import resolvePlugin from '@rollup/plugin-node-resolve';
import ts from 'rollup-plugin-typescript2';

// 1.找到packages
const packagesDirs = path.resolve(__dirname, 'packages');
// 2.找到具体要打包的基准目录
const packagesDir = path.resolve(packagesDirs, process.env.TARGET);
// 3.定义针对某个模块的拼接函数
const resolve = p => path.resolve(packagesDir, p);
// 4.找到package.json
const pkg = require(resolve('package.json'));
// 5.拿到具体文件夹名称
const name = path.basename(packagesDir);
// 6.定义打包类型的映射表,根据你提供的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'
	}
}
// 7.拿到自己包在package.json中定义的选项
const options = pkg.buildOptions;
// 8.定义函数用于创建rollup的配置文件
function createConfig(format, output) {
	// 选项覆盖和配置
	output.name = options.name;
	output.sourcemap = true;

	// 生成rollup的配置文件
	return {
		input: resolve(`src/index.ts`),
		output,
		plugins: [
			// 解析json
			json(),
			// ts配置
			ts({
				tsconfig: path.resolve(__dirname, 'tsconfig.json')
			}),
			// 解析第三方模块
			resolvePlugin()
		]
	}
}
// 9.导出rollup的最终配置文件
export default options.formats.map(format => createConfig(format, outputConfig[format]));
  • tsconfig.json
{
  "compilerOptions": {
    "target": "ESNEXT",
    "module": "ESNEXT",
    "strict": false,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
	"moduleResolution": "node",
	"baseUrl": ".",
	"paths": {
		"@vue/*":[
			"packages/*/src"
		]
	}
  }
}

# 四、执行命令

# 单个编译
yarn run dev

# 全部编译
yarn run build