A quick and easy way to setup Rails + PWA + Turbolinks + Webpacker + Vue + Jest. If your team is considering, or has already decided, to use Vue, this is the right for you. As extra review how to setup PWA, Turbolinks, CSS frameworks, Storybook.
Things you may want to cover:
-
Ruby version: 2.5.3
-
System dependencies: Node.js, Yarn, PostgreSQL, Heroku CLI
-
Key Dependencies: Ruby on Rails version 5.2, Vue.js version 2.5, Webpacker with Webpack 4 and Babel 7
gem install rails -v 5.2
rails new vuejs-rails-5-starterkit -M -C -S --skip-turbolinks --webpack=vue -d postgresql
cd ./vuejs-rails-5-starterkit
bin/rails db:create db:migrate
-
Uncomment
system('bin/yarn')
inbin/setup
andbin/update
to install new node modules. -
Install dependencies:
bin/setup
- Enable unsafe-eval rule to support runtime-only build and webpacker-dev-server
This can be done in the config/initializers/content_security_policy.rb
with the following
configuration:
Rails.application.config.content_security_policy do |policy|
if Rails.env.development?
policy.script_src :self, :https, :unsafe_eval
policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035'
else
policy.script_src :self, :https
end
end
You can learn more about this from: Vue.js Docs and Webpacker/Vue Docs.
- Verify that we have not broken anything
bin/webpack
bin/rails runner "exit"
- Update
Gemfile
to use new version:
gem 'webpacker', '>= 4.0.x'
- Install new Webpacker and update application
bundle update webpacker
bin/rails webpacker:install
bin/rails webpacker:install:vue
- Upgraded packages by Yarn too
yarn add @rails/webpacker@next
yarn upgrade webpack-dev-server --latest
yarn install
- Verify that everything is still working
bin/webpack
bin/rails test
- Install
@vue/babel-preset-app
:
yarn add @vue/babel-preset-app
-
Replace
@babel/preset-env
with@vue/app
in.bablerc
-
Verify by:
bin/webpack
- Enable Webpacker by updating
app/views/layout/application.html.erb
:
Replace:
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
with:
<%= stylesheet_pack_tag 'hello_vue', media: 'all' %>
<%= javascript_pack_tag 'hello_vue' %>
- Add sample page to host Vue.js component:
bin/rails g controller Landing index --no-javascripts --no-stylesheets --no-helper --no-assets --no-fixture
- Setup sample page as home page by updating
config/routes.rb
:
root 'landing#index'
- Verify locally that vue.js working
bin/rails s
open "http://localhost:3000/"
- Add Jest
yarn add --dev jest vue-jest babel-jest @vue/test-utils jest-serializer-vue 'babel-core@^7.0.0-bridge' @babel/core
- Add to
package.json
:
"scripts": {
"test": "jest"
},
"jest": {
"verbose": true,
"testURL": "http://localhost/",
"roots": [
"test/javascript"
],
"moduleDirectories": [
"node_modules",
"app/javascript"
],
"moduleNameMapper": {
"^@/(.*)$": "app/javascript/$1"
},
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
},
"snapshotSerializers": [
"<rootDir>/node_modules/jest-serializer-vue"
]
},
- Add to
.babelrc
:
"env": {
"test": {
"presets": [
["@babel/preset-env", {
"targets": {
"node": "current"
}
}]]
}},
- Add
test/javascript/test.test.js
:
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});
- Verify installation
yarn test
- Add component test for App in
test/javascript/app.test.js
:
import { mount, shallowMount } from '@vue/test-utils'
import App from 'app';
describe('App', () => {
test('is a Vue instance', () => {
const wrapper = mount(App)
expect(wrapper.isVueInstance()).toBeTruthy()
})
test('matches snapshot', () => {
const wrapper = shallowMount(App)
expect(wrapper.html()).toMatchSnapshot()
})
});
- Verify by
yarn test
You should see all tests passed
- Confirm compilation is working:
RAILS_ENV=production \
NODE_ENV=production \
RAILS_SERVE_STATIC_FILES=true \
SECRET_KEY_BASE="7aa51097e982f34be02abe83528c3308768dff3837b405e0907028c750d22d067367fb79e2b223e3f223fea50ddf2d5dc9b3c933cf5bc8c7f2a3d3d75f73c4a7" \
bin/rails assets:precompile
- Create Heroku App and provision it
Requirements: Heroku CLI.
NOTE: Do not forget to commit all your changes: git add . && git commit -m "Generates Ruby on Rails application with Vue.js onboard"
heroku create
heroku buildpacks:add heroku/ruby
heroku config:set RAILS_ENV=production NODE_ENV=production
- Deploy and verify that vue.js working on Heroku
git push heroku master
heroku apps:open
- Install
serviceworker-rails
by adding intoGemfile
:
gem 'serviceworker-rails', github: 'rossta/serviceworker-rails'
- By following guide: https://github.com/rossta/serviceworker-rails should get something to: https://gist.github.com/pftg/786b147eff85a6fc98bd8dc1c3c9778e
- Add node dependencies
yarn add vue-turbolinks turbolinks
yarn install
- Load Turbolinks by adding
app/javascript/initializers/turbolinks.js
:
import Turbolinks from 'turbolinks'
Turbolinks.start()
- Update
app/javascript/packs/application.js
:
import 'initializers/turbolinks.js'
- Uncomment in
hello_vue.js
:
import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
const app = new Vue({
el: '#hello',
data: {
message: "Can you say hello?"
},
components: { App }
})
})
- Update layout with:
<div id="hello"></div>
- Run tests and server to verify:
bin/rails t
bin/rails s