Phoenix 1.4 with Vue on Raspberry Pi
I would like to control Raspberry Pi through web interface. It is a common feature of connected electronic devices. Some are written in PHP, e.g. raspi-webgui. Phoenix and Vue would be a good pair. The idea is that Phoenix can control the hardware and process through GenServer while serving Vue through web interface. Users can use mobile phones or computers to control Raspberry Pi with nice Vue user interface and through Phoenix.
An article shows how to set up Vue with Phoenix 1.3. Since Phoenix 1.4 is coming out and use webpack by default, it might be a good choice to start.
To install Phoenix 1.4 and replace old one
mix archive.uninstall phx_new
mix archive.install hex phx_new 1.4.0-rc.2
Create new project
mix phx.new phx_vue
cd phx_vue
Adjust database setting in config/dev.exs and create database
mix ecto.create
Start phoenix and see the result by connecting to it, probably at 0.0.0.0:4000
iex -S mix phx.server
Now, move into ./assets and you can find installed packages in package.json.
Add vue
yarn add vue
Then add common loaders for development
yarn add -D vue-template-compiler vue-loader css-loader vue-style-loader
Create ./assets/src/components directory to put vue files. Here is an example taken from this article.
// assets/src/main.js
import Vue from 'vue'
import App from './App'Vue.config.productionTip = falseconst element = document.getElementById('app')
const app = new Vue(App).$mount(element)// assets/src/App.vue
<template>
<div id="app">
<header>
<h1>Phoenix Vue</h1>
</header>
<main>
<hello></hello>
</main>
</div>
</template><script>
import Hello from './components/Hello'
export default {
name: 'app',
components: {
Hello
}
}
</script><style>
main {
margin-top: 60px;
}
</style>// assets/src/components/Hello.vue
<template>
<div class="hello">
<h3>Hello from Vue.js!</h3>
<p>{{msg}}</p>
</div>
</template><script>
export default {
name: 'hello',
data() {
return {
msg: 'Simple example using Phoenix, Vue and Webpack.'
}
}
}
</script><style scoped>
p {
margin-top: 40px;
}
</style>
Add <div id="app"></div>
in lib/phx_vue_web/templates/page/index.html.eex
The most important part is assets/webpack.config.js. I am not an expert in webpack, thus, this is a result of trial-and-error.
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 { VueLoaderPlugin } = require('vue-loader')module.exports = (env, options) => ({
mode: 'development',
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({})
]
},
entry: {
app: './src/main.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../priv/static/js')
},
resolve: {
extensions: ['.js', '.vue', '.css']
},
module: {
rules: [
{
// vue-loader config to load `.vue` files or single file components.
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: ['vue-style-loader', {
loader: 'css-loader',
}],
js: [
'babel-loader',
],
},
cacheBusting: true,
},
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
new VueLoaderPlugin()
]
});
Most are default settings. Pay attention to the new entry and output. Resolv and module for Vue are also added. VueLoaderPlugin is essential.
After that, you can follow this article to hook up GenServer with Phoenix.