Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Babelrc env preset for rails app with React + Redux without webpacker using Prettier, Jest and Browserify for create-react-app like setup

package.json

Here I've placed what I see as essentials. Feel free to add or substract if your see overkill for your sitruation! sinon seems like the only potential overkill to me at the time of this writing.

{
  "name": "app-name",
  "jest": {
    "verbose": true,
    "moduleFileExtensions": [
      "js",
      "jsx",
    ],
    "testURL": "https://testing.app.com"
  },
  "devDependencies": {
    "babel-jest": "^21.2.0",
    "browserify-incremental": "^3.1.1",
    "eslint": "^4.4.1",
    "eslint-config-prettier": "^2.3.0",
    "eslint-plugin-babel": "^4.1.2",
    "eslint-plugin-prettier": "^2.1.2",
    "eslint-plugin-react": "^7.2.1",
    "jest": "^21.0.1",
    "nock": "^9.0.14",
    "prettier": "^1.7.2",
    "prettier-eslint": "^8.2.0",
    "react-test-renderer": "^15.6.1",
    "redux-mock-store": "^1.2.3",
    "sinon": "^3.2.0"
  },
  "license": "",
  "engines": {
    "node": "^6.10"
  },
  "dependencies": {
    "babel-core": "^6.26.0",
    "babel-eslint": "^8.0.1",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.6.0",
    "babel-preset-react": "^6.24.1",
    "babelify": "^7.3.0",
    "browserify": "^14.4.0",
    "isomorphic-fetch": "^2.2.1",
    "prop-types": "^15.5.10",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-redux": "^5.0.6",
    "redux": "^3.7.2",
    "redux-thunk": "^2.2.0",
  },
  "browserify": {
    "transform": [
      [
        "babelify"
      ]
    ]
  },
  "scripts": {
    "test": "jest",
    "test:watch": "yarn jest -- --watch",
    "lint": "eslint --ext .js --ext .jsx --max-warnings 0 .",
    "lint-fix": "eslint --ext .js --ext .jsx --fix --max-warnings 0 ."
  }
}

.babelrc

This is where babel configs live. This targets browsers with over 1% of global usage. This also is browserify compatible, meaning it compile everything down to ES5.

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": "> 1%"
        },
        "useBuiltIns": "usage",
        "forceAllTransforms": true,
        "shippedProposals": true
      }
    ],
    "react"
  ],
  "plugins": [
    "syntax-dynamic-import",
    "transform-object-rest-spread",
    "transform-class-properties"
  ]
}

.babelignore

Similar to a .gitignore, this lists files that should not be babelified. You'll notice that we don't run babel on the root application.js file in assets/javascripts so that the comments are preserved and the traditional asset pipeline works as expected

node_modules
vendor/assets/
app/assets/javascripts/application.js # to save traditional rails asset pipeline!

.eslintrc

This is a well-informed, yet opinionated set of eslint style guides that I chose to employ. If you hate trailing commas or like airbnb's guide better that is your perogative.

{
  "extends": [
    "plugin:react/recommended",
    "prettier",
    "prettier/react"
  ],
  "parser": "babel-eslint",
  "plugins": [
    "react",
    "prettier"
  ],
  "env": {
    "es6": true,
    "node": true
  },
  "rules": {
    "prettier/prettier": ["error", {"trailingComma": "es5"}]
  }
}

.eslintignore

This ignores files from the linting process. As noted, I chose to ignore the traditional assets by default. If you can address your existing codebase you certainly should!

node_modules
vendor/assets/
app/assets/javascripts # depending on your threshold to deal with the problem now or not

Gemfile

...
gem 'browserify-rails', '~> 4.2.0'

application.rb

...
config.browserify_rails.commandline_options = "--extension=\".js\" --extension=\".jsx\" --extension=\".js.jsx\" -t [babelify]"

application.js

...
require('../entry_points/BigPicture');

app/views/scheduling/big_picture.html.erb

<div class="row">
  <div id="big-picture"></div> # unique elementId for ReactDOM to target
</div>

assets/entry_points/bigPicture.js (sample)

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import bigPictureStore from "../stores/bigPictureStore";
import BigPicturePageContainer from "../containers/BigPicturePageContainer";

document.addEventListener("DOMContentLoaded", function() {
  const rootElement = document.getElementById("big-picture");
  if (rootElement !== null) {
    ReactDOM.render(
      <Provider store={bigPictureStore}>
        <BigPicturePageContainer />
      </Provider>,
      rootElement
    );
  }
});

assets/stores/bigPictureStore.js (sample)

import { createStore, applyMiddleware } from "redux";
import thunkMiddleware from "redux-thunk";
import rootReducer from "../reducers/bigPicture";

export default createStore(
  rootReducer,
  applyMiddleware(thunkMiddleware)
);

Then place reducers, components and containers inside of the /assets folder as you would for any create-react-app like app!

@danielpowell4

This comment has been minimized.

Copy link
Owner Author

@danielpowell4 danielpowell4 commented Oct 9, 2017

If you can get onto webpacker, that is certainly a better option for apps running Rails 4.2+

If you're realistically on an app that's been around the block and has a good deal of JS inside of the traditional Rails asset pipeline like many of us, however, this is the way to do it to use modern ES syntax and have a grand time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment