Quickly develop Rails ' rich clients with Webpack and ES6 conversions

Source: Internet
Author: User
Tags symlink install node node server ruby on rails transpiler

Fast Rich Client Rails Development with Webpack and the ES6 Transpiler

There's a better way to bring the JavaScript ecosystem into Rails.

Do you have:

    • Wondering if there's a better way to use the modern JavaScript client framework under existing Ruby on Rails projects?
    • How do you integrate JavaScript libraries and examples that are packaged as "modules"?
    • Discover the drawbacks of littering under the global namespace.
    • Heard of ES6 (aka Harmony), the next generation of JavaScript, is now being used in the buzz of Silicon Valley (Facebook, Instagram, Square, and the like)?

So what are you going to do in your Rails project, do the following:

    • Your UI prototype, if you find that JS and Css/sass code has changed, when saved, immediately react to the interface, without overloading the page.
    • As a class citizen in Node ecology , you only need to package.json specify dependencies and execute npm install them, and then you can easily import modules in JavaScript files.
    • Seamless integration of Node-based JavaScript assets to Rails Asset pipeline,** eliminates the need to circumvent the * * Asset Pipeline, but lets it coexist and take advantage of it.
    • Seamlessly integrates the node client ecosystem into existing Rails engineering.
    • Use a variety of JavaScript tools, such as React JSX tranpiler and ES6 transpiler.

This article will show you how to use Webpack to achieve these goals in the Rails development process!

First, I want to tell you a story about how I found it needed a better way to integrate the JavaScript ecosystem into Rails.

Manually copy and paste a bunch of JavaScript to/vendor/assets/javascripts wrong?

Think about what would happen if your Ruby on Rails project didn't bundler? Oh, the cock blows, doesn't it! This is /vendor/assets/javascripts the feeling of manually copying JavaScript! I'm actually pretty worried because more and more JavaScript libraries are starting to rely on other AMD (also called require.js) or CommonJs modules. (There is an article detailing how this modular system works, see Writing Modular JavaScript with AMD, CommonJS & ES Harmony.) One of the problems for the Rails community is to package the popular JavaScript libraries into gems, such as the Jquery-rails gem. Of course you might think that's nice, unless you find that the JavaScript module you're using doesn't have a corresponding Gems. For example, you want to start using NPM
Packaged react components, such as react-bootstrap, or you might want to use JavaScript tools such as JSX and ES6 transpilers (Es6-transpiler and Es6-modul E-transpiler).

Fortunately, I'm not the little baby with the gemfiled looking for JavaScript! You can be a class citizen of JavaScript right now!

Motives: React and ES6

I formally started crouching the rabbit hole of Node from the beginning of preparation with the React framework, including its JSX transpiler. Overall, the React library looks unique, innovative and impressive * *. You can simply assume that the client's UI is a set of components that are rendered based on one-way streaming data, from the top-level component to each of its sub-components. To learn more about the advantages of React, see my other article React on Rails Tutorial. And the purpose of this article is, you can think, I'm going to take React to replace your favorite rich client framework. Of course if someone fork my project and then build a version with Emberjs, I'll be happy.

The first task looks pretty simple with React because it has Ruby's gem,ract-rails Gem, which provides a really painless way to integrate React into rails engineering. It's pretty simple. I made an example, React on Rails Tutorial, and the corresponding GitHub repository, justin808/react-rails-tutorial, this example shows you how to work with Rails 4.2 scaffold generator With react-rails gems. Then I want to use the react-bootstrap. There is no gem, I have considered the manual copy paste into my /vendor/assets/javascripts directory, but it makes me feel very _ _, for the following reasons:

    1. JavaScript has a mature dependency management system (packages and module modules): NPM (and Bower).
    2. Dependencies often also depend on additional packages, whether in the world of Ruby or JavaScript. Imagine if Ruby depended on manual resolution.
    3. JavaScript modules often rely on other CommonJs or Requirejs good modules.

