实现 rollup 实现多模块打包

news/2024/10/17 16:21:20/

rollup 是一个 JavaScript 模块打包器,可以将许多 JavaScript 库和应用程序打包成少量的捆绑包,从而提高了应用程序的性能。本文详细描述如何通过 rollup 实现多模块打包。

前提

项目的目录结构
在这里插入图片描述

先看下项目的 package.json 文件夹:

{"private": true,"workspaces": ["packages/"],"type": "module"
}

workspaces

这里我们使用 workspaces 字段定义 npm 工作空间。它可以让你在同一项目中使用多个独立的 npm 包,这些包可以共享相同的依赖项和环境,使得管理依赖关系变得更加方便。

同时你可以指定一个或多个目录,它们将包含在工作空间中。例子中,将 packages/ 目录包含在工作空间中,意味着在该目录下的所有子目录都将被视为 npm 包,并共享相同的依赖项和环境。

使用工作空间可以大大简化具有多个独立模块或应用的项目的依赖关系管理。你可以在每个模块或应用中独立运行 npm 命令,而无需担心它们之间的依赖关系和环境影响。

需要注意的是,使用工作空间需要你的项目目录结构符合一定的规范,例如每个模块或应用都需要位于 packages/ 目录的子目录中。此外,使用工作空间需要在命令行中运行 npm 命令时,需要使用 “–workspace” 标志来指定要操作的工作空间,例如 npm install rollup -W

同时 “workspaces” 只能在私有项目中使用。这里需要配置 private: true

包使用

通过目录结构可以看到在 packages 里面是有多个 npm 包的那么如何在去引用这些文件呢,例如在 reactivity 里面通过 import xxx from '@vue/shared' 去引用 shared 文件下的某个功能呢?我们经行如下修改:

// tsconfig.json
{"baseUrl": "./","module": "ESNext","moduleResolution": "node",// 省略部分代码"paths": {"@vue/*": ["packages/*/src"]}
}

在 shared 文件夹中补充如下测试代码:

// packages/shared/src/index.ts
export const isArray = Array.isArray

在 reactivity 文件夹下直接引入就行了:

// packages/reactivity/src/index.ts
import { isArray } from '@vue/shared'
console.log(isArray)

打包

既然每个文件都有属于一个独立 npm 模块,也会有一个属于自己的 package.jsonreactivity 为例:

package.json

{"name": "@vue/reactivity","version": "1.0.0","main": "index.js","license": "MIT","buildOptions": {"name": "VueReactivity","formats": ["esm-bundler","cjs","global"]}
}

package.json 里面定义了包的名称以及对应的打包方式,分别是 esmcjsglobal 不同标准的打包方式。

execa

packages/ 目录包含了多个 npm 包那么如何对每个文件经行打包呢,这里我们可以使用 execa

import { readdirSync, statSync } from 'fs'
import { execa } from 'execa'// 1、获取打包目录
const dirs = readdirSync('packages').filter(dir => statSync(`packages/${dir}`).isDirectory()) // [ 'reactivity', 'shared' ]async function build(TARGET) {await execa('rollup', ['-c', '--environment', `TARGET:${TARGET}`], { stdio: 'inherit' })
}function runParaller(dirs) {let result = []for (const dir of dirs) {result.push(build(dir))}return Promise.all(result) // 存放打包的promise
}
// 2、进行打包
runParaller(dirs).then(() => {console.log('success')
})

rollup.config.js

上面代码通过 execa 去执行 rollup 的打包逻辑,这里的 −c 参数表示使用配置文件(默认是 rollup.config.js),−−environment 参数用于指定环境变量, stdio: 'inherit' 表示将命令的标准输入、输出和错误流重定向到父进程的流(即 Node.js 进程的流)。

