Vue.js & Nuxt.js WebSocket client plugin for QEWD.js
vue-qewd:This plugin integrates Vue.js & Nuxt.js applications with a multi-process qewd (QEWD.js) Express or Koa back-end server using WebSockets (or Ajax calls). Exposes the ewd-client module as a this.$qewd
built-in Vue.js service inside your Vue.js components.
A similar react-qewd module exists for React/Redux.
QEWD.js is a unique web framework allowing you to concentrate on your application code, without worrying about system infrastructure, featuring:
- a WebSockets server, allowing your application to connect via this
vue-qewd
module using ewd-client - a (federating) REST server, to build your REST endpoints & allowing you to federate requests to other (chained) QEWD servers, featuring Express or Koa as underlying frameworks
- a microservices server, using very efficient (permanent, secured) WebSocket connections to other QEWD.js servers using JWT's
- a GraphQL server to write & process your GraphQL queries & mutations
- an application router to orchestrate all your different application endpoint(s)/handler(s)
- a master/worker multi-process queue architecture, high-performance and very scalable
- session management/cache allowing you to write stateful applications
- response customization: combine responses from different servers, return responses in different formats, intercept an re-route requests, ...
- built-in JSON database abstraction: make your application data persistent using the InterSystems Caché multi-model database or the InterSystems IRIS Data platform (unified data access as a document/NoSQL store or using SQL or objects), Redis, YottaDB, ...
Installing
npm install vue-qewd
Version 2: breaking changes!
From version 2.0.0 onwards, the socket.io-client and jQuery module dependencies for the underlying ewd-client need to be passed in as parameters when instantiating QEWD:
import io from 'socket.io-client'
import $ from 'jquery'
let qewd = QEWD({
application: 'qewd-test-app', // application name
log: true,
url: 'http://localhost:8080',
io,
$
})
Overview of parameter changes in 2.0.0 and up:
io
was added: required for WebSocket communication mode, import it as above or as
var io = require('socket.io-client')
$
was added: required for Ajax communication mode using the jQuery ajax method, import it as above or as
var $ = require('jquery')
ajax
remains the same: required for Ajax communication mode, using you own custom Ajax module, e.g. with axios
import io from 'socket.io-client'
// import $ from 'jquery'
import axios from 'axios'
var qewd = QEWD({
application: 'qewd-test-app', // application name
log: true,
url: 'http://localhost:8080',
io,
ajax: function (params, success, fail) {
let data = JSON.stringify(params.data)
axios({
url: params.url,
method: 'post',
headers: {
'Content-Type': params.contentType
},
data,
timeout: params.timeout
})
.then(function (response) {
success(response.data)
})
.catch(function (error) {
if (error.response) {
success(error.response.data)
} else {
fail(error.message || 'unknown ajax error')
}
})
}
})
- for mixed WebSocket & Ajax communication mode, you need both parameters (io and $ || ajax)
no_sockets
parameter was removeduse_jquery
parameter was removed
This allows you to control which modules you need and avoids Webpack dependency detection issues.
Options
Options you can pass to the QEWD({ ... })
instance (see examples) with their default values and a short description:
{
// application module name
application: 'unknown',
// socket.io-client module (optional, required for WebSockets communication)
io: undefined,
// jquery module (optional, required for Ajax communication using jQuery's $.ajax)
$: undefined,
// specify your own Ajax request handler function, see example above (optional)
ajax: null,
// url of QEWD.js server, in the form 'http(s)://<host>:<port>'
url: null,
// runtime mode for ewd-client (optional)
mode: 'development',
// log each QEWD message sent & received on console (optional)
log: true,
// specify custom cookie name to restart the current WebSockets session between page refreshes (optional)
cookieName: 'ewdSession',
// use JWT's for sessions (optional)
jwt: false,
// decode JWT's in the client (optional)
jwt_decode: false
}
You'll find further details about these options in the QEWD.js training course.
Vue.js
Use withBelow is a small example using Vue.js components.
First, create a new startup app template with vue-cli (or with the most recent @vue/cli version 3.x). This example is just a modification of the standard app template code. If necessary, adjust the url
property inside the var qewd
to your local settings.
This module adds a $qewd
service to the Vue instance. You can then simply communicate with your back-end by invoking this.$qewd.send()
in your Vue component methods. Btw, you'll need to define a let self = this
to make the Vue component instance available in the send
callback because it's not proxied yet inside the callback.
While QEWD.js is starting the WebSocket connection with the back-end, you can also use conditional rendering to hide (parts of) the app view using this.$qewd.vRegistrationCallback(cb)
. See below, where the App component installs a callback function which QEWD calls when the WebSocket connection state changes. This sets the reactive qewdReady
data property and re-renders the view.
Press the "QEWD message test" button to see the plugin back-end communication in action.
import Vue from 'vue'
import App from './App.vue'
import io from 'socket.io-client'
// import both the QEWD class and VueQEWD plugin
import { QEWD, VueQEWD } from 'vue-qewd'
// import axios (optional, in case you need to use ajax mode)
import axios from 'axios'
// instantiate QEWD with your parameters
var qewd = QEWD({
application: 'qewd-test', // application name
log: true,
url: 'http://localhost:8080', // adjust this to your local environment
io, // use WebSocket communication
// uncomment the lines below to use axios ajax calls instead of using WebSockets (and remove io parameter)
// see also part 14 of QEWD training course from page 15 at
// https://www.slideshare.net/robtweed/ewd-3-training-course-part-14-using-ajax-for-ewdxpress-messages
/*
ajax: function (params, success, fail) {
let data = JSON.stringify(params.data)
axios({
url: params.url,
method: 'post',
headers: {
'Content-Type': params.contentType
},
data,
timeout: params.timeout
})
.then(function (response) {
success(response.data)
})
.catch(function (error) {
if (error.response) {
success(error.response.data)
} else {
fail(error.message || 'unknown ajax error')
}
})
}
*/
});
// let Vue know you want to use the plugin
Vue.use(VueQEWD, { qewd });
// create your Vue instance
new Vue({
el: '#app',
render: h => h(App)
})
Next, create a default App.vue component:
<template>
<div id="app">
<template v-if="qewdReady">
<img src="./assets/logo.png">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
<li><a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
<li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
<li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
</ul>
<button @click="testing">QEWD message test</button>
</template>
<template v-else>
<img src="./assets/logo.png">
<h2>Starting application, please wait ...</h2>
</template>
</div>
</template>
<script>
export default {
name: 'app',
mounted: function() {
var self = this;
// monitor when QEWD is ready
this.$qewd.vRegistrationCallback(function(registered) {
self.qewdReady = registered; //
});
// start the QEWD WebSockets connection ...
this.$qewd.vueStart();
},
data () {
return {
qewdReady: false,
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
testing: function() {
let messageObj = {
type: 'test',
params: {
text: 'a Vue.js test message for QEWD'
}
};
let self = this;
this.$qewd.send(messageObj, function(messageObj) {
self.msg = messageObj.message.text;
});
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
Next, create a qewd-test.js
module in your QEWD back-end server with a test
handler returning a simple test message (see below).
module.exports = {
handlers: {
test: function(messageObj, session, send, finished) {
var incomingText = messageObj.params.text;
var d = new Date();
finished({text: 'You sent: ' + incomingText + ' at ' + d.toUTCString()});
}
}
};
Next, you'll need to install one dependency the QEWD client needs to build it's WebSockets connection to the QEWD.js server back-end:
npm i socket.io-client --save
Finally, run your Vue.js test app with:
npm run dev
Tip
: to avoid Webpack errors (requiring both socket.io-client
and jquery
to be installed), include the module(s) you need as (at least development) dependency in your Vue.js project, e.g.:
npm i socket.io-client
npm i -D jquery
Nuxt.js
Use withIf you want to build Vue.js apps using SSR (server-side rendering), you can use vue-qewd
inside a Nuxt.js
project (template). You need to define vue-qewd
first as a plugin for your Nuxt.js
project.
Create a vue-qewd.js
file inside your /plugins
directory:
import Vue from 'vue'
import io from 'socket.io-client'
// import both the QEWD class and VueQEWD plugin
import { QEWD, VueQEWD } from 'vue-qewd'
// instantiate QEWD with your parameters
var qewd = QEWD({
application: 'qewd-test', // application name
log: true,
// adjust this to your local environment
// using environment vars defined in nuxt.config.js
url: 'http://' + process.env.qewdHost + ':' + process.env.qewdPort,
io,
// use a custom cookie in the browser
cookieName: 'qwt'
});
// let Vue know you want to use the plugin
Vue.use(VueQEWD, { qewd })
Inside your nuxt.config.js
, add vue-qewd.js
to the plugins array, e.g.:
module.exports = {
env: {
qewdHost: process.env.QEWD_HOST || 'localhost',
qewdPort: process.env.QEWD_PORT || '8080'
},
server: {
port: 3000, // default: 3000
host: '0.0.0.0' // default: localhost
},
...
plugins: [
'~/plugins/vuetify.js',
'~/plugins/vue-qewd.js'
],
...
You can leverage QEWD.js
's cookie mechanism to reconnect the WebSocket session automatically between complete page refreshes in Nuxt.js
: it's recommended to launch the QEWD.js client from the mounted
hook in an Application layout file, e.g. inside /layouts/default.vue
you can add QEWD like this:
<template>
<v-app dark>
...
</v-app>
</template>
<script>
export default {
data () {
return {
qewdReady: false,
sessionExpired: false,
...
}
},
mounted: function () {
var self = this
// monitor when QEWD is ready
this.$qewd.vRegistrationCallback(function (registered, msgType) {
console.log('registration callback: ', registered, msgType)
self.qewdReady = registered
// preserve session across page refreshes & switches
if (registered) {
self.sessionExpired = false
if (msgType === 'ewd-registered') {
self.$qewd.setCookie('qwt')
}
} else {
if (msgType === 'socketDisconnected') {
self.sessionExpired = true
}
}
})
// start the QEWD WebSockets connection ...
this.$qewd.vueStart()
},
methods: {
...
}
}
</script>
Btw, this example uses the Vuetify framework to build a nice UI very easily using components.
Next, you can use this.$qewd
in all your page methods as usual.
License
Copyright (c) 2019 Stabe nv,
Hofstade, Oost-Vlaanderen, BE
All rights reserved
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.