返回
Rollup 实践系列 01:从零开始手写一个 rollup
前端
2023-11-18 19:17:43
rollup 与其思想
rollup 作为一款前端模块打包工具,在构建和优化 JavaScript 应用程序中发挥着重要作用。它通过将多个 JavaScript 模块组合成一个或多个更优化的 JavaScript 文件,实现模块化开发和性能优化。
rollup 的思想是以树状结构来解析和分析模块间的依赖关系,并据此决定需要打包的文件,最终生成一个捆绑包(Bundle)。其中,打包过程中运用一种被称为 Tree-Shaking 的优化技术,专门去除未被使用的代码,从而有效缩小文件体积,提升运行性能。
需求:自己的 rollup
手写 rollup,目的是深入了解 rollup 打包工具的工作原理与模块打包流程,为自定义的构建配置以及打包优化积累经验。
rollup 初探
思路
- 首先需要收集项目的源码文件以及其依赖文件。
- 然后根据依赖关系构建一个有向图。
- 根据有向图进行拓扑排序,得到一个有序的文件列表。
- 最后根据有序的文件列表进行打包。
实现步骤
1. 收集文件
通过 fs
模块遍历项目目录,收集项目的所有源码文件以及其依赖文件。
const fs = require("fs");
function collectFiles(dir) {
const files = [];
const dirs = [];
const filesInDir = fs.readdirSync(dir);
for (const file of filesInDir) {
const path = `${dir}/${file}`;
const stat = fs.statSync(path);
if (stat.isFile()) {
files.push(path);
} else if (stat.isDirectory()) {
dirs.push(path);
}
}
for (const d of dirs) {
files.push(...collectFiles(d));
}
return files;
}
2. 构建有向图
根据收集到的文件,通过分析每个文件的依赖关系,构建一个有向图。
function buildGraph(files) {
const graph = {};
for (const file of files) {
const dependencies = [];
const code = fs.readFileSync(file, "utf-8");
const matches = code.match(/require\("(.+)"\)/g);
if (matches) {
for (const match of matches) {
const dependency = match.slice(9, -2);
dependencies.push(dependency);
}
}
graph[file] = dependencies;
}
return graph;
}
3. 拓扑排序
对有向图进行拓扑排序,得到一个有序的文件列表。
function topologicalSort(graph) {
const sorted = [];
const visited = {};
for (const node in graph) {
if (!visited[node]) {
visit(node);
}
}
function visit(node) {
visited[node] = true;
for (const neighbor of graph[node]) {
if (!visited[neighbor]) {
visit(neighbor);
}
}
sorted.push(node);
}
return sorted.reverse();
}
4. 打包
根据有序的文件列表,进行打包。
function bundle(files) {
const output = [];
for (const file of files) {
output.push(`// ${file}`);
output.push(fs.readFileSync(file, "utf-8"));
}
return output.join("\n");
}
5. 输出结果
将打包后的结果输出到指定文件。
const outputFile = "bundle.js";
fs.writeFileSync(outputFile, bundle(sortedFiles));
总结
手写 rollup,不仅加深了对 rollup 打包工具的工作原理以及模块打包流程的理解,也为自定义的构建配置以及打包优化积累了经验。