mcpField
E
elixir-phoenix

elixir-phoenix

github.com/gsmlg-dev开发037 次安装3 周前更新
代码仓库

关于 elixir-phoenix

elixir-phoenix 是面向 Phoenix 项目的配置技能,采用 Bun、Tailwind v4、devenv 和 PostgreSQL。它提供资源构建、数据库连接、运行时二进制文件及显式执行端到端测试的配置模式。

主要功能

  1. 01配置 Bun 替代 esbuild
  2. 02设置 Tailwind v4 资源工作流
  3. 03配置 devenv 和 PostgreSQL
  4. 04通过 NODE_PATH 解析 Phoenix JavaScript 依赖
  5. 05配置运行时二进制文件路径
  6. 06将端到端测试设为手动执行

适用场景

  1. 01创建使用 PostgreSQL 的 Phoenix 项目
  2. 02配置 Bun 和 Tailwind 资源构建
  3. 03使用 devenv 设置本地开发环境
  4. 04仅在明确要求时运行端到端测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gsmlg-dev/code-agent --skill elixir-phoenix

安装后在 Claude Code 中输入/elixir-phoenix确认已加载。

附带文件references/devenv-template.md

详细介绍

Phoenix 项目设置

使用 Bun、Tailwind v4、devenv 和 PostgreSQL 的 Phoenix 项目标准模式。

1. 创建 Phoenix 项目

# Standard project
mix phx.new my_app --database postgres

# Umbrella app
mix phx.new my_app --umbrella --database postgres

生成后,将默认的 esbuild 配置替换为 bun。

2. 将 esbuild 替换为 Bun

在 mix.exs 的 deps 中,将 {:esbuild, ...} 替换为:

{:bun, "~> 1.4", runtime: Mix.env() == :dev},
{:tailwind, "~> 0.2", runtime: Mix.env() == :dev},

在 config/config.exs 中,将 config :esbuild 代码块替换为:

config :bun,
  version: "1.3.4",
  my_app: [
    args: ~w(build assets/js/app.js --outdir=priv/static/assets --external /fonts/* --external /images/*),
    cd: Path.expand("../", __DIR__)
  ]

config :tailwind,
  version: "4.1.11",
  my_app: [
    args: ~w(--input=assets/css/app.css --output=priv/static/assets/app.css),
    cd: Path.expand("../", __DIR__)
  ]

对于 umbrella 应用,将 Path.expand("../apps/my_app", __DIR__) 用于 cd:。

在 config/dev.exs 中,更新 watchers:

watchers: [
  tailwind: {Tailwind, :install_and_run, [:my_app, ~w(--watch)]},
  bun: {Bun, :install_and_run, [:my_app, ~w(--sourcemap=inline --watch)]}
]

更新 mix.exs 别名:

"assets.deploy": [
  "phx.digest.clean",
  "tailwind my_app --minify",
  "bun my_app --minify",
  "phx.digest"
]

3. 设置 NODE_PATH 以解析 Phoenix 依赖

将 NODE_PATH 设置为项目根目录的 deps/ 目录,以便 Bun 从 Phoenix 的 deps/ 目录解析 Node 风格的包。像 import {Socket} from "phoenix" 和 import "phoenix_html" 这样的导入会解析到 Elixir 依赖包,无需 node_modules/。

在 devenv.nix 中,已使用绝对路径完成配置:

env.NODE_PATH = "${config.git.root}/deps";

对于非 devenv 设置,请在 shell 或构建脚本中导出该变量:

export NODE_PATH="$(pwd)/deps"

无需 npm install 或符号链接——Phoenix 会将 JS 与 Elixir 源代码一起放在 deps/<package>/priv/static/ 中。

5. 配置 runtime.exs 以使用二进制文件路径

在 config/runtime.exs 中读取环境变量,以使用 devenv 提供的二进制文件,而不是下载副本。两个包都需要显式配置:

if System.get_env("MIX_BUN_PATH") do
  config :bun, path: System.get_env("MIX_BUN_PATH")
end

if System.get_env("MIX_TAILWIND_PATH") do
  config :tailwind, path: System.get_env("MIX_TAILWIND_PATH")
end

设置 path 后,hex 包会跳过下载,直接使用提供的二进制文件。devenv 通过 lib.getExe 设置这些环境变量,指向 Nix store 路径(参见第 4 步)。

6. 设置 devenv

完整的 devenv.yaml 和 devenv.nix 模板请参见 references/devenv-template.md。

要点:

  • lib.getExe 会解析 MIX_BUN_PATH 和 MIX_TAILWIND_PATH 的 Nix store 路径
  • PostgreSQL 仅通过 Unix socket 运行(listen_addresses = "")——不会发生端口冲突
  • DATABASE_URL 使用 ?socket= 参数指向 devenv 的状态目录
  • 设置 PGHOST,以便 psql 和 Ecto 自动找到 socket

7. 配置 Ecto 使用基于 URL 的连接

在 config/dev.exs 中,同时支持 Unix socket(devenv)和 TCP(手动设置):

db_config =
  [
    username: System.get_env("POSTGRES_USER", "my_app_dev"),
    password: System.get_env("POSTGRES_PASSWORD", "my_app_dev"),
    database: System.get_env("POSTGRES_DB", "my_app_dev"),
    show_sensitive_data_on_connection_error: true,
    pool_size: 10
  ]
  |> then(fn config ->
    case System.get_env("PGHOST") do
      nil ->
        config ++ [hostname: System.get_env("POSTGRES_HOST", "localhost"),
                   port: String.to_integer(System.get_env("POSTGRES_PORT", "5432"))]
      pghost when is_binary(pghost) ->
        if String.starts_with?(pghost, "/") do
          config ++ [socket_dir: pghost]
        else
          config ++ [hostname: pghost,
                     port: String.to_integer(System.get_env("POSTGRES_PORT", "5432"))]
        end
    end
  end)

config :my_app, MyApp.Repo, db_config

这会自动检测 PGHOST 是 Unix socket 路径还是主机名。

8. 通过 URL 配置生产数据库

在生产环境的 config/runtime.exs 中:

if config_env() == :prod do
  database_url =
    System.get_env("DATABASE_URL") ||
      raise "DATABASE_URL is not set"

  config :my_app, MyApp.Repo,
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE", "10"))
end

9. 端到端测试

端到端测试位于标准 test/ 文件夹旁的 e2e_test/ 中。运行这些测试成本较高,绝不能自动运行——只能在明确请求时运行。

在 mix.exs 中添加 test.e2e 别名:

defp aliases do
  [
    # ... existing aliases ...
    "test.e2e": ["run --no-halt", "cmd mix test e2e_test/"]
  ]
end

在 mix.exs 项目配置中将 e2e_test/ 配置为额外测试路径,让 Mix 能找到辅助文件,但要将其排除在默认的 mix test 运行之外:

def project do
  [
    # ...
    test_paths: ["test"],
    elixirc_paths: elixirc_paths(Mix.env()),
  ]
end

显式运行端到端测试:

mix test.e2e

绝不要将 test.e2e 添加到 CI 流水线、提交前钩子,或任何会在常规构建或测试流程中运行的自动化别名中。

快速参考

工具Hex 包环境变量devenv 来源
Bun{:bun, "~> 1.4"}MIX_BUN_PATHlib.getExe pkgs.bun
Tailwind{:tailwind, "~> 0.2"}MIX_TAILWIND_PATHlib.getExe pkgs.tailwindcss_4
PostgreSQL{:ecto_sql, ...} + {:postgrex, ...}DATABASE_URL / PGHOSTservices.postgres

评论

支持 Markdown