VueRails
online demo for server side render
Get started with Webpacker
add webpacker and vue_rails to your gemfile
gem 'webpacker'
gem 'vue_rails'
run installers
$ bundle install
$ rails webpacker:install
$ rails webpacker:install:vue
$ rails generate vue:install
confirm your webpacker source_entry path
|-- app
|-- javascript
|-- packs
|-- application.js
|-- vue_server_render.js
|-- vue_components
|-- hello.vue
|-- rails_vue_ujs.js
all the vue components should be initialized in vue_componects
Basic Usage
1. add javascript_pack_tag to application.html
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
2. generate a controller and view
example:
$ rails generate controller home index
and don't forget the router config!
3. add vue_components in your home/index.html
<%= vue_component("hello") %>
multiple components render is also work!
<%= vue_component("hello") %>
<%= vue_component("hello") %>
<%= vue_component("hello") %>
4. open the browser and check it, it should been works!
mapping between component path and name
/vue_components/hello.vue
-> vue_component('hello')
/vue_components/post/index.vue
-> vue_component('post/index')
/vue_components/post/edit/index.vue
-> vue_component('post/edit/index')
Advanced Usage
pass props to your components
<%= vue_component("hello", {foo: 'bar'}) %>
in your component hello.vue:
<template>
<div id="app">
<p>{{ outside.foo }}</p>
</div>
</template>
<script>
export default {
props: ['outside'],
data: function () {
return {
message: "Hello Vue!"
}
}
}
</script>
hash or array is also works
<%= vue_component("hello", {foo: {name: 'Peter'}}) %>
<template>
<div id="app">
<p>{{ outside.foo.name }}</p>
</div>
</template>
<script>
export default {
props: ['outside'],
data: function () {
return {
message: "Hello Vue!"
}
}
}
</script>
<%= vue_component("hello", {foo: [1,2,3]}) %>
<template>
<div id="app">
<template v-for="i in outside.foo">
<div>{{i}}</div>
</template>
<p>{{ outside.foo.name }}</p>
</div>
</template>
<script>
export default {
props: ['outside'],
data: function () {
return {
message: "Hello Vue!"
}
}
}
</script>
server side render
If you're just a component for rendering small parts, you should not use server side render!
with options prerender
, server side will prerender a dom before vue components initialize in client side
<%= vue_component("hello", {foo: [1,2,3]}, {prerender: true}) %>
distinguish ssr and csr ,use props env_ssr
Adjust the order of asset_tags
<!DOCTYPE html>
<html>
<head>
<title>RailsVueSsr</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_pack_tag 'application' %>
</head>
<body>
<%= yield %>
</body>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</html>
javascript_pack_tag should under the body
server side render with vue-router
$ yarn add vue-router
in both application.js and vue_server_render.js
import VueRouter from 'vue-router';
RailsVueUJS.use(VueRouter);
and your vue component
<template>
<div class="container">
<div class="content">
<router-view :outside="outside" :env_ssr="env_ssr"></router-view>
</div>
</div>
</template>
<script>
import VueRouter from 'vue-router';
import PostList from './posts/index';
import PostDetail from './posts/show';
import newPost from './posts/new';
import EditPost from './posts/edit';
const routes = [
{
path: '/',
component: PostList,
name: 'post_index',
props: true
},
{
path: '/posts/new',
component: newPost,
name: 'new_post'
},
{
path: '/posts/edit/:id',
component: EditPost,
name: 'edit_post'
},
{
path: '/posts/:id',
component: PostDetail,
name: 'post_detail'
}
];
const router = new VueRouter({
mode: 'history',
routes
});
export default {
props: ['outside', 'env_ssr'],
router
};
</script>
option prerender can receive a path for vue router
<%= vue_component("hello", {foo: [1,2,3]}, {prerender: request.path}) %>
in your routes.rb
get '*path', to: 'home#index'
server side render with vuex
$ yarn add vuex
initialize a store
import Vue from 'vue'
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
currentUser: {},
hasLogin: false
}
});
export default store;
in both application.js and vue_server_render.js
import VueRouter from 'vue-router';
import Vuex from 'vuex';
import store from "../vue_components/store";
RailsVueUJS.use(VueRouter, Vuex);
RailsVueUJS.initializeVuexStore(store);
...
in your html file
<%= vue_component("hello", {foo: [1,2,3]}, {prerender: true, state: {
hasLogin: true
}}) %>
with option state
, it will replace your vuex state, for more information see the doc with vuex
in your component
...
<div v-if="$store.state.hasLogin">
<a href="/users/logout">logout</a>
</div>
...
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the VueRails project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.