diff --git a/README.md b/README.md index 32a3d3e7..3355843a 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,14 @@ As with all gem dependencies, we strongly recommend adding `react-rails` to your ```ruby # Gemfile -gem 'react-rails', '~> 0.8.0.0' +gem 'react-rails', '~> 1.0.0' ``` - ## Usage ### react.js -In order to use React client-side in your application, you must make sure the browser requests it. One way to do that is to drop `react.js` into `app/assets/javascript/` and by default your application manifest will pick it up. There are downsides to this approach, so we made it even easier. Once you have `react-rails` installed, you can just add a line into your config file (see Configuring) and require react directly in your manifest: +In order to use React client-side in your application, you must make sure the browser requests it. One way to do that is to drop `react.js` into `vendor/assets/javascript/` and by default your application manifest will pick it up. There are downsides to this approach, so we made it even easier. Once you have `react-rails` installed, you can just add a line into your config file (see Configuring) and require react directly in your manifest: You can `require` it in your manifest: @@ -129,3 +128,20 @@ Component = React.createClass `` ``` +### Changing react.js and JSXTransformer.js versions + +In some cases you may want to have your `react.js` and `JSXTransformer.js` files come from a different release than the one, that is specified in the `react-rails.gemspec`. To achieve that, you have to manually replace them in your app. + +#### Instructions + +Just put another version of `react.js` or `JSXTransformer.js` under `/vendor/assets/react` directory. +If you need different versions of `react.js` for production and development, then use a subdirectory named +after `config.react.variant`, e.g. you set `config.react.variant = :development` so for this environment +`react.js` is expected to be in `/vendor/assets/react/development` + +#### Things to remember + +If you replace `JSXTransformer.js` in production environment, you have to restart your rails instance, +because the jsx compiler context is cached. + +Name of the `JSXTransformer.js` file *is case-sensitive*. diff --git a/lib/react/jsx.rb b/lib/react/jsx.rb index c9cfa24c..f58d00a3 100644 --- a/lib/react/jsx.rb +++ b/lib/react/jsx.rb @@ -1,17 +1,26 @@ require 'execjs' require 'react/source' require 'react/jsx/template' +require 'rails' module React module JSX def self.context - # TODO: create React::Source::contents_for - contents = - # If execjs uses therubyracer, there is no 'global'. Make sure - # we have it so JSX script can work properly. - 'var global = global || this;' + - File.read(React::Source.bundled_path_for('JSXTransformer.js')) - @context ||= ExecJS.compile(contents) + # lazily loaded during first request and reloaded every time when in dev or test + unless @context && ::Rails.env.production? + contents = + # If execjs uses therubyracer, there is no 'global'. Make sure + # we have it so JSX script can work properly. + 'var global = global || this;' + + + # search for transformer file using sprockets - allows user to override + # this file in his own application + File.read(::Rails.application.assets.resolve('JSXTransformer.js')) + + @context = ExecJS.compile(contents) + end + + @context end def self.transform(code) diff --git a/lib/react/jsx/template.rb b/lib/react/jsx/template.rb index 3118b5fb..18316748 100644 --- a/lib/react/jsx/template.rb +++ b/lib/react/jsx/template.rb @@ -9,7 +9,7 @@ class Template < Tilt::Template def prepare end - def evaluate(scopre, locals, &block) + def evaluate(scope, locals, &block) @output ||= JSX::transform(data) end end diff --git a/lib/react/rails/engine.rb b/lib/react/rails/engine.rb index c6afcc8f..7af1f8c5 100644 --- a/lib/react/rails/engine.rb +++ b/lib/react/rails/engine.rb @@ -1,7 +1,7 @@ module React module Rails class Engine < ::Rails::Engine - initializer "react_rails.setup_engine", :after => "sprockets.environment", :group => :all do |app| + initializer "react_rails.setup_engine", :group => :all do |app| app.assets.register_engine '.jsx', React::JSX::Template end end diff --git a/lib/react/rails/railtie.rb b/lib/react/rails/railtie.rb index e29ff92c..3dfbf5af 100644 --- a/lib/react/rails/railtie.rb +++ b/lib/react/rails/railtie.rb @@ -5,9 +5,9 @@ module Rails class Railtie < ::Rails::Railtie config.react = ActiveSupport::OrderedOptions.new - initializer "react_rails.setup_vendor", :after => "sprockets.environment" do |app| - variant = app.config.react.variant - + # run after all initializers to allow sprockets to pick up react.js and + # jsxtransformer.js from end-user to override ours if needed + config.after_initialize do |app| # Mimic behavior of ember-rails... # We want to include different files in dev/prod. The unminified builds # contain console logging for invariants and logging to help catch @@ -26,9 +26,17 @@ class Railtie < ::Rails::Railtie tmp_path.join('react.js')) FileUtils.cp(::React::Source.bundled_path_for('JSXTransformer.js'), tmp_path.join('JSXTransformer.js')) + app.assets.prepend_path tmp_path + + # Allow overriding react files that are not based on environment + # e.g. /vendor/assets/react/JSXTransformer.js + dropin_path = app.root.join("vendor/assets/react") + app.assets.prepend_path dropin_path if dropin_path.exist? - # Make sure it can be found - app.assets.append_path(tmp_path) + # Allow overriding react files that are based on environment + # e.g. /vendor/assets/react/react.js + dropin_path_env = app.root.join("vendor/assets/react/#{variant}") + app.assets.prepend_path dropin_path_env if dropin_path_env.exist? end end end diff --git a/lib/react/rails/version.rb b/lib/react/rails/version.rb index 80f4182f..1c1ffc40 100644 --- a/lib/react/rails/version.rb +++ b/lib/react/rails/version.rb @@ -2,7 +2,6 @@ module React module Rails # Version numbers will track react-source, but we'll add another level so # that we can increment, but have some amount of stability. - VERSION = '0.8.0.0' + VERSION = '1.0.0.beta1' end end - diff --git a/test/dummy/app/assets/javascripts/example3.js.jsx b/test/dummy/app/assets/javascripts/example3.js.jsx new file mode 100644 index 00000000..2611211a --- /dev/null +++ b/test/dummy/app/assets/javascripts/example3.js.jsx @@ -0,0 +1,2 @@ +/** @jsx React.DOM */ +
; diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb index afbc0ae7..cff2ea78 100644 --- a/test/dummy/config/environments/test.rb +++ b/test/dummy/config/environments/test.rb @@ -5,7 +5,11 @@ # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true + + # we need this to reload the jsx transformer when different version is dropped in + config.cache_classes = false + config.reload_plugins = true + config.assets.cache_store = :null_store # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that @@ -33,4 +37,6 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr + + config.react.variant = :test end diff --git a/test/dummy/vendor/assets/react/JSXTransformer__.js b/test/dummy/vendor/assets/react/JSXTransformer__.js new file mode 100644 index 00000000..3eba809e --- /dev/null +++ b/test/dummy/vendor/assets/react/JSXTransformer__.js @@ -0,0 +1,7 @@ +var JSXTransformer = { + transform: function () { + return { + code: 'test_confirmation_token_jsx_transformed;' + }; + } +}; diff --git a/test/dummy/vendor/assets/react/test/react__.js b/test/dummy/vendor/assets/react/test/react__.js new file mode 100644 index 00000000..0860b7de --- /dev/null +++ b/test/dummy/vendor/assets/react/test/react__.js @@ -0,0 +1 @@ +'test_confirmation_token_react_content'; \ No newline at end of file diff --git a/test/jsxtransform_test.rb b/test/jsxtransform_test.rb index 973344aa..7a9a820a 100644 --- a/test/jsxtransform_test.rb +++ b/test/jsxtransform_test.rb @@ -1,6 +1,7 @@ require 'test_helper' +require 'fileutils' -# The transformer is inserting a newline after the docblock for some reason... +# Sprockets is inserting a newline after the docblock for some reason... EXPECTED_JS = <