react_on_rails 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +182 -56
  3. data/{LICENSE → docs/LICENSE} +0 -0
  4. data/docs/{gen-notes/reducers.md → additional_reading/generated_client_code.md} +5 -1
  5. data/docs/additional_reading/heroku_deployment.md +21 -0
  6. data/docs/{manual_configuration.md → additional_reading/manual_installation.md} +4 -63
  7. data/docs/{node_dependencies_and_npm.md → additional_reading/node_dependencies_and_npm.md} +0 -0
  8. data/docs/additional_reading/optional_configuration.md +34 -0
  9. data/docs/additional_reading/server_rendering_tips.md +16 -0
  10. data/docs/additional_reading/tips.md +10 -0
  11. data/{CODE_OF_CONDUCT.md → docs/code_of_conduct.md} +0 -0
  12. data/docs/{Contributing.md → contributing.md} +0 -0
  13. data/lib/generators/react_on_rails/base_generator.rb +35 -4
  14. data/lib/generators/react_on_rails/bootstrap_generator.rb +27 -7
  15. data/lib/generators/react_on_rails/generator_helper.rb +4 -2
  16. data/lib/generators/react_on_rails/install_generator.rb +13 -19
  17. data/lib/generators/react_on_rails/js_linters_generator.rb +19 -0
  18. data/lib/generators/react_on_rails/react_no_redux_generator.rb +7 -3
  19. data/lib/generators/react_on_rails/react_with_redux_generator.rb +6 -15
  20. data/lib/generators/react_on_rails/ruby_linters_generator.rb +33 -0
  21. data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/startup/globals.jsx.tt +5 -0
  22. data/lib/generators/react_on_rails/templates/{redux → base}/base/client/package.json.tt +23 -10
  23. data/lib/generators/react_on_rails/templates/base/base/client/server.js +8 -2
  24. data/lib/generators/react_on_rails/templates/base/base/client/{webpack.client.base.config.js → webpack.client.base.config.js.tt} +2 -1
  25. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +1 -3
  26. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/assets.rake +1 -3
  27. data/lib/generators/react_on_rails/templates/{linters/lib/tasks/linters.rake → base/base/lib/tasks/linters.rake.tt} +36 -29
  28. data/lib/generators/react_on_rails/templates/{linters → js_linters}/client/.eslintignore +0 -0
  29. data/lib/generators/react_on_rails/templates/{linters → js_linters}/client/.eslintrc +0 -0
  30. data/lib/generators/react_on_rails/templates/{linters → js_linters}/client/.jscsrc +0 -0
  31. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx.tt +12 -0
  32. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/index.jsx +2 -2
  33. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/{HelloWorldAppClient.jsx → HelloWorldAppClient.jsx.tt} +3 -2
  34. data/lib/generators/react_on_rails/templates/redux/base/client/app/lib/middlewares/loggerMiddleware.js +1 -5
  35. data/lib/generators/react_on_rails/templates/ruby_linters/.rubocop.yml +26 -0
  36. data/lib/generators/react_on_rails/templates/ruby_linters/.scss-lint.yml +205 -0
  37. data/lib/generators/react_on_rails/templates/{linters → ruby_linters}/lib/tasks/brakeman.rake +0 -0
  38. data/lib/generators/react_on_rails/templates/{linters → ruby_linters}/lib/tasks/ci.rake +0 -0
  39. data/lib/generators/react_on_rails/templates/ruby_linters/ruby-lint.yml +20 -0
  40. data/lib/react_on_rails/version.rb +1 -1
  41. metadata +29 -24
  42. data/docs/gen-notes/react_syntax.md +0 -3
  43. data/docs/linters.md +0 -25
  44. data/lib/generators/react_on_rails/linters_generator.rb +0 -38
  45. data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/startup/clientGlobals.jsx +0 -4
  46. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx +0 -11
  47. data/lib/generators/react_on_rails/templates/no_redux/base/client/package.json.tt +0 -75
