Single file components and SSR for Rails with Vue JS and Webpack
If I were to build this gem again, I would probably use something like mini_racer to render the Vue components on the same server, as opposed to introducing an HTTP request and infra overhead. If anyone still uses this gem and wants to do that work, it should be relatively straight forward by modifying the Renderer class.
Vueport provides your Rails app with a modern, componentized approach to UI development by using Webpack and Vue.js to enable single file, reactive components rendered on the server and the client and seamless integration with your Rails views.
Take a look at the Vue.js documentation on single file components for more information on that side of things.
Vueport piggybacks onto the WebpackRails gem to get Webpack setup with Rails, so check that out for more information.
Example Rails App
Add this line to your application's Gemfile:
And then execute:
Or install it yourself as:
$ gem install vueport
Then just run
rails generate vueport:install
to bootstrap everything you need to get started (this will install WebpackRails and also everything Vueport needs on top).
To run your app, execute
bundle exec foreman start -f Procfile.dev
to boot the Webpack Dev server and your Rails app!
Ensure to run
npm run compile (or
yarn run compile) as part of your deployment process to production. This compiles the production version of your client side bundle, as well as compiling the server side bundle for our Node JS app to use.
In production we send HTTP requests to a basic NodeJS server to render our content. To run the Rails app and the Node server concurrently, use
Wrap your application in the
vueport helper, to render out your components. E.g. in your
<body> <%= vueport do %> <%= render partial: 'shared/nav' %> <%= yield %> <% end %> </body>
It can also accept a single argument. E.g.:
<body> <%= vueport yield %> </body>
Ensure you place the JS entrypoint after the Vueport helper!
Out of the box, Vueport expects your components to live in app/components, and compiles assets to public/webpack. To change these, you'll need to change both the Webpack config (in config/webpack.config.js and config/webpack.server.js) and the Vue gem application config. To do this, in an initializer do:
Vueport.configure do |config| config[:server_port] = 3001 end
Check out the WebpackRails gem for information on its configuration.
How does it work?
What Vueport gives you is effectively 3 applications:
- Your base rails app
- A Node app for server side rendering in production (in /renderer)
- A Node app for running webpack in development
These have been set up so that they can be built for production completely separately to avoid complicated pipelines—for example, you can run these 3 application using Docker completely separately meaning you don't need Ruby and Node in a single Dockerfile.
For more information on how Webpack has been integrated with Rails, check out this section of the Webpack Rails readme.
Server Side Rendering (SSR)
To enable Server Side rendering, I created a simple NodeJS app which uses the Vue Server Renderer to render out the contents of the page on each request. To enable Client Side rehydration, we also attach the original view contents in a template for the Client Side Vue instance to pick up.
SSR is only enabled in production.
My experience of working with many modern UI libraries, and particulary with integrating them with Rails apps (especially React and Vue JS), has lead me to the conclusion that Vue JS seems to be a more explcit and 'batteries included' library when building compnents for Rails.
I use React on a regular basis for SPAs and love its functional philosophy, but for writing components to fit into a Rails frontend, Vue seems to provide me with the least complexity, and seems to be easiest for Ruby developers to reason about.
For a Vue.js and React collaborative comparison, check this out.
I get the error
Could not load compiled manifest from /app/public/webpack/manifest.jsonin production
You'll need to run
npm run compileas part of your build process to generate the production JS bundle (this error is generated by WebpackRails)
- Handle SSR
- Make webpack config more like the config from the Vue CLI template
- Optimize SSR interaction with NodeJS
- JS Component test setup
After checking out the repo, run
bin/setup to install dependencies. Then, run
rake spec to run the tests. You can also run
bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run
bundle exec rake install. To release a new version, update the version number in
version.rb, and then run
bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the
.gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/samtgarson/vueport. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
- Many thanks to Evan You and the VueJS team for sustaining such a vibrant and supportive community around Vue JS
- Many thanks also to mipearson for his WebpackRails gem on which this gem relies.
The gem is available as open source under the terms of the MIT License.