(Note: For Node, module it is a packaged JavaScript code that can be require() called.) For more information, see NPM FAQs and StackOverflow)

There are some other nice ways to handle the Rails app assets:five Ways to Manage front-end assets in rails. I have simply tried these techniques, for example, with the use of the Browserify-rails gem. However, it all seems to react-rails clash with gems, and if I don't use this gem, I need to find another way to convert the jsx into a JS file. This allows me to start experimenting with Webpack module bundler.


What is Webpack?

Webpack generates static assets for the dependencies of modules and modules.

Why would I try Webpack? I recommend you see my Pete Hunt of the React team. There are plenty of reasons to explain why it is Webpack:

    1. Use NPM (also optional bower) as package management.
    2. Support all the module syntax, as long as you like it.
    3. There are many loaders (like pipeline), including ES6 and JSX.
    4. Webpack Dev Server is great for rapid prototyping of JS and Css/sass (Hot Module replacement).

A good place to start learning Webpack is Pete Hunt's webpack-howto.

I originally wanted to use Webpack module bundler to separate JS from Rails because I wanted to see the so-called react code "hot Reload". You can try this to write a simple code: React-tutorial-hot. Hot module Replacement will refresh the JS code (and CSS) at run time without any page refresh required. Even the JS object inside all the data! This technique is much cooler than Live Reload to refresh the entire page.

Then I started using these features of Webpack:

    1. Es6-loader, which includes Es6-transpiler and Es6-module-transpiler. You want to play, try ES6 Grammar, you can pass ES6 fiddle. Here's a great references on ES6 features.
    2. Jsx-loader, use ES6 to process the Jsx file loader.
    3. BITS integration, through NPM can easily add any package, and can use any module syntax.

Since the "bundle" generated by Webpack is not necessarily compressed, it should look like it can be used directly by Rails ' asset pipeline, and sure enough, it can! This article explains clearly: Setting up Webpack with rails and example code explains how to precompile webpack:webpack in the Rails Asset Pipeline.

With a basic section, I started to want to implement the following features:

    1. You can use Webpack Dev Server (Hot module replacement) for client-side JS prototyping and have the same code in my Rails application. This includes JavaScript, Sass, and Image files, which are common to both Rails and Webpack Dev Server.
    2. Can be easily published to Heroku.

My solution was on GitHub repo:justin808/react-webpack-rails-tutorial. This is based on my react-rails example of using gems: Rails 4.2, React, completed tutorial. Next I will explain the project in detail.


You need to install node. js. I assume you already have Ruby and Rails.

    1. node. JS: You can find the download file for node. js here. Well, some of my friends suggested that I use the node. JS installation package instead of Brew. I haven't tried Brew yet.
    2. Many articles suggest executing the following command so that you do not need to use sudo before the node command line, so you can change your/usr/local directory permissions yourself.

      $ sudo chown-r $USER/usr/local

    3. Your /package.json files are used to configure all dependencies, and then you npm install can completely install all the packages as soon as you execute them.

Once this has started to work, it's like Santa Claus gives me a complete Node ecology of the app, cool!

Bundler and Node Package Manager

All Rails developers are familiar with gems and bundler (bundles). The equivalent Javascript is the Package.json file and Node package Manager (NPM) (see the section below, which I'll explain why I don't choose Bower).

Both package management systems are implemented by retrieving trustworthy online resources. It's package.json much better to use a file than to manually download a dependent file and then copy it to the /vendor/assets directory!

Why NPM instead of Bower?

Many of the popular good JavaScript are available on Node package Manager (NPM) and Bower. Because to use Webpack, you should be more inclined to use NPM, the documentation for the following reasons:

In many cases, NPM has a better module quality than Bower. In most cases, Bower only includes the concatenated/bundled file, which results in:

  • Webpack more difficult to manage
  • Webpack more difficult to optimize
  • Sometimes the module system is not available.

So fall in love with commonjs-style module, let Webpack compile it.

Webpack plus Rails's solution description

