Setup

As with React, Mithril does not come with a built-in toolchain, so we will have to construct our own. However, as Mithril is very similar to React, we will be able to re-use much of what we did there. First create a new directory week12 and in that run

$ yarn init -y

Then install all the required dependencies:

$ yarn add @babel/core @babel/preset-env @babel/plugin-transform-react-jsx babel-loader css-loader bootstrap webpack html-webpack-plugin node-sass sass-loader style-loader webpack-cli webpack-dev-server mithril

Next, copy the webpack.conf.js from week11 into the week12 directory and then update the entry and babel-loader presets so that they look like this:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    devServer: {
        historyApiFallback: true,
        static: {
           directory: path.resolve(__dirname, '/dist')
        },
        open: false
    },
    entry: {
        main: path.resolve(__dirname, './src/js/index.js')
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: '[name].js',
        libraryTarget: 'var',
        library: 'Athena',
    },
    module: {
        rules: [
            {
                test: /\.m?jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },{
                test: /\.scss$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sassOptions: {
                                includePaths: [path.resolve(__dirname, 'node_modules')]
                            }
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Athena',
            filename: path.resolve(__dirname, './dist/index.html'),
            template: path.resolve(__dirname, './src/index.html'),
            inject: false,
            xhtml: true
        })
    ],
    optimization: {
        splitChunks: {
            chunks: "all",
            cacheGroups: {
                commons: {
                    test: /node_modules/,
                    name: "athena-vendor",
                    chunks: "initial",
                    minSize: 1,
                },
            },
        },
    },
}

Next, we need to create a .babelrc file to setup the presets, babel plugins and Mithril:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        ["@babel/plugin-transform-react-jsx", {
            // pragma overwrites default 'React.Fragment'
            // we need both entries since Mithril uses both
            "pragma": "m",
            "pragmaFrag": "'['"
        }]
    ]
}

It is mandatory to use this file since Mithril will throw an error otherwise. The change in webpack.conf.js is needed as with Mithril we will use a separate file that provides the main loading and routing functionality (unlike in the React solution, where everything was in the athena.jsx). Note that we use @babel/plugin-transform-react-jsx to implement the transformation of the JSX representation into the pure JavaScript version for the browser. Mithril can also use JSX (and we will), but where in React the JSX is translated to nested React.createElement calls, in Mithril, the function call is just called mithril. We thus use the pragma setting in the configuration to tell the @babel/plugin-transform-react-jsx to convert the JSX into nested mithril calls.

Now create a directory src and into that copy the styles directory from week11, as we can simply re-use that.

With that in place, we can now move on to building the actual application.