Mix
Mix is Elixir’s build tool that provides project scaffolding, dependency management, compilation, testing, and deployment capabilities.
Installation
# Install Erlang and Elixir
# macOS with Homebrew
brew install erlang elixir
# Ubuntu/Debian
sudo apt-get install erlang elixir
# Verify installation
mix --version
elixir --version
Creating Projects
New Project
# Create new Mix project
mix new my_app
# Create umbrella project (monorepo)
mix new --umbrella my_umbrella
# Create with supervisor
mix new my_app --sup
# Check project structure
tree my_app
Project Structure
my_app/
├── _build/ (Compiled output)
├── lib/ (Application code)
│ └── my_app.ex
├── test/ (Tests)
│ └── my_app_test.exs
├── mix.exs (Project manifest)
├── mix.lock (Dependency lock file)
└── README.md
Project Configuration
mix.exs
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :my_app,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
extra_applications: [:logger],
mod: {MyApp.Application, []}
]
end
defp deps do
[
{:plug_cowboy, "~> 2.6"},
{:ecto_sql, "~> 3.10"},
{:postgrex, ">= 0.0.0"},
{:jason, "~> 1.2"},
{:ex_doc, "~> 0.30", only: :dev, runtime: false},
{:dialyxir, "~> 1.4", only: :dev, runtime: false}
]
end
end
Essential Commands
| Command | Description |
|---|---|
mix compile | Compile project |
mix deps.get | Install dependencies |
mix deps.update | Update dependencies |
mix test | Run tests |
mix run | Execute project |
mix ecto.setup | Setup database |
mix format | Format code |
mix credo | Lint code |
Dependency Management
# Get dependencies
mix deps.get
# Update dependencies
mix deps.update
# Update specific dependency
mix deps.update plug_cowboy
# Remove dependency
# Edit mix.exs and run mix deps.clean
# Show dependency tree
mix deps.tree
# Check if dependencies are available
mix deps
Building & Compilation
# Compile project
mix compile
# Compile with warnings as errors
mix compile --warnings-as-errors
# Clean compiled output
mix clean
# Recompile everything
mix clean && mix compile
# Run with interactive shell
iex -S mix
# Run specific module
mix run -e "MyApp.main()"
Testing
Running Tests
# Run all tests
mix test
# Run tests for specific file
mix test test/my_app_test.exs
# Run specific test
mix test test/my_app_test.exs:12
# Run with coverage
mix test --cover
# Run tests matching pattern
mix test --only integration
# Verbose output
mix test --verbose
Test Structure
defmodule MyAppTest do
use ExUnit.Case
doctest MyApp
setup do
# Setup code
:ok
end
test "greets the world" do
assert MyApp.hello() == :world
end
@tag :integration
test "integration test" do
# Integration test
assert true
end
end
Database Management
Ecto Setup
# Create database
mix ecto.create
# Run migrations
mix ecto.migrate
# Rollback migrations
mix ecto.rollback
# Reset database
mix ecto.drop && mix ecto.create && mix ecto.migrate
# Generate migration
mix ecto.gen.migration add_users_table
# Check migration status
mix ecto.migrations
migration example
defmodule MyApp.Repo.Migrations.CreateUsers do
use Ecto.Migration
def change do
create table(:users) do
add :email, :string, null: false
add :name, :string
timestamps()
end
create unique_index(:users, [:email])
end
end
Phoenix Framework
Create Phoenix Project
# Install Phoenix generator
mix archive.install hex phx_new
# Create Phoenix project
mix phx.new my_app
cd my_app
# Install dependencies
mix deps.get
# Setup database
mix ecto.setup
# Start server
mix phx.server
Phoenix Generators
# Generate context
mix phx.gen.context Accounts User users email:string password:string
# Generate schema
mix phx.gen.schema User users email:string name:string
# Generate controller
mix phx.gen.html Post posts title:string content:text
# Generate embedded schema
mix phx.gen.embedded Address street:string city:string
Code Quality Tools
Formatting
# Format all code
mix format
# Check if formatted
mix format --check-formatted
# Format specific file
mix format lib/my_app.ex
Linting with Credo
# Install credo
# Add to mix.exs:
# {:credo, "~> 1.7", only: [:dev, :test], runtime: false}
# Run linting
mix credo
# Run with strict mode
mix credo --strict
# Show help
mix credo --help
Type Checking with Dialyzer
# Install dialyxir
# {:dialyxir, "~> 1.4", only: [:dev], runtime: false}
# Run dialyzer
mix dialyzer
# Build PLT (first time)
mix dialyzer --plt
Release & Deployment
Building Releases
# Create release configuration
mix release.init
# Build release
mix release
# Build release for production
MIX_ENV=prod mix release
# Run release
_build/prod/rel/my_app/bin/my_app start
# Console access
_build/prod/rel/my_app/bin/my_app remote
release.exs Configuration
import Config
config :my_app, MyApp.Repo,
username: System.get_env("DB_USER") || "postgres",
password: System.get_env("DB_PASSWORD") || "",
database: System.get_env("DB_NAME") || "my_app_prod",
hostname: System.get_env("DB_HOST") || "localhost"
Environment Configuration
# Run in development (default)
mix test
# Run in production
MIX_ENV=prod mix test
# Run in test
MIX_ENV=test mix test
# Environment variable
export MIX_ENV=prod
mix compile
Troubleshooting
# Clear all build artifacts
mix clean --deps
# Reinstall dependencies
rm mix.lock
mix deps.get
# Recompile with verbose output
mix compile --verbose
# Check Elixir/OTP versions
elixir --version
# Update mix itself
mix local.hex --force
Best Practices
- Use semantic versioning for projects
- Keep dependencies updated regularly
- Use guards and pattern matching
- Write property-based tests with ExCheck
- Document public API with @doc
- Use Credo for code quality
- Use Dialyzer for type checking
- Keep mix.lock in version control
Resources
Last updated: 2025-07-06|Edit on GitHub