查看源代码 资产管理

除了生成 HTML,大多数 Web 应用程序还有各种资产(JavaScript、CSS、图像、字体等等)。

从 Phoenix v1.7 开始,新应用程序使用 esbuild 通过 Elixir esbuild 包装器 来准备资产,以及使用 tailwindcss 通过 Elixir tailwindcss 包装器 来处理 CSS。与 esbuildtailwind 的直接集成意味着新生成的应用程序没有对 Node.js 或外部构建系统(例如 Webpack)的依赖。

你的 JavaScript 通常放在 "assets/js/app.js" 中,esbuild 会将其提取到 "priv/static/assets/app.js" 中。在开发过程中,这将通过 esbuild 监视器自动完成。在生产环境中,这可以通过运行 mix assets.deploy 来完成。

esbuild 也可以处理你的 CSS 文件,但默认情况下 tailwind 会处理所有 CSS 构建。

最后,所有其他通常不需要预处理的资产直接放在 "priv/static" 中。

第三方 JS 包

如果你想导入 JavaScript 依赖项,至少有三种方法可以将其添加到你的应用程序中

  1. 在你的项目中将这些依赖项作为供应商,并使用相对路径在你的 "assets/js/app.js" 中导入它们

    import topbar from "../vendor/topbar"
  2. 在你的 assets 目录中运行 npm install topbar --saveesbuild 将能够自动获取它们

    import topbar from "topbar"
  3. 使用 Mix 从源代码库跟踪依赖项

    # mix.exs
    {:topbar, github: "buunguyen/topbar", app: false, compile: false}

    运行 mix deps.get 获取依赖项,然后导入它

    import topbar from "topbar"

    新应用程序使用这种第三种方法来导入 Heroicons,避免在可能只使用几个甚至不使用任何图标的情况下提供所有图标的副本,避免使用 Node.js 和 npm,并跟踪一个易于更新的显式版本,这要归功于 Mix。需要注意的是,git 依赖项不能被 Hex 包使用,因此,如果你打算将你的项目发布到 Hex,请考虑将文件作为供应商提供。

图像、字体和外部文件

如果你在 CSS 或 JavaScript 文件中引用了外部文件,esbuild 会尝试验证和管理它们,除非另有说明。

例如,假设你想从你的 CSS 文件中引用 priv/static/images/bg.png,在 /images/bg.png 上提供服务

body {
  background-image: url(/images/bg.png);
}

以上操作可能会失败,并显示以下消息

error: Could not resolve "/images/bg.png" (mark it as external to exclude it from the bundle)

鉴于图像已由 Phoenix 管理,你需要将来自 /images(以及 /fonts)的所有资源标记为外部,如错误消息所述。这是 Phoenix 从 v1.6.1+ 开始对新应用程序默认执行的操作。在你的 config/config.exs 中,你会找到

args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),

如果你需要引用其他目录,你需要相应地更新上面的参数。注意运行 mix phx.digest 会为 priv/static 中的所有资产创建摘要文件,因此你的图像和字体仍然会被缓存。

Esbuild 插件

Phoenix 对 esbuild 的默认配置(通过 Elixir 包装器)不允许你使用 esbuild 插件。如果你想使用 esbuild 插件,例如将 SASS 文件编译成 CSS,你可以使用自定义构建脚本替换默认构建系统。

以下是使用 Node.JS 通过 esbuild 进行自定义构建的示例。首先,你需要在开发中安装 Node.js 并使其可用于你的生产构建步骤。

然后你需要将 esbuild 添加到你的 Node.js 包和 Phoenix 包中。在 assets 目录中,运行

$ npm install esbuild --save-dev
$ npm install ../deps/phoenix ../deps/phoenix_html ../deps/phoenix_live_view --save

或者,对于 Yarn

$ yarn add --dev esbuild
$ yarn add ../deps/phoenix ../deps/phoenix_html ../deps/phoenix_live_view

接下来,添加一个自定义 JavaScript 构建脚本。我们将示例称为 assets/build.js

const esbuild = require("esbuild");

const args = process.argv.slice(2);
const watch = args.includes('--watch');
const deploy = args.includes('--deploy');

const loader = {
  // Add loaders for images/fonts/etc, e.g. { '.svg': 'file' }
};

const plugins = [
  // Add and configure plugins here
];

// Define esbuild options
let opts = {
  entryPoints: ["js/app.js"],
  bundle: true,
  logLevel: "info",
  target: "es2017",
  outdir: "../priv/static/assets",
  external: ["*.css", "fonts/*", "images/*"],
  nodePaths: ["../deps"],
  loader: loader,
  plugins: plugins,
};

if (deploy) {
  opts = {
    ...opts,
    minify: true,
  };
}

if (watch) {
  opts = {
    ...opts,
    sourcemap: "inline",
  };
  esbuild
    .context(opts)
    .then((ctx) => {
      ctx.watch();
    })
    .catch((_error) => {
      process.exit(1);
    });
} else {
  esbuild.build(opts);
}

此脚本涵盖以下用例

  • node build.js:为开发和测试构建(在 CI 上有用)
  • node build.js --watch:与上面类似,但会持续监视更改
  • node build.js --deploy:为生产构建压缩后的资产

修改 config/dev.exs,以便每次更改文件时运行脚本,替换 watchers 下现有的 :esbuild 配置

config :hello, HelloWeb.Endpoint,
  ...
  watchers: [
    node: ["build.js", "--watch", cd: Path.expand("../assets", __DIR__)]
  ],
  ...

修改 mix.exs 中的 aliases 任务,以便在 mix setup 期间安装 npm 包,并在 mix assets.deploy 上使用新的 esbuild

  defp aliases do
    [
      setup: ["deps.get", "ecto.setup", "cmd --cd assets npm install"],
      ...,
      "assets.deploy": ["cmd --cd assets node build.js --deploy", "phx.digest"]
    ]
  end

最后,从 config/config.exs 中删除 esbuild 配置,并从你 mix.exs 中的 deps 函数中删除依赖项,你就完成了!

其他 JS 构建工具

如果你正在编写 API 或想使用其他资产构建工具,你可能想删除 esbuild Hex 包(见下面的步骤)。然后你必须按照第三方工具所需的额外步骤进行操作。

删除 esbuild

  1. 删除 config/config.exsconfig/dev.exs 中的 esbuild 配置,
  2. 删除 mix.exs 中定义的 assets.deploy 任务,
  3. mix.exs 中删除 esbuild 依赖项,
  4. 解锁 esbuild 依赖项
$ mix deps.unlock esbuild

其他 CSS 框架

默认情况下,Phoenix 使用 tailwind 库及其默认插件生成 CSS。

如果你想使用外部 tailwind 插件或其他 CSS 框架,你应该替换 tailwind Hex 包(见下面的步骤)。然后你可以使用 esbuild 插件(如上所述)甚至完全使用另一个框架。

删除 tailwind

  1. 删除 config/config.exsconfig/dev.exs 中的 tailwind 配置,
  2. 删除 mix.exs 中定义的 assets.deploy 任务,
  3. mix.exs 中删除 tailwind 依赖项,
  4. 解锁 tailwind 依赖项
$ mix deps.unlock tailwind

你也可以选择删除和删除 heroicons 依赖项。