@@ -0,0 +1,34 @@
1
+ # Optional Configuration
2
+
3
+ Create a file `config/react_on_rails.rb` to override any defaults (this file is automatically created for you when using the generator). If you don't specify this file, the default options are below.
4
+
5
+ The `server_bundle_js_file` must correspond to the bundle you want to use for server rendering.
6
+
7
+ ```ruby
8
+ # Shown below are the defaults for configuration
9
+ ReactOnRails.configure do |config|
10
+ # Client bundles are configured in application.js
11
+ # Server bundle is a single file for all server rendering of components.
12
+ # Set the server_bundle_js_file to "" if you know that you will not be server rendering.
13
+ config.server_bundle_js_file = "app/assets/javascripts/generated/server.js" # This is the default
14
+
15
+ # Below options can be overriden by passing to the helper method.
16
+ config.prerender = false # default is false
17
+ config.generator_function = false # default is false, meaning that you expose ReactComponents directly
18
+ config.trace = Rails.env.development? # default is true for development, off otherwise
19
+
20
+ # For server rendering. This can be set to false so that server side messages are discarded.
21
+ config.replay_console = true # Default is true. Be cautious about turning this off.
22
+ config.logging_on_server = true # Default is true. Logs server rendering messags to Rails.logger.info
23
+
24
+ # Settings for the pool of renderers:
25
+ config.server_renderer_pool_size ||= 1 # ExecJS doesn't allow more than one on MRI
26
+ config.server_renderer_timeout ||= 20 # seconds
27
+ end
28
+ ```
29
+
30
+ You can configure your pool of JS virtual machines and specify where it should load code:
31
+
32
+ - On MRI, use `therubyracer` for the best performance (see [discussion](https://github.com/reactjs/react-rails/pull/290))
33
+ - On MRI, you'll get a deadlock with `pool_size` > 1
34
+ - If you're using JRuby, you can increase `pool_size` to have real multi-threaded rendering.
@@ -0,0 +1,16 @@
1
+ # Server Rendering Tips
2
+
3
+ - Your code can't reference `document`. Server side JS execution does not have access to `document`, so jQuery and some
4
+ other libs won't work in this environment. You can debug this by putting in `console.log`
5
+ statements in your code.
6
+ - You can conditionally avoid running code that references document by passing in a boolean prop to your top level react
7
+ component. Since the passed in props Hash from the view helper applies to client and server side code, the best way to
8
+ do this is to use a generator function.
9
+ - If you're serious about server rendering, it's worth the effort to have different entry points for client and server rendering. It's worth the extra complexity.
10
+
11
+ You might also do something like this in some file for your top level component:
12
+ ```javascript
13
+ global.App = () => <MyComponent serverSide={true} />;
14
+ ```
15
+
16
+ The point is that you have separate files for top level client or server side, and you pass some extra option indicating that rendering is happening server sie.
@@ -0,0 +1,10 @@
1
+ # Tips
2
+ + **DO NOT RUN `rails s`** and instead run
3
+
4
+ `foreman start -f Procfile.dev`
5
+
6
+ to automatically start the webpack file watchers that will regenerate your JavaScript. Note, RSpec does not automatically rebuild the bundle files, so you could get incorrect results from your tests if you change the client code and do not rebuild the bundles. The same problem occurs when pulling down changes from GitHub and running tests without first rebuilding the bundles.
7
+ + The default for rendering right now is `prerender: false`. **NOTE:** Server side rendering does not work for some components that use an async setup for server rendering. You can configure the default for prerender in your config.
8
+ + You can expose either a React component or a function that returns a React component. If you wish to create a React component via a function, rather than simply props, then you need to set the property "generator" on that helper invocation to true (or change the defaults). When that is done, the function is invoked with a single parameter of "props", and that function should return a React element.
9
+ + Be sure you can first render your react component **client only** before you try to debug server rendering!
10
+ + Open up the HTML source and take a look at the generated HTML and the JavaScript to see what's going on under the covers. Note that when server rendering is turned on, then you'll see the server rendered react components. When server rendering is turned off, then you'll only see the `div` element where the in-line JavaScript will render the component. You might also notice how the props you pass (a Ruby Hash) becomes in-line JavaScript on the HTML page.
@@ -8,12 +8,30 @@ module ReactOnRails
8
8
  hide!
9
9
  source_root(File.expand_path("../templates", __FILE__))
10
10
 
11
+ # --redux
12
+ class_option :redux,
13
+ type: :boolean,
14
+ default: false,
15
+ desc: "Install Redux gems and Redux version of Hello World Example",
16
+ aliases: "-R"
11
17
  # --server-rendering
12
18
  class_option :server_rendering,
13
19
  type: :boolean,
14
20
  default: false,
15
21
  desc: "Configure for server-side rendering of webpack JavaScript",
16
22
  aliases: "-S"
23
+ # --skip-js-linters
24
+ class_option :skip_js_linters,
25
+ type: :boolean,
26
+ default: false,
27
+ desc: "Skip installing JavaScript linting files",
28
+ aliases: "-j"
29
+ # --ruby-linters
30
+ class_option :ruby_linters,
31
+ type: :boolean,
32
+ default: false,
33
+ desc: "Install ruby linting files, tasks, and configs",
34
+ aliases: "-L"
17
35
 
18
36
  def add_hello_world_route
19
37
  route "get 'hello_world', to: 'hello_world#index'"
@@ -89,10 +107,8 @@ module ReactOnRails
89
107
  client/index.jade
90
108
  client/npm-shrinkwrap.json
91
109
  client/server.js
92
- client/webpack.client.base.config.js
93
110
  client/webpack.client.hot.config.js
94
111
  client/webpack.client.rails.config.js
95
- client/app/bundles/HelloWorld/startup/clientGlobals.jsx
96
112
  lib/tasks/assets.rake
97
113
  REACT_ON_RAILS.md
98
114
  client/REACT_ON_RAILS_CLIENT_README.md
@@ -102,14 +118,29 @@ module ReactOnRails
102
118
  def template_base_files
103
119
  base_path = "base/base/"
104
120
  %w(Procfile.dev
105
- app/views/hello_world/index.html.erb).each { |file| template(base_path + file + ".tt", file) }
121
+ app/views/hello_world/index.html.erb
122
+ client/webpack.client.base.config.js
123
+ client/package.json).each { |file| template(base_path + file + ".tt", file) }
124
+ end
125
+
126
+ def template_client_globals_file
127
+ filename = options.server_rendering? ? "clientGlobals.jsx" : "globals.jsx"
128
+ location = "client/app/bundles/HelloWorld/startup"
129
+ template("base/base/#{location}/globals.jsx.tt", "#{location}/#{filename}")
106
130
  end
107
131
 
108
132
  def install_server_rendering_files_if_enabled
109
133
  return unless options.server_rendering?
110
134
  base_path = "base/server_rendering/"
111
135
  %w(client/webpack.server.rails.config.js
112
- client/app/bundles/HelloWorld/startup/serverGlobals.jsx).each { |file| copy_file(base_path + file, file) }
136
+ client/app/bundles/HelloWorld/startup/serverGlobals.jsx).each do |file|
137
+ copy_file(base_path + file, file)
138
+ end
139
+ end
140
+
141
+ def template_linter_files_if_appropriate
142
+ return if !options.ruby_linters? && options.skip_js_linters?
143
+ template("base/base/lib/tasks/linters.rake.tt", "lib/tasks/linters.rake")
113
144
  end
