Mind Dump, Tech And Life Blog
written by Ivan Alenko
published under license Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)copy! share!
posted in category Systems Software / Phoenix (Elixir)
posted at 10. Jul '19

Two CSS and JS files for Webpack 4 and Phoenix 1.4

I post this here, because in retrospective I’m a bit ashamed it took so long and it’s so trivial.

Basically I started with vanilla Phoenix 1.4 web app and default Webpack configuration creates only one app.js file. But I want to have app.js for front facing web and admin.js for admin section. Just to separate CSS rules (normalizers in CSS frameworks are global) and admin-specific Javascript initialization code.

We need to change entry section and set names (used in [name] variable later by Webpack) and set the output and plugins section.

  • change ./js/app.js to only app, add admin - otherwise it will put files into subdirectories and names will be like /js/js/app.js.js and /css/js/app.js.css
  • change output - apparently you cannot output just two files, but there is a wildcard [name]
  • change rules
  • change plugins
  • you don’t have to have SCSS loader to use @import statements in .css files (see the example). Just don’t put them at the top, because they wil be copied verbatim for some reason. You can import files from node_modules directory.

/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: {
      'app': ['./js/app.js'].concat(glob.sync('./vendor/**/*.js')),
      'admin': ['./js/admin.js']
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, '../priv/static/js')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /admin\/.+\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /app\/.+\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ filename: '../css/[name].css' }),
    new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
  ]
});

/assets/js/app.js

// We need to import the CSS so that webpack will load it.
// The MiniCssExtractPlugin is used to separate it out into
// its own CSS file.
import css from "../css/app/app.css"

// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
// in "webpack.config.js".
//
// Import dependencies
//
import "phoenix_html"

// Import local files
//
// Local files can be imported directly using relative paths, for example:
// import socket from "./socket"

/assets/js/admin.js

import css from "../css/admin/admin.css"

/assets/css/app/app.css

~~~css /* This file is for your main application css. */ html, body { font-size: 14px; }

.flex { display: flex; }

.flex-item { flex: 1; }

@import “../../node_modules/normalize.css/normalize.css”; @import “home_page.css”; ~~~`

Add Comment