Is there a way to reduce mix phx.server output?

Every time I run mix phx.server, I get:

[info] Running HelloWeb.Endpoint with cowboy 2.8.0 at 0.0.0.0:4000 (http)
[info] Access HelloWeb.Endpoint at http://localhost:4000

webpack is watching the files…

[hardsource:86c17673] Using 1 MB of disk space.
[hardsource:86c17673] Tracking node dependencies with: package-lock.json.
[hardsource:86c17673] Reading from cache 86c17673...
Hash: 97fd47bb7gfde75674c1
Version: webpack 4.41.5
Time: 174ms
Built at: 2021-02-05 2:42:46 p.m.
                Asset       Size  Chunks             Chunk Names
       ../css/app.css   10.7 KiB     app  [emitted]  app
       ../favicon.ico   1.23 KiB          [emitted]
../images/phoenix.png   13.6 KiB          [emitted]
        ../robots.txt  202 bytes          [emitted]
               app.js   13.5 KiB     app  [emitted]  app
Entrypoint app = ../css/app.css app.js
[0] multi ./js/app.js 28 bytes {app} [built]
    + 5 hidden modules

Any way to control the output of this command?

Like in the docs:

$ mix phx.server
[info] Running HelloWeb.Endpoint with cowboy 2.5.0 at http://localhost:4000

Webpack is watching the files…
...
2 Likes

Which part you want to get rid of? Elixir logging can be controlled via setting appropriate level and for Webpack messages you need to check Webpack documentation.

2 Likes

try snowpack. It’s output is much more civil:

> @ watch /home/derek/projects/roastidious/assets
> snowpack build --watch

[snowpack] ! building source files...
[snowpack] ✔ build complete [2.83s]
[snowpack] ! installing dependencies...
[snowpack] ✔ install complete! [2.16s]
[snowpack] ! verifying build...
[snowpack] ✔ verification complete [0.00s]
[snowpack] ! writing build to disk...
[snowpack] Watching for changes...
...
[snowpack] File changed...
[debug] Live reload: priv/static/js/app.js
2 Likes

Is there a good guide on switching from webpack to snowpack in Phoenix projects?

It is very simple. Just install snowpack using the npm, than make a small snowpack.config.js:

module.exports = {
    mount: {
        "static": {url: "/", static: true, resolve: false},
        "css": "/css",
        "js": "/js"
    },
    plugins: [
        "@snowpack/plugin-postcss"
    ],
    buildOptions: {
        out: "../priv/static"
    },
};

then hook up snowpack into the flow. My way is chaning the package.json to:

...
  "scripts": {
    "deploy": "snowpack build",
    "watch": "snowpack build --watch"
  },
...

then in your dev.exs:

...
  watchers: [
    npm: [
      "run",
      "watch",
      cd: Path.expand("../assets", __DIR__)
    ]
...

In your template, make sure your js file is included with type=“module”, such as:

<script defer type="module" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>

The thing I like the most about snowpack is it does not bundle. All js files are loose, so it is much more easier to debug in the browser dev tool.

4 Likes

Silly me imagined for some reason Phoenix had some flags for this.

Updated my webpack.config.js and now works as expected:

Final result

❯ mix phx.server
[info] Running HelloWeb.Endpoint with cowboy 2.8.0 at 0.0.0.0:4000 (http)
[info] Access HelloWeb.Endpoint at http://localhost:4000

webpack is watching the files…

webpack.config.js

❯ cat assets/webpack.config.js
const path = require('path');
const glob = require('glob');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
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');

module.exports = (env, options) => {

  const devMode = options.mode !== 'production';

  return {
    stats: 'minimal',  #<-------Add kv------->
    optimization: {
      minimizer: [
        new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
        new OptimizeCSSAssetsPlugin({})
      ]
    },
    entry: {
      'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
    },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, '../priv/static/js'),
      publicPath: '/js/'
    },
    devtool: devMode ? 'eval-cheap-module-source-map' : undefined,
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader'
          }
        },
        {
          test: /\.[s]?css$/,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            'sass-loader',
          ],
        }
      ]
    },
    plugins: [
      new MiniCssExtractPlugin({ filename: '../css/app.css' }),
      new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
    ]
    .concat(devMode ? [new HardSourceWebpackPlugin({
      #<-------Add obj------->
      info: {
        level: 'warn'
      }  
    })] : [])
  }
};
2 Likes

There is also vite that is competing in this space but js FaTiGuE. Much rather configure stock phoenix than go back down that rabbit hole

1 Like

JS fatigue is very real for everyone who’s not a JS dev – but has to deal with the frontend somewhat.

I’m glad that the JS community is working on improving the ecosystem but their expectations that everybody else should just keep up with what’s used nowadays is unrealistic.

To make things worse, they don’t give a single thought to backwards compatibility and transferable knowledge.

4 Likes

I understand. My knowledge about js tooling is even less then elixir; so my top priority for the js tooling is stay out of my way. Sadly, webpack failed this criteria for me.

2 Likes

I fully agree; and that’s why we need to be extra diligent in choosing a technology; not just go blindly with the status quo.

1 Like