When starting Keestash back in late 2018, I was focused on the PHP backend and how things might work “out of the box”. The frontend needed just some click handlers here and there and thus, jQuery was the choice.
Now, about two years later, things have changed a bit. The frontend got a boost with Bootstrap, Webpack, a package manager (NPM). The overall code is splitted up into the core and several apps. Handling software in this way requires a key module (Keestash Core) and the app modules. And as you can imagine, jQuery is not the first choice for that kind of software architecture.
Further, the frontend JavaScript (not limited to jQuery) code has grown and grown. While seeing how Keestash get’s improved makes me happy, however, on the other hand, jQuery is a real thorn in the eye. This blog accompanies the attempt to integrate a new JavaScript framework into the existing ecosystem: Vue.Js.
Vue.Js should be introduced to Keestash without breaking existing functionality (without reinventing the wheel). I am aware of that many things described below will not be perfect. The aim is to introduce Vue.Js without breaking things and enabling a modular migration while extending and developing Keestash.
Modular Keestash: Apps
I believe in modular code structures and am firmly convinced that monolithic software structures will get unmaintainable. Therefore, I structured key components of Keestash as modular parts of source code, called apps.
The central app in Keestash is the password_manager. A lot of PHP and jQuery code is here and disqualifies the app for being a frontend jQuery-Vue.Js migration candidate. Instead, I will keep this as it is and migrate another smaller app: installation.
The installation process is splitted up into two apps: install_instance and install where the former installs the whole instance whereas the latter cares about the apps. As you can imagine, the installation process takes mainly place in the backend and has a small frontend part which makes both apps a perfect candidate to migrate to Vue.Js.
Keestash Installation Process
Keestash asks for several input data in order to install databases, checks file and directory permissions as well as for missing files or directories. If missing or incomplete, a simple web UI asks for the input or points to the files/directories and provides a button to check again.
App installation is done by a similar way: Keestash checks installable app candidates and shows them to the user. When clicking on the install button, all apps in the background get installed. So far, this was a task for jQuery.
App Webpack Config
As I stated before, we are using Webpack for module bundling in Keestash. Since source code is – mostly – organized as apps, we can simply create a webpack config for each app. This decouples the code from the core, enables a modular structure for which we are looking for and lets us define app specific requirements.
Each webpack configuration is merged into a “global” configuration. The global config contains default properties, such as the (config) modules defined, the “resolve” option which defines how modules are defined as well as the mode (NODE_ENV).
The global webpack defines also rules that assert module files (such as files with vue, scss, etc. extensions). Because we are still using jQuery (unfortunately) next to Vue.Js, we need to consider module rules for both. Further, we need a loader for scss/sass and exclude code from node_modules:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | module: { rules: [ { exclude: /node_modules/, loader: 'babel-loader', }, { test: /\.js$/, loader: 'babel-loader' }, { test: /\.vue$/, exclude: /node_modules/, loader: ['vue-loader'] }, { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', }, ], }, ] }, |
The global webpack configuration is merged with all app configs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | const appModules = glob.sync("./apps/*/js/webpack.config.js"); .... const webpackConfig = [].concat( baseModule , toConfig(appModules, baseModule) ); function toConfig(modules, baseModule) { let conf = []; for (let i = 0; i < modules.length; i++) { const configPath = modules[i]; const config = require(configPath); config.mode = baseModule.mode; config.node = {fs: 'empty'}; config.module = Object.assign(baseModule.module, config.module || {}); config.resolve = Object.assign(baseModule.resolve, config.resolve || {}); conf.push(config); } return conf; } module.exports = webpackConfig; |
Notice that this approach is not optimal. There are other ways to for webpack merge, but this approach is acceptable for Keestash (so far).
Vue.Js integration
Vue.Js needs an div container to mount it’s virtual DOM. Further, before mounting, we need to provide plugins and – if we want use Vuex – configure the store1. The created Vue instance get’s an component injected that denotes the entry point to the app. We call this the “bootstrapping process”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import App from "./InstallInstance/App"; import BootstrapVue from "bootstrap-vue"; import Vue from 'vue'; import store from "../../../../lib/js/src/Store/store"; window.addEventListener( 'DOMContentLoaded' , bootstrap ); function bootstrap() { const vueConfig = { store, render: h => h(App) }; Vue.use(BootstrapVue); new Vue(vueConfig) .$mount("#install_instance_app"); } |
The bootstrapping is very simple and self-explanatory. Once the DOM is loaded, the bootstrap function is called which configures our Vue instance, tells it to use BootstrapVue-Plugin as well as the div container id to mount.
Further Work
Keestash Installation can now get implemented in Vue.Js in the frontend. The webpack config enables this for the install_instance app and all other apps. The bootstrapping has to be done for each app seperatelly, but however, Vue.Js enables us to think in components, allows us to reuse it and has overall a better and more modern development approach.
There is a lot of thing to do with Keestash and Keestash apps. And we are also open for new ideas and contributors. If you are interested in developing and extending Keestash, just write me an email or open a PR on GitHub.