引言
Mix 是 Elixir 的构建工具——创建项目、管理依赖、编译、测试、发布,一站式搞定。它背后是 Erlang 生态的成熟工程实践:从 Hex 包仓库到 OTP release。本文讲透 Mix 工作流:项目结构、依赖、环境配置、测试质量、以及生产发布与 CI。
前置:/elixir-intro-phoenix/(Elixir/Phoenix 基础)、/elixir-testing-property/(测试方法论)、/erlang-hot-code-upgrade/(OTP release)。
目录
- 1. Mix 是什么
- 2. 项目结构与 mix new
- 3. 自定义任务 Mix.Tasks
- 4. 依赖管理与 Hex
- 5. 配置与环境 Mix.Config
- 6. 测试与代码质量
- 7. 编译与增量构建
- 8. 发布与部署:mix release
- 9. CI 集成与常见陷阱
- 10. 速查表与一句话记忆
- 延伸阅读
1. Mix 是什么
1.1 一站式构建工具
✓ 项目脚手架(mix new)
✓ 依赖管理(Hex / mix deps)
✓ 编译(mix compile)
✓ 测试(mix test)
✓ 发布(mix release)
✓ 自定义任务(Mix.Tasks.*)
1.2 Mix 与 OTP 的关系
Mix 构建的应用本质是 OTP 应用(app tree + supervision tree),发布后用 bin/app start 启动,配合热升级/监控。
记忆:Mix = Elixir 的一站式构建工具(脚手架/依赖/编译/测试/发布),构建出的应用是 OTP 应用——与 Erlang 生态无缝衔接。
2. 项目结构与 mix new
2.1 生成项目
mix new my_app # 普通应用
mix new my_app --sup # 带 supervisor(推荐)
mix phx.new my_app # Phoenix Web 应用
2.2 目录结构
my_app/
├── lib/ # 源码
│ ├── my_app.ex # 应用模块(use Application)
│ └── my_app/ # 子模块
├── test/ # 测试(my_app_test.exs)
├── config/ # 配置(config.exs / 环境)
├── mix.exs # 项目定义(依赖/应用/版本)
├── mix.lock # 依赖锁定版本
└── README.md
2.3 mix.exs 关键配置
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :my_app,
version: "0.1.0",
elixir: "~> 1.14",
deps: deps(),
releases: releases()
]
end
def application do
[extra_applications: [:logger], mod: {MyApp.Application, []}]
end
defp deps do
[
{:jason, "~> 1.4"},
{:plug_cowboy, "~> 2.0"}
]
end
end
记忆:mix new –sup 生成 OTP 应用骨架(lib/test/config + mix.exs/mix.lock);mix.exs 是项目定义——deps 依赖、application 应用模块、releases 发布。
3. 自定义任务 Mix.Tasks
3.1 定义一个任务
# lib/mix/tasks/hello.ex
defmodule Mix.Tasks.Hello do
use Mix.Task
@shortdoc "打印问候"
def run(_args) do
Mix.shell().info("Hello, Mix!")
end
end
3.2 使用
mix hello
# → Hello, Mix!
3.3 任务内部访问应用环境
def run(args) do
Mix.Task.run("app.start") # 启动应用(能访问 Application env)
MyApp.some_function()
end
记忆:自定义任务 = use Mix.Task + run/1(Mix.shell().info 输出),需要应用环境时先 Mix.Task.run(“app.start”)——团队脚本标准化的入口。
4. 依赖管理与 Hex
4.1 Hex 生态
Hex 是 Elixir 的包管理器(类似 npm/crates.io),hex.pm 托管。
mix local.hex --force # 安装 Hex
mix hex.search jason # 搜索包
mix deps.get # 拉取依赖
mix deps.update jason # 更新依赖
mix deps.tree # 查看依赖树
4.2 mix.lock
锁定精确版本,保证环境一致:
mix deps.get # 生成/更新 mix.lock
mix deps.compile # 编译依赖
# mix.lock 必须提交到 git
4.3 依赖来源
{:jason, "~> 1.4"}, # Hex 包(语义化版本)
{:my_lib, path: "../my_lib"}, # 本地路径(开发)
{:my_lib, github: "user/my_lib"}, # GitHub
{:my_lib, ">= 0.1.0", only: :dev} # 仅开发环境
记忆:依赖管理走 Hex——mix deps.get 拉取 + mix.lock 锁定 + deps.tree 查树;来源支持 Hex/路径/Git,only: :dev 限定环境——mix.lock 必须入库保证可复现。
5. 配置与环境 Mix.Config
5.1 config 目录
# config/config.exs(公共配置)
import Config
import_config "#{config_env()}.exs" # 按环境加载
# config/dev.exs
config :my_app, MyApp.Repo, username: "postgres", database: "my_app_dev"
# config/prod.exs(生产)
config :my_app, MyApp.Repo, username: System.fetch_env!("DB_USER")
5.2 运行时读取
# 读取配置
Application.get_env(:my_app, :timeout, 5000)
# 运行时环境变量(生产推荐)
System.get_env("MY_APP_SECRET")
记忆:配置分层——config.exs 公共 + config_env().exs 按环境;运行时用 Application.get_env 读取、生产密钥用 System.get_env 环境变量注入。
6. 测试与代码质量
6.1 mix test 体系
mix test # 跑全部
mix test test/foo_test.exs # 指定文件
mix test --cover # 覆盖率
mix test --trace # 详细输出
6.2 质量工具链
# mix.exs deps
{:credo, "~> 1.7", only: [:dev, :test], runtime: false}, # 代码规范
{:dialyxir, "~> 1.4", only: [:dev], runtime: false}, # 类型分析
{:excoveralls, "~> 0.18", only: [:test], runtime: false} # 覆盖率
mix credo # 规范检查
mix dialyzer # Dialyzer 类型分析
mix coveralls.report # 覆盖率报告
6.3 质量门禁
✓ mix format --check-formatted(格式检查)
✓ mix credo --strict(规范)
✓ mix dialyzer(类型)
✓ mix test --cover(覆盖率阈值)
记忆:质量四件套——mix format 格式、credo 规范、dialyzer 类型、test –cover 覆盖率;CI 里全部门禁,mix.lock 保证测试可复现。
7. 编译与增量构建
7.1 增量编译
Mix 只重新编译变化的文件:
mix compile # 编译(增量)
mix compile --force # 全量重编
mix clean # 清理
mix deps.compile # 编译依赖
7.2 编译产物
_build/ # 编译产物(dev/prod 分离)
deps/ # 依赖源码
elixir/ # Elixir 版本管理(mise/asdf)
记忆:Mix 增量编译(只编变化文件)——_build/ 产物按环境分离、deps/ 依赖源码、force 全量重编;配合 .formatter.exs 统一格式。
8. 发布与部署:mix release
8.1 构建 release
# mix.exs
def releases do
[
my_app: [
include_executables_for: [:unix],
steps: [:assemble]
]
]
end
MIX_ENV=prod mix release
# → _build/prod/rel/my_app/
8.2 启动与管理
_build/prod/rel/my_app/bin/my_app start # 启动
_build/prod/rel/my_app/bin/my_app daemon # 后台
_build/prod/rel/my_app/bin/my_app stop # 停止
_build/prod/rel/my_app/bin/my_app eval "MyApp.foo()" # 执行
8.3 release 优势
✓ 自带 OTP VM + 应用,无需源码环境
✓ 部署零依赖(目标机不需要 Elixir)
✓ 配合热升级(release_handler)
✓ 生产配置用环境变量注入
记忆:mix release 打包 OTP VM + 应用(_build/prod/rel/my_app)——目标机零依赖启动 bin/my_app start;配合环境变量注入配置,升级可走热升级。
9. CI 集成与常见陷阱
9.1 GitHub Actions 流水线
- uses: erlef/setup-beam@v1
with: { otp-version: "26", elixir-version: "1.16" }
- run: mix deps.get
- run: mix format --check-formatted
- run: mix compile --warnings-as-errors
- run: mix test
- run: mix credo --strict
9.2 常见陷阱
✗ 忘提交 mix.lock → 依赖不一致
✗ 测试连外部服务 → 用 :meck / Ecto sandbox
✗ 生产配置硬编码密钥 → 必须环境变量
✗ 发布忘了 config_env → prod 配置不生效
✗ CI 里直接 mix deps.get(无锁文件)→ 用 mix.lock
记忆:CI 流水线 = setup-beam + deps.get + format/compile –warnings-as-errors + test + credo;陷阱——mix.lock 入库、测试隔离外部服务、密钥环境变量注入、发布按 config_env 加载生产配置。
10. 速查表与一句话记忆
| 场景 | 命令/做法 |
|---|---|
| 脚手架 | mix new –sup |
| 依赖 | mix deps.get + mix.lock |
| 编译 | mix compile / –force |
| 测试 | mix test / –cover |
| 规范 | mix format / credo |
| 类型 | mix dialyzer |
| 发布 | MIX_ENV=prod mix release |
| 启动 | bin/my_app start |
| 自定义 | use Mix.Task |
一句话记忆:Mix 工程化 = 一站式工具链(mix new 脚手架、mix deps 依赖管理走 Hex + mix.lock 锁定、mix compile 增量编译、mix test + format + credo + dialyzer 质量四件套、mix release 打包 OTP VM 零依赖发布);配置分层 config.exs + config_env().exs、生产密钥环境变量注入;自定义任务 use Mix.Task 标准化脚本;CI 用 setup-beam + deps.get + format/compile –warnings-as-errors + test + credo 全部门禁——构建出的应用是 OTP 应用,与 Erlang 热升级/监控生态无缝衔接。"
延伸阅读
- /elixir-intro-phoenix/ — Elixir/Phoenix 基础
- /elixir-testing-property/ — 测试方法论
- /erlang-hot-code-upgrade/ — OTP release 与热升级
- /erlang-otp-framework/ — OTP 应用结构
- /erlang-production-cases/ — 生产实践案例
- [[devops]] — 部署运维与 CI/CD
- [[tools]] — 开发工具链
- Mix 官方文档
- Hex 包管理文档
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。