Difference between revisions of "User:Saul/Realtime app"

From Organic Design wiki
(Setup: Subdivided and adding lost more info.)
m (Services: Added info on this section.)
(17 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
This is the documentation for the stack I use for creating a real-time application. The stack consists of node.js and feathers.js for the server, the client uses: Vue, vue-router, vuex and setup using the vue webpack.
 
This is the documentation for the stack I use for creating a real-time application. The stack consists of node.js and feathers.js for the server, the client uses: Vue, vue-router, vuex and setup using the vue webpack.
  
== Setup ==
+
= Setup =
=== Install And Generate Files ===
+
== Install And Generate Files ==
 
The following commands will setup the app:
 
The following commands will setup the app:
 
<source lang="bash">
 
<source lang="bash">
Line 11: Line 11:
 
</source>
 
</source>
  
=== Modify Files ===
+
== Modify Files ==
 
A few changes are need to finish connecting the app:<br>
 
A few changes are need to finish connecting the app:<br>
 
<br>
 
<br>
Copy all dependencies from server/package.json to the package.json located in the root dir. Do the same for request and request-promise from devDependencies.<br>
+
Copy all dependencies from <b>server/package.json</b> to the <b>package.json</b> located in the root dir. Do the same for request and request-promise from devDependencies.<br>
Add to the scripts section in package.json (this allows the back end to be started via "npm run server"):
+
<br>
 +
Add to the scripts section in <b>package.json</b> (this allows the back end to be started via "npm run server"):
 
<source lang="json">
 
<source lang="json">
 
"server": "node server/src/",
 
"server": "node server/src/",
 
</source>
 
</source>
Add to package.json:
+
Add to <b>package.json</b>:
 
<source lang="json">
 
<source lang="json">
 
"directories": {
 
"directories": {
Line 25: Line 26:
 
},
 
},
 
</source>
 
</source>
Modify the dev script in package.json to:
+
Modify the dev script in <b>package.json</b> to:
 
<source lang="json">
 
<source lang="json">
 
"cross-env NODE_ENV=development webpack-dev-server --content-base server/public --open --hot"
 
"cross-env NODE_ENV=development webpack-dev-server --content-base server/public --open --hot"
 
</source>
 
</source>
Modify the config/default.json file like so:
+
Modify the <b>config/default.json</b> file like so:
 
<source lang="json">
 
<source lang="json">
 
"public": "../server/public/",
 
"public": "../server/public/",
 
</source>
 
</source>
Modify the webpack.config.js by changing the path and publicPath like so:
+
Modify the <b>webpack.config.js</b> by changing the path and publicPath like so:
 
<source lang="json">
 
<source lang="json">
 
path: path.resolve(__dirname, "server", "public"),
 
path: path.resolve(__dirname, "server", "public"),
 
publicPath: "/",
 
publicPath: "/",
 
</source>
 
</source>
Modify the index.html so that the script build source is:
+
Modify the <b>index.html</b> so that the script build source is:
 
<source lang="html">
 
<source lang="html">
 
<script src="build.js"></script>
 
<script src="build.js"></script>
 
</source>
 
</source>
  
=== Fix Structure, Install, And Cleanup ===
+
== Fix Structure, Install, And Cleanup ==
 
These commands will finish arranging the files (make sure you are still in the server dir):
 
These commands will finish arranging the files (make sure you are still in the server dir):
 
<source lang="bash">
 
<source lang="bash">
Line 52: Line 53:
 
<source lang="bash">
 
<source lang="bash">
 
cd .. # go back to the project root
 
cd .. # go back to the project root
npm i @feathersjs/client vuex # install additional dependencies (socket.io-client may also be needed?)
+
npm i @feathersjs/client vuex vue-router # install additional dependencies (socket.io-client may also be needed?)
 
npm i # install dependencies
 
npm i # install dependencies
 
</source>
 
</source>
=== Run App ===
+
 
 +
== Run App ==
 
To run in development:
 
To run in development:
 
<source lang="bash">
 
<source lang="bash">
Line 66: Line 68:
 
npm run server # run the backend
 
npm run server # run the backend
 
</source>
 
</source>
=== See Also ===
+
== See Also ==
 
*[[User:Saul/linode#Setting_Up_Node.js]]
 
*[[User:Saul/linode#Setting_Up_Node.js]]
 +
 +
= Client  =
 +
== File Structure ==
 +
To generate the recommended file structure, navigate to the project root directory and run the following command:
 +
<source lang="bash">
 +
mkdir src/components src/store src/libs src/pages # generate the client end folders: components (for storing vue components), store (for storing vuex store files), and libs (for storing client side js libs)
 +
</source>
 +
=== Auto ===
 +
To automatically edit the files run this one-liner or skip to [[User:Saul/Realtime_app#Manual|manual]] if you would like to manually edit them.
 +
The code does the following:
 +
*generates the src/store/index.js file with an example included.
 +
*generates the src/router.js file with examples
 +
*rewrites App.vue to use the vue-router
 +
*rewrites main.js to use the vue-router and vuex
 +
<source lang="bash">
 +
echo -e "import Vue from \"vue\"\nimport Vuex from \"vuex\"\n//import chat from \"./SOTRENAMEONE\"\n//import login from \"./SOTRENAMETWO\"\n\nVue.use(Vuex)\n\nexport default new Vuex.Store({\n\tmodules: {\n\t\t/*\n\t\t\tchat,\n\t\t\tlogin\n\t\t*/\n\t}\n})" > src/store/index.js && echo -e "import Vue from \"vue\"\nimport Router from \"vue-router\"\n//import Login from \"./pages/Login.vue\"\n//import Register from \"./pages/Register.vue\"\n//import Chat from \"./pages/Chat.vue\"\n//import auth from \"./libs/auth\"\n\nVue.use(Router)\n\nconst router = new Router({\n\tmode: \"history\",\n\troutes: [\n\t\t/*\n\t\t\t{\n\t\t\t\tpath: \"/\",\n\t\t\t\tname: \"Chat\",\n\t\t\t\tcomponent: Chat,\n\t\t\t\tbeforeEnter: auth.isLoggedIn\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: \"/login\",\n\t\t\t\tname: \"Login\",\n\t\t\t\tcomponent: Login\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: \"/register\",\n\t\t\t\tname: \"Register\",\n\t\t\t\tcomponent: Register\n\t\t\t},\n\t\t*/\n\t\t// If access a non-existing route, redirect to root route\n\t\t{\n\t\t\tpath: \"*\",\n\t\t\tredirect: \"/\"\n\t\t}\n\t]\n})\n\nrouter.afterEach(function (to, from){\n\t//Set the title for the pages\n\tdocument.title = to.name;\n});\n\nexport default router;" > src/router.js && echo -e "<template>\n\t<div id=\"app\">\n\t\t<router-view></router-view>\n\t</div>\n</template>\n\n<script>\n\texport default {\n\t\tname: \"app\"\n\t}\n</script>\n\n<style>\n\t#app, body, html{\n\t\tbox-sizing: border-box;\n\t\tpadding: 0px;\n\t\tmargin: 0px;\n\t}\n</style>" > src/App.vue && echo -e "import Vue from \"vue\"\nimport App from \"./App.vue\"\nimport router from \"./router\"\nimport store from \"./store\"\n\nnew Vue({\n\tel: \"#app\",\n\tstore,\n\trouter,\n\trender: h => h(App)\n})" > src/main.js
 +
</source>
 +
 +
=== Manual ===
 +
This section does the same thing manually as [[User:Saul/Realtime_app#Auto|Auto]] does.<br>
 +
<br>
 +
First create the src/store/index.js file like this:
 +
<source lang="javascript">
 +
import Vue from "vue"
 +
import Vuex from "vuex"
 +
//import chat from "./SOTRENAMEONE"
 +
//import login from "./SOTRENAMETWO"
 +
 +
Vue.use(Vuex)
 +
 +
export default new Vuex.Store({
 +
modules: {
 +
/*
 +
chat,
 +
login
 +
*/
 +
}
 +
})
 +
</source>
 +
Then create the src/router.js file with the following:
 +
<source lang="javascript">
 +
import Vue from "vue"
 +
import Router from "vue-router"
 +
//import Login from "./pages/Login.vue"
 +
//import Register from "./pages/Register.vue"
 +
//import Chat from "./pages/Chat.vue"
 +
//import auth from "./libs/auth"
 +
 +
Vue.use(Router)
 +
 +
const router = new Router({
 +
mode: "history",
 +
routes: [
 +
/*
 +
{
 +
path: "/",
 +
name: "Chat",
 +
component: Chat,
 +
beforeEnter: auth.isLoggedIn
 +
},
 +
{
 +
path: "/login",
 +
name: "Login",
 +
component: Login
 +
},
 +
{
 +
path: "/register",
 +
name: "Register",
 +
component: Register
 +
},
 +
*/
 +
// If access a non-existing route, redirect to root route
 +
{
 +
path: "*",
 +
redirect: "/"
 +
}
 +
]
 +
})
 +
 +
router.afterEach(function (to, from){
 +
//Set the title for the pages
 +
document.title = to.name;
 +
});
 +
 +
export default router;
 +
</source>
 +
Then change the contents of App.vue like so:
 +
<source lang="html">
 +
<template>
 +
<div id="app">
 +
<router-view></router-view>
 +
</div>
 +
</template>
 +
 +
<script>
 +
export default {
 +
name: "app"
 +
}
 +
</script>
 +
 +
<style>
 +
#app, body, html{
 +
box-sizing: border-box;
 +
padding: 0px;
 +
margin: 0px;
 +
}
 +
</style>
 +
</source>
 +
Finally change the contents main.js to use the vue-router and vuex like this:
 +
<source lang="javascript">
 +
import Vue from "vue"
 +
import App from "./App.vue"
 +
import router from "./router"
 +
import store from "./store"
 +
 +
new Vue({
 +
el: "#app",
 +
store,
 +
router,
 +
render: h => h(App)
 +
})
 +
</source>
 +
 +
== Creating Pages ==
 +
For every page you would like to make create a file in src/pages/PAGENAME.vue and then add it in the src/router.js file.<br>
 +
Each page should have the standard vue template:
 +
<source lang="html">
 +
<template>
 +
</template>
 +
 +
<script>
 +
</script>
 +
 +
<style>
 +
</style>
 +
</source>
 +
 +
== Creating Components ==
 +
Components are independent pieces of code to be embedded into a page.<br>
 +
For every component you would like to make create a file in src/component/COMPONENTNAME.vue<br>
 +
Each component should have the standard vue template (like pages do).<br>
 +
To embed the components in a page you need to import them in the page (in the script section):
 +
<source lang="javascript">
 +
import Chat from './components/chat.vue'
 +
import Channels from './components/channels.vue'
 +
 +
export default{
 +
components: {
 +
Channels,
 +
Chat
 +
}
 +
}
 +
</source>
 +
Then you can use them in the template section like so:
 +
<source lang="html">
 +
<channels></channels>
 +
<chat></chat>
 +
</source>
 +
 +
== Creating Vuex Stores ==
 +
Vuex stores are ways of preserving state.<br>
 +
To create a vuex store for your application create the <b>folder</b> src/store/STORENAME<br>
 +
Create a index.js file in the src/store/STORENAME folder.
 +
The index.js file should contain something like:
 +
<source lang="javascript">
 +
export const state = {
 +
// This should contain variables that you would like to preserve
 +
}
 +
 +
export const mutations = {
 +
// This should contain methods for modifying the state section but should not be called directly
 +
}
 +
 +
export const actions = {
 +
// This should contain methods that do not modify the state directly
 +
// They may however modify the stat by calling a method in the mutations
 +
// This may be done via: commit("mutation_name", channel)
 +
}
 +
 +
export const getters = {
 +
// This should contain methods for retrieving the data from the state
 +
}
 +
 +
export default {
 +
  state,
 +
  mutations,
 +
  actions,
 +
  getters
 +
}
 +
</source>
 +
Then you need to modify the src/store/index.js to reference it.<br>
 +
Then you can import it into your pages and use the data.
 +
 +
== Using JS Librarys ==
 +
To add a JS library just create the file src/libs/LIBNAME.js<br>
 +
Add the code into that file and import it into the relevant files.
 +
 +
= Server =
 +
== Services ==
 +
To generate a feathers js service run:
 +
<source lang="bash">
 +
feathers generate service # Creates the feathers.js service
 +
# Example: Mongoose, channels, /server/src/services, mongodb://localhost:27017/chat
 +
</source>
 +
To generate the authentication service run:
 +
<source lang="bash">
 +
feathers generate authentication # Creates the feathers.js authentication service
 +
</source>
 +
If you have issues with a service check what the service name is.

Revision as of 23:33, 19 March 2018

This is the documentation for the stack I use for creating a real-time application. The stack consists of node.js and feathers.js for the server, the client uses: Vue, vue-router, vuex and setup using the vue webpack.

Setup

Install And Generate Files

The following commands will setup the app:

sudo npm install -g vue @feathersjs/cli # install dependencies globally
sudo vue init webpack-simple APPNAME # create a new project using the "webpack-simple" template
mkdir APPNAME/server && cd APPNAME/server
feathers generate app # generate the feathers app

Modify Files

A few changes are need to finish connecting the app:

Copy all dependencies from server/package.json to the package.json located in the root dir. Do the same for request and request-promise from devDependencies.

Add to the scripts section in package.json (this allows the back end to be started via "npm run server"):

"server": "node server/src/",

Add to package.json:

"directories": {
	"lib": "server/src"
},

Modify the dev script in package.json to:

"cross-env NODE_ENV=development webpack-dev-server --content-base server/public --open --hot"

Modify the config/default.json file like so:

"public": "../server/public/",

Modify the webpack.config.js by changing the path and publicPath like so:

path: path.resolve(__dirname, "server", "public"),
publicPath: "/",

Modify the index.html so that the script build source is:

<script src="build.js"></script>

Fix Structure, Install, And Cleanup

These commands will finish arranging the files (make sure you are still in the server dir):

mv config ../config && mv .editorconfig ../.editorconfig && mv ../index.html public/index.html # move then files to the proper dirs
rm package.json LICENSE .gitignore .npmignore README.md .eslintrc.json package-lock.json -R test node_modules # delete the unnecessary files

And to install the dependencies and run:

cd .. # go back to the project root
npm i @feathersjs/client vuex vue-router # install additional dependencies (socket.io-client may also be needed?)
npm i # install dependencies

Run App

To run in development:

npm run dev # this launches the front-end
npm run server # this launches the back-end

To run in production:

npm build # build the front-end into the backend
npm run server # run the backend

See Also

Client

File Structure

To generate the recommended file structure, navigate to the project root directory and run the following command:

mkdir src/components src/store src/libs src/pages # generate the client end folders: components (for storing vue components), store (for storing vuex store files), and libs (for storing client side js libs)

Auto

To automatically edit the files run this one-liner or skip to manual if you would like to manually edit them. The code does the following:

  • generates the src/store/index.js file with an example included.
  • generates the src/router.js file with examples
  • rewrites App.vue to use the vue-router
  • rewrites main.js to use the vue-router and vuex
echo -e "import Vue from \"vue\"\nimport Vuex from \"vuex\"\n//import chat from \"./SOTRENAMEONE\"\n//import login from \"./SOTRENAMETWO\"\n\nVue.use(Vuex)\n\nexport default new Vuex.Store({\n\tmodules: {\n\t\t/*\n\t\t\tchat,\n\t\t\tlogin\n\t\t*/\n\t}\n})" > src/store/index.js && echo -e "import Vue from \"vue\"\nimport Router from \"vue-router\"\n//import Login from \"./pages/Login.vue\"\n//import Register from \"./pages/Register.vue\"\n//import Chat from \"./pages/Chat.vue\"\n//import auth from \"./libs/auth\"\n\nVue.use(Router)\n\nconst router = new Router({\n\tmode: \"history\",\n\troutes: [\n\t\t/*\n\t\t\t{\n\t\t\t\tpath: \"/\",\n\t\t\t\tname: \"Chat\",\n\t\t\t\tcomponent: Chat,\n\t\t\t\tbeforeEnter: auth.isLoggedIn\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: \"/login\",\n\t\t\t\tname: \"Login\",\n\t\t\t\tcomponent: Login\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: \"/register\",\n\t\t\t\tname: \"Register\",\n\t\t\t\tcomponent: Register\n\t\t\t},\n\t\t*/\n\t\t// If access a non-existing route, redirect to root route\n\t\t{\n\t\t\tpath: \"*\",\n\t\t\tredirect: \"/\"\n\t\t}\n\t]\n})\n\nrouter.afterEach(function (to, from){\n\t//Set the title for the pages\n\tdocument.title = to.name;\n});\n\nexport default router;" > src/router.js && echo -e "<template>\n\t<div id=\"app\">\n\t\t<router-view></router-view>\n\t</div>\n</template>\n\n<script>\n\texport default {\n\t\tname: \"app\"\n\t}\n</script>\n\n<style>\n\t#app, body, html{\n\t\tbox-sizing: border-box;\n\t\tpadding: 0px;\n\t\tmargin: 0px;\n\t}\n</style>" > src/App.vue && echo -e "import Vue from \"vue\"\nimport App from \"./App.vue\"\nimport router from \"./router\"\nimport store from \"./store\"\n\nnew Vue({\n\tel: \"#app\",\n\tstore,\n\trouter,\n\trender: h => h(App)\n})" > src/main.js

Manual

This section does the same thing manually as Auto does.

First create the src/store/index.js file like this:

import Vue from "vue"
import Vuex from "vuex"
//import chat from "./SOTRENAMEONE"
//import login from "./SOTRENAMETWO"

Vue.use(Vuex)

export default new Vuex.Store({
	modules: {
		/*
			chat,
			login
		*/
	}
})

Then create the src/router.js file with the following:

import Vue from "vue"
import Router from "vue-router"
//import Login from "./pages/Login.vue"
//import Register from "./pages/Register.vue"
//import Chat from "./pages/Chat.vue"
//import auth from "./libs/auth"

Vue.use(Router)

const router = new Router({
	mode: "history",
	routes: [
		/*
			{
				path: "/",
				name: "Chat",
				component: Chat,
				beforeEnter: auth.isLoggedIn
			},
			{
				path: "/login",
				name: "Login",
				component: Login
			},
			{
				path: "/register",
				name: "Register",
				component: Register
			},
		*/
		// If access a non-existing route, redirect to root route
		{
			path: "*",
			redirect: "/"
		}
	]
})

router.afterEach(function (to, from){
	//Set the title for the pages
	document.title = to.name;
});

export default router;

Then change the contents of App.vue like so:

<template>
	<div id="app">
		<router-view></router-view>
	</div>
</template>

<script>
	export default {
		name: "app"
	}
</script>

<style>
	#app, body, html{
		box-sizing: border-box;
		padding: 0px;
		margin: 0px;
	}
</style>

Finally change the contents main.js to use the vue-router and vuex like this:

import Vue from "vue"
import App from "./App.vue"
import router from "./router"
import store from "./store"

new Vue({
	el: "#app",
	store,
	router,
	render: h => h(App)
})

Creating Pages

For every page you would like to make create a file in src/pages/PAGENAME.vue and then add it in the src/router.js file.
Each page should have the standard vue template:

<template>
</template>

<script>
</script>

<style>
</style>

Creating Components

Components are independent pieces of code to be embedded into a page.
For every component you would like to make create a file in src/component/COMPONENTNAME.vue
Each component should have the standard vue template (like pages do).
To embed the components in a page you need to import them in the page (in the script section):

import Chat from './components/chat.vue'
import Channels from './components/channels.vue'

export default{
	components: {
		Channels,
		Chat
	}
}

Then you can use them in the template section like so:

<channels></channels>
<chat></chat>

Creating Vuex Stores

Vuex stores are ways of preserving state.
To create a vuex store for your application create the folder src/store/STORENAME
Create a index.js file in the src/store/STORENAME folder. The index.js file should contain something like:

export const state = {
	// This should contain variables that you would like to preserve
}

export const mutations = {
	// This should contain methods for modifying the state section but should not be called directly
}

export const actions = {
	// This should contain methods that do not modify the state directly
	// They may however modify the stat by calling a method in the mutations
	// This may be done via: commit("mutation_name", channel)
}

export const getters = {
	// This should contain methods for retrieving the data from the state
}

export default {
  state,
  mutations,
  actions,
  getters
}

Then you need to modify the src/store/index.js to reference it.
Then you can import it into your pages and use the data.

Using JS Librarys

To add a JS library just create the file src/libs/LIBNAME.js
Add the code into that file and import it into the relevant files.

Server

Services

To generate a feathers js service run:

feathers generate service # Creates the feathers.js service
# Example: Mongoose, channels, /server/src/services, mongodb://localhost:27017/chat

To generate the authentication service run:

feathers generate authentication # Creates the feathers.js authentication service

If you have issues with a service check what the service name is.