返回

优雅地打包非JavaScript静态资源

前端

今天想与大家讨论一个一直困扰前端开发人员的问题,那就是打包非JavaScript静态资源,以供将其并入构建后的 JavaScript 代码包中。

大多数情况下,这些资源可以是用于页面的图像、用于应用程序的图标、工作者脚本或者一些可执行二进制文件,这些二进制文件可能是编译自 Rust 的 WASM 文件,或者是编译自 C++ 的 Emscripten 二进制文件。

有各种方法可以在网络上包含这些非 JavaScript 静态资源,但它们有各自的优缺点,而且都不能同时在所有工具链中工作。一些未来的提议可能会让我们用专门的语法来导入这些资源,但我们还没有走到这一步。

针对这一问题,我来详细展开聊聊,并探索可行的解决方案。

现有方法

  • 使用 JavaScript fetch API
fetch('/static/icon.png')
  .then(response => response.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    const image = new Image();
    image.src = url;
    document.body.appendChild(image);
  });

这种方法的优点在于简单易用,且与所有 JavaScript 工具链兼容。缺点是可能会导致 HTTP 请求过多,这可能会降低性能。

  • 使用 JavaScript import 语句
import icon from '/static/icon.png';

const image = new Image();
image.src = icon;
document.body.appendChild(image);

这种方法的优点在于与 JavaScript 模块系统无缝集成,并且不会导致额外的 HTTP 请求。缺点是它只适用于支持 ES 模块的工具链。

  • 使用 CSS url() 函数
body {
  background-image: url('/static/background.png');
}

这种方法的优点在于简单易用,并且与所有 CSS 工具链兼容。缺点是它只能用于加载图像,而且可能会导致 HTTP 请求过多。

  • 使用 HTML <link> 标签
<link rel="icon" href="/static/favicon.ico">

这种方法的优点在于简单易用,并且与所有 HTML 工具链兼容。缺点是它只能用于加载图标。

潜在解决方案

目前,有几个提案正在讨论如何将非 JavaScript 静态资源导入到 JavaScript 代码中。

这种方法允许将任何文件导入到 Webpack 中,而无需将其转换为 JavaScript。缺点是它只会将文件复制到构建后的代码包中,而不会对其进行任何处理。

这种方法允许将 C++ 代码编译为 WASM,然后将其导入到 JavaScript 代码中。缺点是它需要安装额外的工具,并且可能很难设置。

这种方法允许将 C 代码编译为 Go 二进制文件,然后将其导入到 Go 代码中。缺点是它需要安装额外的工具,并且可能很难设置。

这种方法允许生成 Go 代码,然后将其编译为二进制文件。缺点是它需要安装额外的工具,并且可能很难设置。

Rust 提供了一种将 Rust 代码编译为 WASM 的方法,然后可以将其导入到 JavaScript 代码中。缺点是它需要安装额外的工具,并且可能很难设置。

Pkg-config 是一种用于查找和配置库的工具。它可以与 Rust、C 和 C++ 一起使用,以帮助您将非 JavaScript 静态资源导入到 JavaScript 代码中。缺点是它可能很难设置。

替代方法

如果上面的方法都不适合您,则还可以考虑以下替代方法:

  • 使用 CDN 来托管您的非 JavaScript 静态资源。这将减少 HTTP 请求的数量,并可能提高性能。
  • 将您的非 JavaScript 静态资源打包成一个单独的文件,然后将其作为 <script> 标签的一部分加载。这将减少 HTTP 请求的数量,并可能提高性能。
  • 使用清单文件来管理您的非 JavaScript 静态资源。这将使您可以轻松地跟踪您的资源,并确保它们被正确地打包到您的构建后的代码包中。

结论

有各种方法可以在网络上包含非 JavaScript 静态资源,但它们有各自的优缺点,而且都不能同时在所有工具链中工作。一些未来的提议可能会让我们用专门的语法来导入这些资源,但我们还没有走到这一步。

在选择哪种方法时,您需要考虑您的具体需求和约束。如果您需要一种简单易用且与所有工具链兼容的方法,则可以使用 JavaScript fetch API 或 JavaScript import 语句。如果您需要一种更强大且可定制的方法,则可以使用 Webpack loader、Emcc、Cgo、Go generate、Rust 或 Pkg-config。