114
145
  end
115
146
  end
@@ -32,11 +32,24 @@ module ReactOnRails
32
32
  client/bootstrap-sass.config.js).each { |file| copy_file(base_path + file, file) }
33
33
  end
34
34
 
35
- def change_application_css_to_scss_if_necessary
36
- stylesheets_path = File.join(destination_root, "app/assets/stylesheets")
37
- application_css = File.join(stylesheets_path, "application.css")
38
- return unless File.exist?(application_css)
39
- File.rename(application_css, File.join(stylesheets_path, "application.css.scss"))
35
+ # rename to application.scss from application.css or application.css.scss
36
+ def force_application_scss_naming_if_necessary
37
+ base_path = "app/assets/stylesheets/"
38
+ application_css = "#{base_path}application.css"
39
+ application_css_scss = "#{base_path}application.css.scss"
40
+
41
+ bad_name = dest_file_exists?(application_css) || dest_file_exists?(application_css_scss)
42
+ return unless bad_name
43
+
44
+ new_name = File.join(destination_root, "#{base_path}application.scss")
45
+ File.rename(bad_name, new_name)
46
+ end
47
+
48
+ # if there still is not application.scss, just create one
49
+ def create_application_scss_if_necessary
50
+ path = File.join(destination_root, "app/assets/stylesheets/application.scss")
51
+ return if File.exist?(path)
52
+ File.open(path, "w") { |f| f.puts "// Created by React on Rails gem\n\n" }
40
53
  end
41
54
 
42
55
  def prepend_to_application_scss