In order to integrate Webpack to Rails, the following two ways are used:

    1. Webpack is used alone in the /webpack directory, so you can use Webpack dev Server to provide a quick development tool for client Javascript prototyping. webpack.hot.config.jsused to configure JS and CSS assets for Webpack Dev Server.
    2. Webpack monitors and Packages /webpack/assets/javascripts all Javascript under the folder, generated rails-bundle.js . Files webpack.rails.config.js convert JSX files to JS files by using JSX and ES6 transpilers.

The following diagram illustrates the Webpack file organization structure in Rails:

file Notes
/app/assets/javascripts/rails-bundle.js webpack --config webpack.rails.config.jsOutput Directory
/app/assets/javacripts/application.js rails-bundlea reference to such webpack output will be used by sprockets
/app/assets/javascripts Empty all the files here and put them in/webpack/assets/javascripts
/app/assets/stylesheets/application.css.scss /webpack/assets/stylesheetsthe referenced sass file
/node_modules Storing NPM Modules
/webpack All webpack files are placed under this directory, except node_modules andpackage.json
/webpack/assets/images Link to /app/assets/images . This way Webpack Dev Server can see the same picture as Rails sprockets.
/webpack/assets/javascripts JavaScripts will be packaged rails-bundle.js and used for Webpack Dev Server
/webpack/assets/stylesheets StyleSheets for Asset pipeline ( /app/assets/stylesheets/application.css.scss referenced), also used for Webpack Dev Server
/webpack/index.html Use the default home page of Webpack Dev Server
/webpack/scripts Files for Rails or Webpack Dev Server environments only
/webpack/server.js Server.js is the code part of Webpack Dev Server
/webpack/webpack.hot.config.js Webpack webpack Dev Server configuration file
/webpack/webpack.rails.config.js Webpack used to generate rails-bundle.js the configuration file
/.buildpacks Buildpacks for configuring Heroku Multi-Environment node + Ruby
/npm-shrinkwrap.json and/package.json Defining npm install The configuration file at execution time

Again, we are using Webpack for the following reasons:

    1. In order to be able to use JS "module", including using AMD (also called require.js) or CommonJS module syntax
    2. In order to convert the JSX file (ES6 and JSX syntax) to the JS file. Note, or you do not need to change all the JS files to ES6, because it is likely that some of the incoming modules will conflict.

Setup webpack.config file, we want to have two versions according to demand, Webpack Dev Server and Asset Pipeline.

Modify Webpack.config

