Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/ex_postcss.

ExPostcss

Mix tasks for installing and invoking postcss.

Installation

If you are going to build assets in production, then you add ex_postcss as a dependency on all environments but only start it in dev:

def deps do
[
{:ex_postcss, "~> 0.1", runtime: Mix.env() == :dev}
]
end

However, if your assets are precompiled during development, then it only needs to be a dev dependency:

def deps do
[
{:ex_postcss, "~> 0.4", only: :dev}
]
end

Adding to Phoenix

You must install postcss-cli by running:

npm i -D postcss postcss-cli

You may also want to install additional plugins for the postcss environment like autoprefixer, postcss-preset-env, and cssnano

cd assets
npm -i -D autoprefixer postcss-preset-env

Next we will add a configuration file for postcss and place it in our assets directory.

touch assets/postcss.config.js

Here's a sample configuration using autoprefixer, postcss-preset-default, and cssnano.

module.exports = (ctx) => ({
plugins: [
require("autoprefixer"),
require("postcss-preset-env")({
stage: 3,
browsers: [
"> 0.5% in US",
"not IE 11",
"not dead"
]
}),
require("cssnano")({
preset: [
"default",
{
discardComments: { removeAll: true }
}
]
})
]
})

Profiles

The first argument to ex_postcss is the execution profile. You can define multiple execution profiles with the current directory, the OS environment, and default arguments to the postcss task:

config :ex_postcss,
default: [
args: ~w(css/app.scss -o ../priv/static/assets/app.css --config ./postcss.config.js),
cd: Path.expand("../assets", __DIR__)
]

Note You must pass in the path to the configuration file for postcss to pick up your plugins.

You can now invoke postcss with:

$ mix postcss default --no-map

When mix postcss default is invoked, the task arguments will be appended to the ones configured above.

Watching for changes in development

Add the following configuration to your config/dev.exs file within the watchers section.

postcss: {ExPostcss, :run, [:default, ~w(--watch)]}

Usage with DartSass

We can combine ex_postcss with DartSass by having dart sass compile to a file in a temporary directory. Postcss can then watch that file and output its contents to the /priv/static directory.

config :dart_sass,
version: "1.49.9",
default: [
args: ~w(css/app.scss ../priv/temp/assets/app.css --load-path=assets/node_modules/),
cd: Path.expand("../assets", __DIR__)
]
config :ex_postcss,
default: [
args: ~w(../priv/temp/assets/app.css -o ../priv/static/assets/app.css --config ./postcss.config.js),
cd: Path.expand("../assets", __DIR__)
]

We should ignore this directory in our .gitconfig file.

# Ignore assets that are produced by build tools.
/priv/temp/
/priv/static/assets/

Note: if you are using esbuild (the default from Phoenix v1.6), make sure you remove the import "../css/app.css" line at the top of assets/js/app.js so esbuild stops generating css files.

Note: make sure the "assets" directory from priv/static is listed in the :only option for Plug.Static in your endpoint file at, for instance lib/my_app_web/endpoint.ex.

Finally, back in your mix.exs, make sure you have an assets.deploy alias for deployments:

"assets.deploy": [
"esbuild default --minify",
"postcss default",
"phx.digest"
]

Acknowledgements

This package is based on the excellent esbuild by Wojtek Mach and José Valim, and dart_sass by CargoSense, Inc.

License

Copyright (c) 2022 Thomas Cioppettini.

ex_postcss source code is licensed under the MIT License.