@@ -63,11 +76,18 @@ module ReactOnRails
63
76
  @import 'post-bootstrap';
64
77
 
65
78
  DATA
66
- append_to_file("app/assets/stylesheets/application.css.scss", data)
79
+
80
+ application_scss = File.join(destination_root, "app/assets/stylesheets/application.scss")
81
+
82
+ if File.exist?(application_scss)
83
+ append_to_file(application_scss, data)
84
+ else
85
+ puts_setup_file_error(application_scss, data)
86
+ end
67
87
  end
68
88
 
69
89
  def strip_application_scss_of_incompatible_sprockets_statements
70
- application_scss = File.join(destination_root, "app/assets/stylesheets/application.css.scss")
90
+ application_scss = File.join(destination_root, "app/assets/stylesheets/application.scss")
71
91
  gsub_file(application_scss, "*= require_tree .", "")
72
92
  gsub_file(application_scss, "*= require_self", "")
73
93
  end
@@ -1,11 +1,13 @@
1
1
  module GeneratorHelper
2
2
  # Takes a relative path from the destination root, such as `.gitignore` or `app/assets/javascripts/application.js`
3
3
  def dest_file_exists?(file)
4
- File.exist?(File.join(destination_root, file)) ? file : nil
4
+ dest_file = File.join(destination_root, file)
5
+ File.exist?(dest_file) ? dest_file : nil
5
6
  end
6
7
 
7
8
  def dest_dir_exists?(dir)
8
- Dir.exist?(File.join(destination_root, dir)) ? dir : nil
9
+ dest_dir = File.join(destination_root, dir)
10
+ Dir.exist?(dest_dir) ? dest_dir : nil
9
11
  end
10
12
 
11
13
  # Takes the missing file and the
@@ -1,16 +1,3 @@
1
- # Install Generator: gem's only public generator
2
- #
3
- # Usage:
4
- # rails generate react_on_rails:install [options]
5
- #
6
- # Options:
7
- # [--redux], [--no-redux]
8
- # Indicates when to generate with redux
9
- # [--server-rendering], [--no-server-rendering]
10
- # Indicates whether ability for server-side rendering of webpack output should be enabled
11
- # [--skip-linters]
12
- # Indicates whether linter files and configs should be installed
13
- #
14
1
  require "rails/generators"
15
2
 
16
3
  module ReactOnRails
@@ -20,19 +7,25 @@ module ReactOnRails
20
7
  class_option :redux,
21
8
  type: :boolean,
22
9
  default: false,
23
- desc: "Setup Redux files",
10
+ desc: "Install Redux gems and Redux version of Hello World Example",
24
11
  aliases: "-R"
25
12
  # --server-rendering
26
13
  class_option :server_rendering,
27
14
  type: :boolean,
28
15
  default: false,
29
- desc: "Configure for server-side rendering of webpack JavaScript",
16
+ desc: "Add necessary files and configurations for server-side rendering",
30
17
  aliases: "-S"
31
- # --linters
32
- class_option :linters,
18
+ # --skip-js-linters
19
+ class_option :skip_js_linters,
33
20
  type: :boolean,
34
21
  default: false,
35
- desc: "Install linter files",
22
+ desc: "Skip installing JavaScript linting files",
23
+ aliases: "-j"
24
+ # --ruby-linters
25
+ class_option :ruby_linters,
26
+ type: :boolean,
27
+ default: false,
28
+ desc: "Install ruby linting files, tasks, and configs",
36
29
  aliases: "-L"
37
30
 
38
31
  def run_generators
@@ -41,7 +34,8 @@ module ReactOnRails
41
34
  invoke "react_on_rails:base"
42
35
  invoke "react_on_rails:react_no_redux" unless options.redux?
43
36
  invoke "react_on_rails:react_with_redux" if options.redux?
44
- invoke "react_on_rails:linters" if options.linters?
37
+ invoke "react_on_rails:js_linters" unless options.skip_js_linters?
38
+ invoke "react_on_rails:ruby_linters" if options.ruby_linters?
45
39
  invoke "react_on_rails:bootstrap"
46
40
  invoke "react_on_rails:heroku_deployment"
47
41
  end