You might want to not modify this webpack config file. So here are some things you should be aware of.

    1. Module.exports.enty: This entry point will determine where webpack will put the bag. Although it looks much like the manifest file /app/assets/javascripts/application.js , here you need to specify just the **entry** point. So if you specify ./assets/javascripts/example (you don't need a file suffix) as the entry point, then you don't need and don't specify ./assets/javascripts/CommentBox this as an entry point. Again, this dependency is done for Webpack, not Rails.
module.exports = { context: __dirname, entry: [   "./assets/javascripts/example" ],
    1. module.exports.externals: If you need to load jQuery from a CDN or from a Rails gem, you should specify it like this:

      module.exports.externals: { jquery: "var jQuery"},

    2. module.exports.module.loaders: Here's where you can expose Webpack's jQuery to Rails-bundle.js. In this way, the JavaScript part of the non-module in Rails can also be used with jQuery.

module.exports.module: {  loaders: [    // Next 2 lines expose jQuery and $ to any JavaScript files loaded after rails-bundle.js    //   in the Rails Asset Pipeline. Thus, load this one prior.    { test: require.resolve("jquery"), loader: "expose?jQuery" },    { test: require.resolve("jquery"), loader: "expose?$" }  ]}
Webpack Dev Server and hot Module replacement

Because waiting for Webpack to generate rails-bundle.js files and then refreshing the Rails page is very time consuming, and using Webpack Dev Server and hot Module replacement is simply slag, using the latter if possible, You can also load new JavaScript and Sass code directly without modifying the client data. If you think Live Reload is cool, you will definitely love this feature. Take a look at this quote:

Webpack-dev-server is a small node. JS Express Service that provides services for Webpack by using webpack-dev-middleware . It also has a small runtime that is linked to the service via Socket.io . The service pushes state changes to the client, and then the client responds to this change.

It handles static assets files from the current directory. If the file does not find an HTML page referencing the current JavaScript, it will automatically generate one.

In short, the file /webpack/server.js is an HTTP service that uses the Webpack Dev Server API:

    1. /webpack/webpack.hot.config.jsConfiguring the Webpack Asset
    2. There are multiple responses to JSON
    3. Set "hot" to true so that hot module replacement is available.

Webpack handles /webpack/assets/javascripts These aspects of the folder problem:

    1. Prepare the JavaScript file "package" for Rails or Webpack Dev Server. This includes executing jsx and ES6 loader, converting JSX and ES6 syntax into standard JavaScript. The following are the appropriate configurations:
module.loaders = [{ test: /\.jsx$/, loaders: ["react-hot", "es6", "jsx?harmony"] }]
    1. Webpack also handles the module loading syntax (Requirejs, CommonJs, or ES6) of your choice.
Sass and images

For Webpack Dev Serve (not the Rails version of Rails-bundle.js), Sass is mainly based on two reasons for Webpack loading:

    1. Webpack can handle the sass compiler.
    2. Any sass or CSS file changes can be loaded into the browser via Hot module loader.

The file /webpack/scripts/webpack_only.jsx contains the following:


This "require" style file is the same as the "require" JavaScript. So there /webpack/index.html is no reference to anything generated from Sass. This file is webpack_only.jsx also webpack.hot.config.js used only as an "entry point" in the file, meaning it is explicitly called in the bundle file.

Images is a bit of a mess, at the time of release, for caching purposes, you want your image to be able to add fingerprints (fingerprint). For those who are using the new version of Rails, it's basically something to ignore, of course, thanks to the asset pipeline feature of rails. Of course webpack can also fingerprint pictures, but this is not necessary, because in our Railse release environment, there is no need to use the webpack of this feature. So we just need to access the same image in the Webpack Dev Server. That is, we need to be able to reference the same picture in the Scss file, whether it's Webpack Dev Server or Rails asset pipeline.

For example, here is a fragment of the sass code that is used to load the twitter_64.png image in the top-level directory /app/assets/images . This needs to be available in Rails ' Asset Pipeline and Webpack Dev Serve.

.twitter-image {  background-image: image-url(‘twitter_64.png‘);}

The question is how to get the same picture from the style files in the Rails and Express versions of the server, and we can use the symlink, and Git is easy to store.

    1. /webpack/assets/image/app/assets/imagesfolder pointed to
    2. image-urlSass Helper can handle the correct picture directory mapping relationship. The picture directory is configured in the Webpack service through the following line:
module.loaders = [{ test: /.scss$/, loader: “style!css!sass?outputStyle=expanded&imagePath=/assets/images”}]

The Sass Gem in RALs is responsible for handling Asset pipline.

    1. Symlink is required because Webpack Dev Server is not able to fetch pictures from the root directory.

In this way, images can be obtained correctly in the production environment through Rails Asset Pipeline, and are also well used in Webpack Dev Server.


When debugging JavaScript through the Rails app, I don't want to flip through the huge rails-bundle.js inside. Webpack's sourcemap can solve this problem. First I tried to use pure sourcemaps (splitting the file, not the integration), but because a mistake caused the failure. Then I played some tricks to move the files to the right place, that is /public/assets . And you should note that creating a Sourcemap file during publishing to Heroku will cause Heroku compilation to fail. All of these actions are handled at the webpack.rails.config.js bottom of the file.

In Chrome, Sourcemap looks like this:

Heroku Release

When we publish on Heroku, we still need to do something about it.

    1. If all the dependencies in the installation are very heavy at the time of the release package.json , you only need to install dependencies and not _ devDependencies . You only need to install the tools when you do development on your local Webpack dev Server devDependencies .
    2. To clean up your compilation cache:

      heroku plugins:install https://github.com/heroku/heroku-repo.githeroku repo:purge_cache -a <my-app>
    3. package.json dependencies After you have made any * * changes to the right, make sure to performnpm-shrinkwrap
    4. I need to create it with a file /lib/tasks/assets.rake configuration task through Webpack compile_environment rails-bundle.js .
    5. Heroku requires node and ruby two environments. In order to publish to Heroku, you need to execute the following command to set a custom buildpack:

      heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

      This will return two buildpack in the file /.buildpacks , please see ddollar/heroku-buildpack-multi for more details.
Why Node_modules and Package.json are not placed in the Webpack directory

Of course it node=modules 's more neat to put and put it in the package.json /webpack catalogue, but the problem is, because using a custom Buildpack,heroku will install a node_modules yourself.

Why a second level Assets directory is required under Webpack

At first, I did /app/assets/javascripts refer to the JSX file from the directory. But I would like to use the Webstorm project to manage JavaScript code. I either put the Webstorm project in the root directory, which would bring all the Ruby directories, or I would link to the JavaScript directory. You * * * will not want to run two different jetbrains products in the same directory at the same time, so I vetoed the webstorm scenario in the top layer of Rails application. The Symlink approach seems to work, but sometimes it leads to confusion, such as when I use Emacs to open JSX.

It works for me to put webpack packaging files in the /webpack/assets directory. Webpack package These files and then put the generated rails-bundle.js files into the /app/assets/javascripts directory which looks very natural.

Also, I put the style files referenced by Webpack into the /webpack directory. Note that I loaded the style file through Webpack because this allows the hot load of style files to the browser! If you modify any of the files in the /webpack/assets/stylesheets directory, you will see that the changes are reflected almost at the same time as you save the browser. The standard Rails file /app/assets/stylesheets/application.css.scss references the /webpack/assets/stylesheets following style file.

How do I add NPM (JavaScript) module dependencies?

It's kind of like you're using Gemfile to add a new gem dependency.

    1. Modify the /package.json corresponding line in the section of your file dependencies to add the package you want. You will want to specify the version, which is strongly recommended by the Node community. You just have to Google the "NPM < what module >" Then you will get a link to this NPM package page and then you go to see the version you want. For example you want to add a marked dependency, I add package.json this line in it:

"Marked": "^0.3.2",

    1. Insert a module reference. For example, import a marked package:

      var marked = require("marked");

      How to upgrade Node dependencies

When you are ready to upgrade your package, you should use the following step. Import Npm-check-updates and Npm-shrinkwrap.

cd <top level of your app>rm -rf node_modulesnpm install -g npm-check-updatesnpm-check-updates -unpm installnpm-shrinkwrap

Rapid Client Development

Congratulations! You already know the secret weapon that I think can be developed quickly for JavaScript development. Once you've installed each of the steps above, then like this:

    1. Run Webpack Dev Server on Port 3000

      cd webpack && node server.js
    2. Accessing in the browser
    3. Open another shell and execute

      foreman start -f Procfile.dev
    4. Open in the browser to see if you can see the Rails-bundle.js file.
    5. Update the /webpack/assets following jsx and scss files, and then look at the changes that occur on the browser on Port 3000.
    6. Create a JSX with some static data, and then try to server.js send the JSON to the client.
    7. Once these all work, try to create JSON from the Rails service.
    8. Publish to Heroku!
    9. Get!
    1. This article's Github warehouse: justin808/react-webpack-rails-tutorial
    2. Version available on Heroku: http://react-webpack-rails-tutorial.herokuapp.com/
    3. storing or excluding Node Modules in Rails Git repositories
    4. Pete Hunt's introductory guide to Getting Started with Webpack.

Quickly develop Rails ' rich clients with Webpack and ES6 transformations

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.