3行代码即可在你的项目中集成bundle-less构建

上一篇,介绍了unbuild的插桩技术,并且该文章冲到了热榜第六。想来大家对unbuild还是满感兴趣的。故本文再接再厉,来分析unbuild的另一项技术点:bundleless

unbuild中实现该能力是依靠的mkdist包

何为bundleless

bundleless和bundle是相对应的,即是否打包合并

在传统的webpack构建过程中,是会从入口开始,在无拆分的情况下,你得到的将是一个完整的包含所有模块内容的.js文件

而较新的vite则利用浏览器对esm的支持,在开发阶段实现了按模块进行读取,而不是加载一整个构建后的文件(注:想要了解vite实现的可以关注笔者公众号,目前正在针对vite更新系列文章

这二者的区别就是:是否合并bundle

本文目标

了解mkdist的核心实现流程

既是核心,笔者就不会对其进行细致拆分,实际上,笔者看这部分代码也是直接通过github看的。故若细节上有偏差,还望各位看官海涵

源码解析

将代码定位到src/make.ts,这是包的起点。根据笔者个人喜好,它大致可以分为如下几个阶段:初始化准备、编译、重写导入、生成入口、外部集成

  • 初始化准备

这包括参数准备。如下,默认将src/index作为入口,将dist作为出口

ts 复制代码
options.rootDir = resolve(process.cwd(), options.rootDir || ".");
options.srcDir = resolve(options.rootDir, options.srcDir || "src");
options.distDir = resolve(options.rootDir, options.distDir || "dist");

输入地准备。如下,创建一个空的dist目录。但下边这三个操作笔者个人感觉是有重复部分的,按文档来说,只需要emptyDir或者mkdirp一个操作就够了

ts 复制代码
if (options.cleanDist !== false) {
    await fse.unlink(options.distDir).catch(() => {});
    await fse.emptyDir(options.distDir);
    await fse.mkdirp(options.distDir);
}

最后就是文件目录准备。如下,mkdist将入口src下的所有文件扫描出来,并格式化处理成指定的格式

ts 复制代码
const { globby } = await import("globby");
const filePaths = await globby(options.pattern || "**", {
    absolute: false,
    cwd: options.srcDir,
});

const files: InputFile[] = filePaths.map((path) => {
    const sourcePath = resolve(options.srcDir, path);
    return {
      path,
      srcPath: sourcePath,
      extension: extname(path),
      getContents: () => fse.readFile(sourcePath, { encoding: "utf8" }),
    };
});
  • 编译

这里说的编译其实并不准确,因为它的实际编译过程其实是在unbuild中的,不过笔者看它以loader来处理,且也包含内容处理的逻辑,故以此命名

ts 复制代码
const { loadFile } = createLoader(options);

其实loader是什么并不需要关心,根据webpack的理念,它无非是针对各种文件类型的处理,事实上也确实如此

  • 重写导入

这部分包含import、require等,核心就是对路径的重写

ts 复制代码
output.contents = output.contents.replace(
    /require\((["'])(.*)(["'])\)/g,
    (_, head, id, tail) =>
      "require(" +
      head +
      resolveId(output.path, id, cjsResolveExtensions) +
      tail +
);
  • 生成入口

最后一步,就是对这些路径进行收集,将其在dist目录下创建一份,然后将其作为新的入口收集起来等待被unbuild调用即可

ts 复制代码
const writtenFiles: string[] = [];
  await Promise.all(
    outputs
      .filter((o) => !o.skip)
      .map(async (output) => {
        const outFile = join(options.distDir, output.path);
        await fse.mkdirp(dirname(outFile));
        await (output.raw
          ? copyFileWithStream(output.srcPath, outFile)
          : fse.writeFile(outFile, output.contents, "utf8"));
        writtenFiles.push(outFile);
      }),
  );
  • 外部集成

最后只需要在外部构建工具(这里指的unbuild)中集成即可实现bundleless,如下,拿到mkdist收集到的入口列表重写配置项即可

总结

通过对unbuild的分析,现在可以来呼应题目了,所谓3行指的是:

  • 一行引入

你需要在你的构建工程中引入mkdist包

  • 一行调用

你需要嵌入你的构建工程运行流程并对mkdist进行调用

  • 一行重写

你需要将mkdist的返回值作为新的入口列表重写默认的构建工具入口点配置

相关推荐
Hashan10 小时前
深入理解:Webpack编译原理
前端·webpack
子兮曰11 小时前
🚀Vue3异步组件:90%开发者不知道的性能陷阱与2025最佳实践
前端·vue.js·vite
一枚前端小能手16 小时前
🔥 老板要的功能Webpack没有?手把手教你写个插件解决
前端·javascript·webpack
Hashan18 小时前
你知道Webpack解决的问题是什么嘛?
前端·webpack
vipbic2 天前
关于Vue打包的遇到模板引擎解析的引号问题
前端·webpack
妮妮喔妮2 天前
Webpack 有哪些特性?构建速度?如何优化?
前端·webpack·node.js
ST.J2 天前
webpack笔记
前端·笔记·webpack
webYin2 天前
vue2 打包生成的js文件过大优化
前端·vue.js·webpack
!执行2 天前
webpack 相关配置
webpack
拜无忧2 天前
【教程】vue+vite+ts创建一个最新的高性能后台项目架构
vue.js·typescript·vite