import { defineConfig } from 'rollup'
import { createRequire } from 'node:module'
import ts from 'rollup-plugin-typescript2'
import json from '@rollup/plugin-json'
import resolvePlugin from '@rollup/plugin-node-resolve' // 解析第三方插件
import path from 'node:path'
import { fileURLToPath } from 'node:url'const require = createRequire(import.meta.url)
const __dirname = path.dirname(fileURLToPath(import.meta.url))// 2.获取文件路径
const packagesDir = path.resolve(__dirname, 'packages')// 2.1 获取需要打包的文件
const packageDir = path.resolve(packagesDir, process.env.TARGET)
const resolve = p => path.resolve(packageDir, p)
// 2.2 获取每个包的配置项
const pkg = require(resolve('package.json')) // 获取 jsonconst name = path.basename(packageDir) // reactivity
// 3、创建一个映射表
const outputConfigs = {'esm-bundler': {file: resolve(`dist/${name}.esm-bundler.js`),format: 'esm'},'cjs': {file: resolve(`dist/${name}.cjs.js`),format: 'cjs'},'global': {file: resolve(`dist/${name}.global.js`),format: 'iife'}
}const packageOptions = pkg.buildOptions || {}// 1、创建一个打包配置
function createConfig(format, output) {output.name = packageOptions.nameoutput.sourcemap = false// 生成rollup配置const config = {input: resolve('src/index.ts'), // 输入output, // 输出plugins: [json(),ts({tsconfig: path.resolve(__dirname, 'tsconfig.json')}),resolvePlugin()]}return config
}const packageFormats = packageOptions.formatsconst packageConfigs = packageFormats.map(format => createConfig(format, outputConfigs[format]))
export default defineConfig(packageConfigs)

测试

example 在新建一个测试文件:

<script src="../packages/shared/dist/shared.global.js"></script>
<script>let { isArray } = VueShared;console.log(isArray([])); // true
</script>

总结

以上大体实现了通过 rollup 实现多模块打包的功能


http://www.ppmy.cn/news/998254.html

相关文章

恒运资本:炒股知识有用吗?

炒股是指通过购买和出售股票来赚取差价的一种出资行为。在现代社会&#xff0c;炒股已经成为许多人重视的话题。然而&#xff0c;有些人以为炒股常识是非常有用的&#xff0c;而另一些人则以为炒股常识并不有用。那么&#xff0c;炒股常识终究有多大的用途呢&#xff1f;本文将…

Java并发系列之三:乐观锁机制

上一篇悲观锁中&#xff0c;我们讲到悲观锁的四种状态时&#xff0c;提到了“无锁”这种状态&#xff0c;并解释其有两种语义&#xff0c;一种是对共享资源不进行任何同步原语保护&#xff1b;另一种是共享资源会出现被竞争的情况&#xff0c;但是不使用操作系统同步进行保护&a…

LeetCode343. 整数拆分

343. 整数拆分 文章目录 [343. 整数拆分](https://leetcode.cn/problems/integer-break/)一、题目二、题解方法一&#xff1a;动态规划方法改良 一、题目 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整…

测试|LoadRunner安装及介绍

测试|LoadRunner安装及介绍 文章目录 测试|LoadRunner安装及介绍1.什么是LoadRunner2.LoadRunner特点3.LoadRunner基本概念4.LoadRunner三大组件之间关系LoadRunner安装1.安装包2.安装loadrunner 1.什么是LoadRunner LoadRunner是用来模拟用户负载完成性能测试的工具。 它适用…

01-Hadoop集群部署(普通用户)

Hadoop集群部署&#xff08;普通用户&#xff09; 环境准备 1&#xff09;准备3台客户机&#xff08;关闭防火墙、静态IP、主机名称&#xff09; 如果这一步已经配置过了&#xff0c;可以忽略 # 1 关闭防火墙 systemctl stop firewalld.service # 关闭当前防火墙 systemctl…

Vue中常用到的标签和指令

一、标签 在 Vue 中&#xff0c;并没有特定的标签是属于 Vue 的&#xff0c;因为 Vue 是一个用于构建用户界面的框架&#xff0c;可以与 HTML 标签一起使用。Vue 中可以使用的标签和元素基本上与 HTML 标准一致。 以下是一些常见的HTML标签&#xff0c;也可以在 Vue 中使用&a…

C#设计模式之---抽象工厂模式

抽象工厂模式&#xff08;Abstract Factory&#xff09; 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。工厂方…

vue3搭建(vite+create-vue)

目录 前提条件 输入命令 对于Add an End-to-End Testing Solution nightwatch和Cypress 和 Playwright 运行 前提条件 熟悉命令行已安装 16.0 或更高版本的 Node.js &#xff08;node -v查看版本&#xff09; 输入命令 npm init vuelatest 这一指令将会安装并执行 create-…