I’ve never being a fan of keeping backend and frontend codebase together, though some of the well known project achieve it quiet well like Discourse.
Keeping JavaScript aside for backend solutions, as part of standalone UI elements seemed as decent solution. But when you have to develop Vue components as plugins and keep the project running - testing becomes messy.
I spent half a day trying to figure out the ways how you can use symlinks to pick local packages to work in dummy VueJS app, but no luck. Both for yarn
and npm
. There’ve been a long story of resolving these issues for numerous packages like here, or here.
Simple solution with mocking an App behaviour with a sprinkle of chokidar
package solves this problem. Well, at least to some extend:
- You can independently develop Vue Components as plugins
- From the box testing
- Once e2e and unit tests are done, you can publish and integrate these plugins in to your application.
Hot Reload for Development environment
First things first - tools being used:
vue
: 2.9.6node
: v10.16.0 (LTS)yarn|npm
: whatever make you happy!webpack-dev-server
: ^3.7.2
Build instructions are split in 3 parts (base, dev, prod). I’m using webpack-merge
to overwrite base with required instructions, depending on the yarn command:
//package.json part with live reload instructions
"scripts": {
"serve": "webpack-dev-server --config ./build/webpack.dev.config.js --hot --progress -d",
"test": "jest"
}
Going further - HRM specs, to make things run:
const merge = require('webpack-merge')
const chokidar = require('chokidar')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const base = require('./webpack.base.config.js')
module.exports = merge(base, {
entry: './dev/dev.js',
plugins: [
new HtmlWebpackPlugin({
template: './dev/index.html',
inject: true,
}),
],
optimization: {
noEmitOnErrors: true,
},
mode: 'development',
devtool: '#eval-source-map',
devServer: {
hot: true,
hotOnly: true,
open: true,
inline: true,
stats: {
children: false,
modules: false,
chunks: false,
},
port: 8080,
before (app, server) {
chokidar.watch([
'./**/*.html',
]).on('all', function () {
server.sockWrite(server.sockets, 'content-changed');
})
},
}
})
Whenever we run yarn serve
script, it will load a node server, and open a ./dev/index.html
file template which solely has a <div id="app"></div>
container.
Example of Dev structure
Now we simply add a wrapper component Dev.vue
that will contain whatever we want to test:
//dev.js
import Vue from 'vue'
import Dev from './Dev.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(Dev)
}).$mount("#app")
Let’s say we have a simple Calendar.vue
component we need to load when running serve
script:
<template>
<div id="app">
<Calendar/>
</div>
</template>
<script>
import Calendar from '@/components/Calendar.vue'
export default {
components: {
Calendar
}
}
</script>