Thanks to the original blog post: https://equimper.com/blog/how-to-setup-tailwindcss-in-phoenix-1.4
cd assets
npm i --save-dev tailwindcss postcss-loader postcss-import
npx tailwind init
module.exports = {
plugins: [
require('postcss-import')(),
require('tailwindcss')('./tailwind.config.js'),
require('autoprefixer'),
],
};
// assets/webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env, options) => ({
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({}),
],
},
entry: {
'./js/app.js': ['./js/app.js'].concat(glob.sync('./vendor/**/*.js')),
},
output: {
filename: 'app.js',
path: path.resolve(__dirname, '../priv/static/js'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader']
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
],
});
/** assets/css/app.css */
/**
* This injects Tailwind's base styles, which is a combination of
* Normalize.css and some additional base styles.
*
* If using `postcss-import`, use this import instead:
*
* @import "tailwindcss/base";
*/
@tailwind base;
/**
* This injects any component classes registered by plugins.
*
* If using `postcss-import`, use this import instead:
*
* @import "tailwindcss/components";
*/
@tailwind components;
/**
* Here you would add any of your custom component classes; stuff that you'd
* want loaded *before* the utilities so that the utilities could still
* override them.
*
* Example:
*
* .btn { ... }
* .form-input { ... }
*
* Or if using a preprocessor or `postcss-import`:
*
* @import "components/buttons";
* @import "components/forms";
*/
/**
* This injects all of Tailwind's utility classes, generated based on your
* config file.
*
* If using `postcss-import`, use this import instead:
*
* @import "tailwindcss/utilities";
*/
@tailwind utilities;
/**
* Here you would add any custom utilities you need that don't come out of the
* box with Tailwind.
*
* Example :
*
* .bg-pattern-graph-paper { ... }
* .skew-45 { ... }
*
* Or if using a preprocessor or `postcss-import`:
*
* @import "utilities/background-patterns";
* @import "utilities/skew-transforms";
*/
With PurgeCSS you can reduce your CSS asset from approx ~300KB to under 10KB. This will improve the performance of your site.
cd assets
npm i -D purgecss-webpack-plugin glob-all
Then in your webpack.config.js
// assets/webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
+ const PurgecssPlugin = require('purgecss-webpack-plugin');
+ const globAll = require('glob-all');
+ // Custom PurgeCSS extractor for Tailwind that allows special characters in
+ // class names.
+ // Regex explanation: https://tailwindcss.com/docs/controlling-file-size/#understanding-the-regex
+ const TailwindExtractor = content => {
+ return content.match(/[\w-/:]+(?<!:)/g) || [];
+ };
module.exports = (env, options) => ({
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({}),
+ new PurgecssPlugin({
+ paths: globAll.sync([
+ '../lib/<APP_NAME>_web/templates/**/*.html.eex',
+ '../lib/<APP_NAME>_web/views/**/*.ex',
+ '../assets/js/**/*.js',
+ ]),
+ extractors: [
+ {
+ extractor: TailwindExtractor,
+ extensions: ['html', 'js', 'eex', 'ex'],
+ },
+ ],
+ }),
],
},
entry: {
'./js/app.js': ['./js/app.js'].concat(glob.sync('./vendor/**/*.js')),
},
output: {
filename: 'app.js',
path: path.resolve(__dirname, '../priv/static/js'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
],
});
Note: PurgeCSS will remove css classes you wrote to style HTML that comes from outside your code base (like a hex package, i.e pagination library). In those cases explicitly tell PurgeCSS to not remove them with:
/* purgecss start ignore */
.pagination-class-in-your-css-file {
background-color: #fff;
}
/* purgecss end ignore */