title: vue3源碼手寫-打包配置
date: 2023-03-19 22:00:00
categories: 源碼
tags: VUE3
vue3源碼手寫-打包配置
文件夾創(chuàng)建
在packages文件夾下面創(chuàng)建reactivity和shared文件夾,初始化創(chuàng)建對應的package.json并且創(chuàng)建src文件夾下面再創(chuàng)建一個index.tS文件
// reactivity -> package.json
{
// 打包更具這個名稱生成文件在node_modules中
"name": "@vue/reactivity",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"license": "MIT",
// 打包生成的文件類型格式打包后能在dist文件中體現(xiàn)
"buildOptions": {
"name": "vueReactivity",
"formats": [
"esm-bundler",
"cjs",
"global"
]
}
}
// shared -> package.json
{
// 打包更具這個名稱生成文件在node_modules中
"name": "@vue/shared",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"license": "MIT",
// 打包生成的文件類型格式打包后能在dist文件中體現(xiàn)
"buildOptions": {
"name": "vueShared",
"formats": [
"esm-bundler",
"cjs"
]
}
}
在寫源碼之前我們要把項目搭建好,上次我們搭建了環(huán)境,那么解下來就是對項目進行打包配置。vue3是如何能做到每個文件獨立運行也能打包在一塊呢。
1. 我們先對package.json動手
"private": true,//表示這是一個私有項目,不會被 publish 到 npm庫
"type": "module",// 這里是開啟ES6模塊,vue3不支持commonjs。你可以先不管他,等你在引入文件操作文件的時候會提醒你
"workspaces": [//簡單講就是將每個項目的 node_modules 都提升到根目錄的 node_modules 中,形成多個項目復用同一套依賴包效果。
"packages/*"
],
"scripts": {//書寫腳本
"build": "node scripts/build.js", // 打包腳本
"dev": "node scripts/dev.js" // 打包dev環(huán)境
},
2. 在我們配置好了package.json 腳本之后我們要在根目錄下面創(chuàng)建scripts文件夾和build.js與dev.js這倆個腳本文件
3. 我們先對build.js書寫打包時所需要執(zhí)行的代碼
// 編輯打包設置文件 monerepo
// node 內(nèi)置文件讀寫方法
import fs from "fs"
import { execa } from "execa"
// fs.readdirSync 讀取對應文件夾下面的目錄
const dirs = fs.readdirSync("packages").filter((p) => {
// 對應路徑下的文件是否是文件夾
if (!fs.statSync(`packages/${p}`).isDirectory()) {
return false
}
return true
})
// 對所有的文件進行遍歷并行執(zhí)行打包動作
const runParallel = (targets, buildFn) => {
const res = []
for (const target of targets) {
res.push(buildFn(target))
}
return Promise.all(res)
}
// 打包核心調(diào)用execa執(zhí)行 rollup 配置打包
const build = async(pkg) => {
// 這里執(zhí)行完打包結束
await execa('rollup', ['-c', '--environment', `TARGET:${pkg}`], { stdio: 'inherit' })
}
// 調(diào)用打包函數(shù)
runParallel(dirs, build)
腳本書寫完了就要接著上面的寫rollup配置文件,我們在執(zhí)行build腳本的時候會去調(diào)用配置文件,創(chuàng)建rollup.config.js文件,在根目錄下創(chuàng)建。
// 解析ts 插件
import ts from 'rollup-plugin-typescript2'
// 解下json的插件
import json from '@rollup/plugin-json'
// 解析第三方插件
import resolvePlugin from '@rollup/plugin-node-resolve'
// 創(chuàng)建 require 的方法
import { createRequire } from 'node:module'
// 獲取更目錄的
import { fileURLToPath } from 'node:url'
// 獲取path 方法
import path from 'node:path'
const require = createRequire(
import.meta.url)
const __dirname = fileURLToPath(new URL('.',
import.meta.url))
// 獲取文件路徑
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`))
// 取出包名
const name = path.basename(packageDir)
// 創(chuàng)建格式對應表
const outputOpions = {
"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"
},
}
// 獲取每個包下面設定的buildOptions格式
const options = pkg.buildOptions
// 設置打包函數(shù)
function createConfig(format, output) {
// 進行打包
output.name = options.name
output.sourcemap = true
// 生成rollup配置
return {
input: resolve("src/index.ts"), //導入
// 打包配置
output,
// 這里是插件的調(diào)用
Plugin: [
json(),
ts({
tsconfig: path.resolve(__dirname, 'tsconfig.json')
}),
resolvePlugin()
]
}
}
// 注意打包結束的時候一定要retun對象
export default options.formats.map(format => createConfig(format, outputOpions[format]))
上面的代碼就是打包配置,rollup打包工具會根據(jù)你的打包進行
tsconfig文件修改
{
"compilerOptions": {
/* Language and Environment */
// 需要更改不支持ES5
"target": "ESNext",
// 需要更改不支持ES5
"module": "ESNext", /* Specify what module code is generated. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules.
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
// 不使用嚴格模式 個人選擇
"strict": false, /* Enable all strict type-checking options. */
"skipLibCheck": true,
// 下面這些是文件路徑配置,在引用別的包的時候TS檢索不會報錯
"baseUrl": ".",
"moduleResolution": "node",
"paths": {
"@vue/*": ["packages/*/src"]
}
}
}
dev.js 腳本編寫
// 編輯打包設置文件 monerepo
// node 內(nèi)置文件讀寫方法
import { execa } from "execa"
const build = async(pkg) => {
// -cw 監(jiān)聽 相當于熱跟新
await execa('rollup', ['-cw', '--environment', `TARGET:${pkg}`], { stdio: 'inherit' })
}
// 打包函數(shù)
build("reactivity")
這個是打包配置文件,進行到這里就已經(jīng)能將我們需要寫的東西編譯出來。后續(xù)文章開始我們進行源碼書寫,感興趣的同學一起來啊。