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

相关推荐
Tandy12356_1 天前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
TonyH20021 天前
webpack 4 的 30 个步骤构建 react 开发环境
前端·css·react.js·webpack·postcss·打包
你会发光哎u1 天前
Webpack模式-Resolve-本地服务器
服务器·前端·webpack
Small-K2 天前
前端框架中@路径别名原理和配置
前端·webpack·typescript·前端框架·vite
小茹想睡觉5 天前
vite 底层解析
vite
ziyu_jia5 天前
webpack配置全面讲解【完整篇】
前端·webpack·前端框架·node.js
谢尔登5 天前
【Webpack】优化前端开发环境的热更新效率
前端·webpack·node.js
你会发光哎u5 天前
了解Webpack并处理样式文件
前端·webpack·node.js
不穿铠甲的穿山甲5 天前
webpack使用
前端·webpack·npm
几何心凉5 天前
Webpack 打包后文件过大,如何优化?
前端·webpack·node.js