Table of contents
Overview
We choose Vue.js as the framework to develop new Web applications within OpenPaaS. This page describes architecture, best practices and explain choices we made.
Dependencies
Here is the (uncomplete) list of dependencies used to build a Vue app:
- Vue, vue-router, vuex
- HTTP Client: axios, vue-axios
- Material design: Vuetify and so Stylus
- Templates: HTML, PUG with the help of the right loaders
- Auth: @websanova/vue-auth
- Tests: Jest
Environment
We use latest Vue version, Vue CLI 3 and Node 10.x:
- You will need Node and we recommend using nvm to manage your Node version, so install it first if you do not already use it.
- Install Node 10 with nvm
nvm install 10
, then switch if needednvm use 10
- Install Vue CLI
npm install -g @vue/cli
Bootstrap a new application
A “seed” is available at https://github.com/linagora/vue-openpaas-seed. It uses all the dependencies listed above and provides an OpenPaaS compatible layout. By using this seed as basis for other apps, you will be sure to be compliant with all the good practices defined in this guide.
1. Clone the seed
(Replace my-app
by your app name)
git clone git@github.com:linagora/vue-openpaas-seed.git my-app
You will have to change several things in the files, expecially the application name and description in package.json
.
2. Install dependencies
cd my-app
npm install
3. Configure
The application can be configured by updating the .env
files as described in the Vue CLI documentation. Values defined in the .env
file are used at several places in the app (from the store), and can be adapted to your environment. For example, while in development, you can redefine your OpenPaaS instance URL in a .env.development.local
file which will never be commited (so you can also push secrets in it).
VUE_APP_SUPER_SECRET=A super secret thing
VUE_APP_OPENPAAS_URL=http://localhost:8080
4. Develop
Once done, you can start developping:
- You can start the app in dev mode with
npm run serve
- Or, use the Vue CLI UI
vue ui
and browse to your application.
Best practices
Project files layout
We use the default layout provided by vue-cli:
- All the configuration files are at the root of the repository
- Application code is under
src
src/App.vue
andsrc/main.js
are the application entry pointsrc/*.*
files are used to configure the applicationsrc/components
is used for ‘reusable components’src/services
are business services: auth, API clients, everything which is not related to Vuesrc/store
is where the vuex store lives in. As defined in the Store section, we use modules in the store, so each module has its own folder likesrc/store/moduleA
andsrc/store/moduleB
src/views
is used for application ‘pages’. These views are the one which are used by the router. The views are using the components fromsrc/components
State Management
There are tons of articles around the Web to understand why managing state the Flux-way is easy and powerful. The choice was not hard, just because Vue is simple and provides just the right tools, Vuex is used as state manager, and we rely on the modular approach so that we can scale our app.
As shown in src/store/
:
Routing
vue-router is used as the application router.
- We use name-based routing as defined in https://router.vuejs.org/guide/essentials/named-routes.html
- By using
vue-auth
, routes can be protected and so user will be redirected to the login page until he is authenticated. For example (fromsrc/router.js
):
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home,
meta: {
auth: true
}
},
{
path: '/login',
name: 'Login',
component: Login,
meta: {
auth: false
}
}
]
});
The user will be redirected to the Login
page if he is not authenticated when opening the Home
page.
Authentication
The authentication is a complex subject and depends on the way application are hosted in OpenPaaS. Basically, they can be hosted as any other traditional AngularJS application, i.e. in an OpenPaaS module which is served by the OpenPaaS ESN, or they can be hosted in their own ‘runtime’, for example, in a distinct container, or as static assets.
ESN-hosted application
As described in the ESN authentication documentation, AngularJS application relies on cookies to authenticate user: A session cookie is sent with each request. This will be the same if the Vue application is hosted on a module, if not, new authentication mechanisms have to be implemented in the Vue application.
PaaS-hosted application
By ‘PaaS-hosted’, it means that the application is not hosted in an OpenPaaS ESN NodeJS module. It is hosted somewhere else, in a Docker container, served by an Apache server, etc…
JWT
websanova@vue-auth is used to implement JWT based authentication: When a user fills his login/password on the login page, a single POST /api/jwt/generate
request is sent to the OpenPaaS backend, to get a JWT token for the given user. The token is then pushed in the application state and reused in all HTTP calls to OpenPaaS.
Cookies
This is not available right now and it hardly depends on how application are deployed in OpenPaaS:
If a user who is authenticated within OpenPaaS opens a Vue powered application running somewhere else in the PaaS, we should be able to not ask the password again and again. There are several ways to do this, one will be to push a JWT token in the cookie and extract this JWT token when the Vue application is launched.
T O D O: This needs to be checked
LemonLDAP
T O D O: Check how Lemon can be used, (and is already used)
Reusing components
Some frontend components are available as described in Vue Components. If for some reason, you need a component which is not provided by this module but you think it will be useful to share, please consider adding it to the module.
Using OpenPaaS Core API
T O D O: We need a dedicated module.
Build
Building the application can be done from npm npm run build
or from Vue UI. It will generate the application in the dist
folder.
Deploy
Vue applications such as openpaas-videoconference-app which need to be deployed in Docker environment must follow some rules:
- The Docker image must contain the generated assets (from
npm run build
) - The application must not be configured at build time but at run time. This means that we can not use
vue-cli
resources like.env
files in this case - The Vue application assets must be served by an HTTP server like nginx and exposed correctly by the container
Build & Run
# Multistage build
FROM node:10.13.0-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Then to run
FROM nginx:1.13.12-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
VOLUME ["/usr/share/nginx/html/env"]
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
The important point here is the Docker volume used to put files into the container at runtime. The files in /usr/share/nginx/html/env
folder is then used by the application to get all the variables needed to run. For a concrete example, check code in https://ci.linagora.com/linagora/lgs/openpaas/openpaas-videoconference-app/merge_requests/32.
This is then possible to configure the running app from the Docker run command, or any compatible Docker environment like:
docker run -it -p 8888:80 --rm --name openpaas-videoconference-app -v $PWD/.config/env:/usr/share/nginx/html/env linagora/openpaas-videoconference-app