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的返回值作为新的入口列表重写默认的构建工具入口点配置

相关推荐
liangshanbo121514 小时前
Webpack 文件指纹面试题整理
前端·webpack·node.js
liangshanbo121515 小时前
Webpack 常见 Plugin 面试题
前端·webpack·node.js
liangshanbo121516 小时前
Webpack Tree Shaking 面试题整理
前端·webpack·node.js
陪我一起学编程18 小时前
vue3笔记
前端·webpack·vue3·vite·脚手架·vue3笔记·组件式
liangshanbo121520 小时前
Webpack的分包策略面试题
前端·webpack·node.js
liangshanbo12152 天前
面试题:如何优化 Webpack 的打包速度?
前端·webpack·node.js
晚风醉蝶4 天前
webpack 模块提取
前端·webpack·node.js·ast·逆向分析
晚风醉蝶14 天前
保姆级教程:用 AST 自动提取 webpack / rspack 打包后的模块
webpack·web逆向
向北丶16 天前
vite项目中配置alias别名
前端·vite
PedroQue9916 天前
修复 .uvue 页面路径残留问题
前端·vite