@@ -0,0 +1,19 @@
1
+ require "rails/generators"
2
+
3
+ module ReactOnRails
4
+ module Generators
5
+ class JsLintersGenerator < Rails::Generators::Base
6
+ hide!
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ # NOTE: linter modules are included via template in base/base/client/package.json.tt
10
+
11
+ def copy_js_linter_config_files
12
+ base_path = "js_linters/"
13
+ %w(client/.eslintrc
14
+ client/.eslintignore
15
+ client/.jscsrc).each { |file| copy_file(base_path + file, file) }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -18,11 +18,9 @@ module ReactOnRails
18
18
  def copy_base_files
19
19
  base_path = "no_redux/base/"
20
20
  %w(client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx
21
- client/app/bundles/HelloWorld/containers/HelloWorld.jsx
22
- client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx).each do |file|
21
+ client/app/bundles/HelloWorld/containers/HelloWorld.jsx).each do |file|
23
22
  copy_file(base_path + file, file)
24
23
  end
25
- template("#{base_path}client/package.json", "client/package.json")
26
24
  end
27
25
 
28
26
  def copy_server_rendering_files_if_appropriate
@@ -32,6 +30,12 @@ module ReactOnRails
32
30
  copy_file(base_path + file, file)
33
31
  end
34
32
  end
33
+
34
+ def template_appropriate_version_of_hello_world_app_client
35
+ filename = options.server_rendering? ? "HelloWorldAppClient.jsx" : "HelloWorldApp.jsx"
36
+ location = "client/app/bundles/HelloWorld/startup"
37
+ template("no_redux/base/#{location}/HelloWorldAppClient.jsx.tt", "#{location}/#{filename}")
38
+ end
35
39
  end
36
40
  end
37
41
  end
@@ -1,16 +1,3 @@
1
- # Install Generator: gem's only public generator
2
- #
3
- # Usage:
4
- # rails generate react_on_rails:install [options]
5
- #
6
- # Options:
7
- # [--redux], [--no-redux]
8
- # Indicates when to generate with redux
9
- # [--hello-world-example], [--no-hello-world-example]
10
- # Indicates when to generate with hello world example
11
- # [--server-rendering], [--no-server-rendering]
12
- # Indicates whether ability for server-side rendering of webpack output should be enabled
13
- #
14
1
  require "rails/generators"
15
2
 
16
3
  module ReactOnRails
@@ -41,12 +28,10 @@ module ReactOnRails
41
28
  client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx
42
29
  client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx
43
30
  client/app/bundles/HelloWorld/reducers/index.jsx
44
- client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx
45
31
  client/app/bundles/HelloWorld/store/helloWorldStore.jsx
46
32
  client/app/lib/middlewares/loggerMiddleware.js).each do |file|
47
33
  copy_file(base_path + file, file)
48
34
  end
49
- template("#{base_path}client/package.json", "client/package.json")
50
35
  end
51
36
 
52
37
  def copy_server_rendering_redux_files
@@ -56,6 +41,12 @@ module ReactOnRails
56
41
  copy_file(base_path + file, file)
57
42
  end
58
43
  end
44
+
45
+ def template_appropriate_version_of_hello_world_app_client
46
+ filename = options.server_rendering? ? "HelloWorldAppClient.jsx" : "HelloWorldApp.jsx"
47
+ location = "client/app/bundles/HelloWorld/startup"
48
+ template("redux/base/#{location}/HelloWorldAppClient.jsx.tt", "#{location}/#{filename}")
49
+ end
59
50
  end
60
51
  end
61
52
  end
@@ -0,0 +1,33 @@
1
+ require "rails/generators"
2
+
3
+ module ReactOnRails
4
+ module Generators
5
+ class RubyLintersGenerator < Rails::Generators::Base
6
+ hide!
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ def add_ruby_linter_gems_to_gemfile
10
+ linter_gems = <<-GEMS.strip_heredoc
11
+
12
+ # require: false is necessary for the linters as we only want them loaded
13
+ # when used by the linting rake tasks.
14
+ group :development do
15
+ gem("rubocop", require: false)
16
+ gem("ruby-lint", require: false)
17
+ gem("scss_lint", require: false)
18
+ end
19
+ GEMS
20
+ append_to_file("Gemfile", linter_gems)
21
+ end
22
+
23
+ def copy_ruby_linting_and_auditing_tasks
24
+ base_path = "ruby_linters/"
25
+ %w(lib/tasks/brakeman.rake
26
+ lib/tasks/ci.rake
27
+ .rubocop.yml
28
+ .scss-lint.yml
29
+ ruby-lint.yml).each { |file| copy_file(base_path + file, file) }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ <%- component_name = options.server_rendering? ? "HelloWorldAppClient" : "HelloWorldApp" -%>
2
+ import <%= component_name %> from './<%= component_name %>';
3
+
4
+ // This is how react_on_rails can see the HelloWorldApp in the browser.
5
+ window.HelloWorldApp = <%= component_name %>;
@@ -29,49 +29,62 @@
29
29
  "build:client": "NODE_ENV=production webpack --config webpack.client.rails.config.js",
