/vuejs-rails-starterkit

Vue.js + Rails Starting Kit to develop Hybrid Mobile Application: https://vuejs-rails-starterkit.herokuapp.com

Primary LanguageRubyMIT LicenseMIT

Setting up Rails 6 with PWA, Turbolinks, Webpack(er) 4, Babel 7, Vue.js 2 and Jest.

NOTE: For Rails 5.2 please check https://github.com/jetthoughts/vuejs-rails-starterkit/tree/rails-5-latest

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:

Generate Ruby on Rails Project with Vue.js (No Turbolinks included on this stage)

gem install rails

rails new vuejs-rails-starterkit --force --database=postgresql \
  --skip-action-mailer --skip-action-cable --skip-sprockets --skip-turbolinks \
  --webpack=vue

cd ./vuejs-rails-starterkit

bin/rails db:create db:migrate

Setup development environment:

  1. Uncomment system('bin/yarn') in bin/setup and bin/update to install new node modules.

  2. Install dependencies:

bin/setup
  1. 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.

  1. Verify that we have not broken anything
bin/webpack
bin/rails runner "exit"

Use Webpacker assets in the application

  1. Enable Webpacker by updating app/views/layout/application.html.erb:

Add after:

    <%= stylesheet_link_tag 'application', media: 'all' %>
    <%= javascript_pack_tag 'application' %>

inlcude of vue example:

    <%= stylesheet_pack_tag 'hello_vue', media: 'all' %>
    <%= javascript_pack_tag 'hello_vue' %>
  1. Add sample page to host Vue.js component:
bin/rails generate controller Landing index --no-javascripts --no-stylesheets --no-helper --no-assets --no-fixture
  1. Setup sample page as home page by updating config/routes.rb:
  root 'landing#index'
  1. Verify locally that vue.js working
bin/rails s
open "http://localhost:3000/"

Expect to see

Install Jest for Component Unit Tests

  1. Add Jest
yarn add --dev jest vue-jest babel-jest @vue/test-utils jest-serializer-vue 'babel-core@^7.0.0-bridge' @babel/core
  1. 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"
    ]
  },
  1. Add test/javascript/test.test.js:
test('there is no I in team', () => {
  expect('team').not.toMatch(/I/);
});
  1. Verify installation
yarn test

You should found

  1. 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()
  })
});
  1. Verify by
yarn test

You should see all tests passed

Setup Heroku and Deploy

  1. Confirm compilation is working:
RAILS_ENV=production \
NODE_ENV=production \
RAILS_SERVE_STATIC_FILES=true \
SECRET_KEY_BASE="7aa51097e982f34be02abe83528c3308768dff3837b405e0907028c750d22d067367fb79e2b223e3f223fea50ddf2d5dc9b3c933cf5bc8c7f2a3d3d75f73c4a7" \
bin/rails assets:precompile
  1. 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
  1. Deploy and verify that vue.js working on Heroku
git push heroku master

heroku apps:open

Setup basic PWA

  1. Install serviceworker-rails by adding into Gemfile:
gem 'serviceworker-rails', github: 'rossta/serviceworker-rails'
  1. By following guide: https://github.com/rossta/serviceworker-rails should get something to: https://gist.github.com/pftg/786b147eff85a6fc98bd8dc1c3c9778e

Setup Turbolinks

  1. Add node dependencies
yarn add vue-turbolinks turbolinks
yarn install
  1. Load Turbolinks by adding app/javascript/initializers/turbolinks.js:
import Turbolinks from 'turbolinks'
Turbolinks.start()
  1. Add to app/javascript/packs/application.js:
import 'initializers/turbolinks.js'
  1. 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: () => {
      return {
        message: "Can you say hello?"
      }
    },
    components: { App }
  })
})
  1. Update layout with:
<div id="hello"></div>
  1. Run tests and server to verify:
bin/rails t
bin/rails s