How to regenerate priv/static directory? instead remove it manually

I use fontawesome on Phoenix with css like below. (webpack.config.js)
It works finely.

module: {
 rules: [
  ...
  {
        test: /\.ttf|woff2?|eot|svg$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: '../fonts',
            esModule: false,
          }
        }
      }
 ]
}

Then I changed outputPath …/fonts to …/webfonts, it also works.
But /priv/static directory has both of them, fonts and webfonts.
I want to regenerate /priv/static automatically, not remove it manually.

Is there a good way to do it?

You would have to delete it manually. Since you might have multiple entities (depending on your setup and deployment strategy) output things to priv/static you wouldn’t want any of them to delete what the other put there.

As most of the static assets are generated anyway, they shouldn’t be tracked by your version control.

You should be able to do a git clean -Xn followed by a run without n or use i instead of n to get prompted for every file.

Be careful with that command though if you have ignored helper scripts in your repository.

1 Like

Thanks for your advice, @sfusato and @NobbZ.

As most of the static assets are generated anyway, they shouldn’t be tracked by your version control.

Yes, I think so too. So I want to regenerate it when I change my assets.
I reconsider the way, and now I decide to use below settings of dev.exs.

config :my_app, MyAppWeb.Endpoint,
  ...
  watchers: [
    rm: [ # add this.
      "-r",
      "priv/static",
      cd: Path.expand("..", __DIR__)
    ],
    node: [
      "node_modules/webpack/bin/webpack.js",
      "--mode",
      "development",
      "--watch-stdin",
      cd: Path.expand("../assets", __DIR__)
    ]
  ]

A different approach that I’ve used in the past is to setup the deletion at the webpack config level. This has the benefit of correctly generating the assets folder even if executed from outside of the Phoenix watcher.

Maybe https://github.com/johnagan/clean-webpack-plugin would work for this

2 Likes

Thank you, @sb8244.
I like your approach than mine. All settings in the webpack.config.js, nice!

So I take it, below, it works finely. Thank you!

const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = (env, options) => ({
  optimization: {
    minimizer: [
      new TerserPlugin({ cache: true, parallel: true, sourceMap: false }),
      new OptimizeCSSAssetsPlugin({})
    ]
  },
  entry: {
    './js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
  },
  output: {
    filename: './js/app.js',
    path: path.resolve(__dirname, '../priv/static')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.s?css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      },
      {
        test: /\.ttf|woff2?|eot|svg$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: './webfonts',
            esModule: false,
          }
        }
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ filename: './css/app.css' }),
    new CopyWebpackPlugin([{ from: 'static/', to: './' }]),
    new CleanWebpackPlugin({
      dry: false, verbose: true,
      cleanStaleWebpackAssets: false,
      protectWebpackAssets: true,
      cleanOnceBeforeBuildPatterns: ["**/*"]})
  ]
});
1 Like