30
30
  "build:server": "NODE_ENV=production webpack --config webpack.server.rails.config.js",
31
31
  "build:dev:client": "webpack -w --config webpack.client.rails.config.js",
32
- "build:dev:server": "webpack -w --config webpack.server.rails.config.js",<%- if options.linters? %>
32
+ "build:dev:server": "webpack -w --config webpack.server.rails.config.js"<% unless options.skip_js_linters? -%>,
33
33
  "lint": "npm run eslint && npm run jscs",
34
34
  "eslint": "eslint --ext .js,.jsx .",
35
- "jscs": "jscs --verbose ."<%- end %>
35
+ "jscs": "jscs --verbose ."
36
+ <%- end -%>
36
37
  },
37
38
  "dependencies": {
38
39
  "babel-core": "^5.8.25",
39
40
  "babel-loader": "^5.3.2",
40
- "body-parser": "^1.14.1",
41
41
  "es5-shim": "^4.1.14",
42
42
  "es6-promise": "^3.0.2",
43
43
  "expose-loader": "^0.7.0",
44
+ <%- if options.redux? -%>
44
45
  "immutable": "^3.7.5",
46
+ <%- end -%>
45
47
  "imports-loader": "^0.6.4",
46
48
  "jquery": "^2.1.4",
47
49
  "jquery-ujs": "^1.1.0-1",
50
+ <%- if options.redux? -%>
48
51
  "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
52
+ <%- end -%>
49
53
  "loader-utils": "^0.2.11",
54
+ <%- if options.redux? -%>
50
55
  "mirror-creator": "0.0.1",
56
+ <%- end -%>
51
57
  "react": "^0.14.0",
52
58
  "react-bootstrap": "^0.27.0",
53
59
  "react-dom": "^0.14.0",
60
+ <%- if options.redux? -%>
54
61
  "react-redux": "^3.1.0",
55
62
  "redux": "^3.0.2",
56
63
  "redux-promise": "^0.5.0",
57
64
  "redux-thunk": "^1.0.0",
58
- "sleep": "^3.0.0",
65
+ <%- end -%>
59
66
  "webpack": "^1.12.2"
60
67
  },
61
- "devDependencies": {<%- if options.linters? %>
62
- "babel-eslint": "^4.1.3",<%- end %>
68
+ "devDependencies": {
69
+ <%- unless options.skip_js_linters? -%>
70
+ "babel-eslint": "^4.1.3",
71
+ <%- end -%>
63
72
  "babel-plugin-react-transform": "^1.1.1",
64
73
  "bootstrap-sass": "^3.3.5",
65
74
  "bootstrap-sass-loader": "^1.0.9",
66
- "css-loader": "^0.19.0",<%- if options.linters? %>
75
+ "css-loader": "^0.19.0",
76
+ <%- unless options.skip_js_linters? -%>
67
77
  "eslint": "^1.6.0",
68
78
  "eslint-config-airbnb": "0.1.0",
69
- "eslint-plugin-react": "^3.5.1",<%- end %>
79
+ "eslint-plugin-react": "^3.5.1",
80
+ <%- end -%>
70
81
  "esprima-fb": "^15001.1001.0-dev-harmony-fb",
71
82
  "express": "^4.13.3",
72
83
  "file-loader": "^0.8.4",
73
- "jade": "^1.11.0",<%- if options.linters? %>
74
- "jscs": "^2.3.0",<%- end %>
84
+ "jade": "^1.11.0",
85
+ <%- unless options.skip_js_linters? -%>
86
+ "jscs": "^2.3.0",
87
+ <%- end -%>
75
88
  "node-sass": "^3.3.3",
76
89
  "react-transform-hmr": "^1.0.1",
77
90
  "sass-loader": "^3.0.0",