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

相关推荐
lin-lins20 小时前
模块化开发 & webpack
前端·webpack·node.js
柳鲲鹏2 天前
LINUX/CMAKE编译opencv_contrib
linux·opencv·webpack
前端李易安2 天前
webpack的常见配置
前端·webpack·node.js
魏大帅。2 天前
Webpack入门教程:从基本概念到优化技巧
前端·webpack·node.js
web_code3 天前
webpack源码快速分析
前端·webpack·源码阅读
王小金Ryan3 天前
开发一个Vite插件,给所有DOM节点插入自定义属性
vue.js·vite
Aaaaaaaaaaayou3 天前
从零实现 webpack,但 Rust 版 - [4] 实现插件系统
webpack·rust
熊的猫3 天前
从 vue 源码看问题 — vue 初始化都做了什么事?
前端·javascript·vue.js·chrome·webpack·前端框架·node.js
王解3 天前
#Jest进阶知识:整合 webpack 综合练习
前端·javascript·webpack·单元测试·node.js
诗雅颂5 天前
【js逆向学习】某多多anti_content逆向(补环境)
开发语言·javascript·webpack·逆向·拼多多·补环境·anti_content