Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Browserify + Rails = a great way to modularize your legacy JavaScript

License

NotificationsYou must be signed in to change notification settings

browserify-rails/browserify-rails

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This project is currently in maintenance mode. New contributors are more than welcome!

Gem Version

This library adds CommonJS module support to Sprockets (via Browserify).

It lets you mix and match//= require directives andrequire() calls for including plain javascript files as well as modules. However, it is important to remember that once you are into code that is being browserified you can no longer use sprockets-style require (so no//= require). In many cases, it makes sense to put all your sprockets-required code in a separate file or at the very least at the top of your main JavaScript file. Then userequire() to pull in the CommonJS code.

  1. Manage JS modules withnpm
  2. Serve assets with Sprockets
  3. Require modules withrequire() (without separate//= require directives)
  4. Only build required modules
  5. Requirenpm modules in your Rails assets
  6. Require modules relative to asset paths (ie app/assets/javascript) with non-relative syntax (see below before using)
  7. Configure browserify options for each JavaScript file so you can mark modules with--require,--external, etc

Should you use this gem?

As the primary developer, I'm going to offer some opiniated advice. The sweet spot for thisgem is for Rails projects with legacy JavaScript (not using CommonJS/modules). This gem isa great way to make it possible to rewrite that legacy JavaScript to CommonJS on a timelinethat you dictate. Then consider stepping off the Rails asset pipeline or using another gem.

If you're starting a new Rails project today, I highly recommend looking at alternatives tothis gem. The primary reason is that this gem, while it works well, is not as efficient asmost would like for local development. Also a lot has changed over the last couple of years.

An example of that change is this project from Rails:

rails/webpacker

This is a huge step in the right direction for the Rails community. In the past, it has beenextremely frustrating working with JavaScript on the asset pipeline. The good news is you have a lotof great choices. If I were starting a new Rails project today, I think the safest choice isone in which you have aProcfile that kicks off a separate Webpack build and you use zeroRails magic. A slightly less safe but maybe more convenient choice would be trying rails/webpackeror another gem. The choice is yours.

For more discussion on this topic, see issues203,161,43, etc.

Getting Started

Add this line to your application's Gemfile:

gem "browserify-rails"

Createpackage.json in your Rails root:

{"name":"something","dependencies" :{"browserify":"^14.0.0","browserify-incremental":"^3.1.0"},"license":"MIT","engines":{"node":">= 0.10"}}

Then run:

npm install

Then start writing CommonJS, and everything will magically work!:

// foo.jsmodule.exports=function(n){returnn*11}// application.jsvarfoo=require('./foo');console.log(foo(12));

Gotchas withrequire andmodule.exports

Do not putmodule.exports orrequire() in JavaScript comments or strings.Doing so will certainly cause issues with compilation that are difficult totrack down.

This happens because browserify-rails works by parsing your JavaScript files forthese keywords that indicate whether it is a module, or is requiring a module.If a file meets one of these criteria, browserify will compile the modules asexpected.

Because browserify-rails is working within the restraints of Ruby/Sprockets, theparsing is done by Ruby and therefore does not know whether it is a JavaScriptstring, comment, or function.

CoffeeScript

For CoffeeScript support, make sure to follow the standard rails.js.coffee naming convention. You'll also need to add the npmpackagecoffeeify as a dependency:

{// ..."dependencies" :{// ..."coffeeify":"~0.6"}}

and configurebrowserify_rails accordingly:

config.browserify_rails.commandline_options="-t coffeeify --extension=\".js.coffee\""

Requirements

  • node-browserify 4.x
  • browserify-incremental

Configuration

Global configuration

You can configure different options of browserify-rails by adding one of the linesmentioned below into yourconfig/application.rb or your environment file(config/environments/*.rb):

classMy::Application <Rails::Application# Specify the file paths that should be browserified. We browserify everything that# matches (===) one of the paths. So you will most likely put lambdas# regexes in here.## By default only files in /app and /node_modules are browserified,# vendor stuff is normally not made for browserification and may stop# working.config.browserify_rails.paths <</vendor\/assets\/javascripts\/module\.js/# Environments in which to generate source maps## The default is noneconfig.browserify_rails.source_map_environments <<"development"# Should the node_modules directory be evaluated for changes on page load## The default is `false`config.browserify_rails.evaluate_node_modules=true# Force browserify on every found JavaScript asset if true.# Can be a proc.## The default is `false`config.browserify_rails.force=->(file){File.extname(file) ==".ts"}# Command line options used when running browserify## can be provided as an array:config.browserify_rails.commandline_options=["-t browserify-shim","--fast"]# or as a string:config.browserify_rails.commandline_options="-t browserify-shim --fast"# Define NODE_ENV to be used with envify## defaults to Rails.envconfig.browserify_rails.node_env="production"

browserify-incremental

browserify-incremental is used to cache browserification of CommonJS modules. One of the side effects is that the absolute module path is included in the emitted JavaScript. Most people do not want this for production code so browerify-incremental is current disabled for theproduction andstaging environments. Note that counter-intuitively, browserify-incremental helps even with a single build pass of your code because typically the same modules are used multiple times. So it helps even for say asset compilation on a push to Heroku.

Enabling browserify-incremental in production

To enable browserify-incremental in production, add the following line toconfig/environments/production.rb:

config.browserify_rails.use_browserifyinc=true

Multiple bundles

node-browserify supportsmultiple bundlesand so do does rails-browserify. It does this usingconfig/browserify.yml.Below is an example.

Say you have three JavaScript files and one is a huge library you would like touse in both. Browserify lets you mark that huge library with --require in onefile (to both bundle it and mark it with a special internal ID) and thenrequire it in the other file and mark it with --external (so it is not bundledinto the file but instead accessed via browserify internals using that specialID). Note that this only works when the file that has the library bundled isloaded before the file that uses the library with --external.

javascript:main:require:      -a_huge_librarysecondary:external:      -a_huge_library

Note that any valid browserify option is allowed in the YAML file but not alluse cases have been considered. If your use case does not work, please openan issue with a runnable example of the problem including your browserify.yml file.

Inside Isolated Engines

To make browserify-rails work inside an isolated engine, add the engine app directory to the browserify-rails paths (inside engine.rb):

config.browserify_rails.paths <<->(p){p.start_with?(Engine.root.join("app").to_s)}

If you wish to put the node_modules directory within the engine, you have some control over it with:

config.browserify_rails.node_bin="some/directory"

Example setup

Refer to this repo for setting up this gem with ES6 and all front-end goodies like react and all -github.com/gauravtiwari/browserify-rails

Support for rails asset directories as non-relative module sources

In the Rails asset pipeline, it is common to have files inapp/assets/javascripts and being able to do//= require some_file whichexists in one of the asset/javascript directories. In some cases, it isuseful to have similar functionality with browserify. This has been addedby putting the Rails asset paths into NODE_PATH environment variable whenrunning browserify.

But this comes at a large cost: right now, it appears to break source maps.This might be a bug or a fixable breakage but it hasn't been solved yet. Theuse of NODE_PATH is also contentious in the NodeJS community.

Why leave it in? Because some typical Rails components break without it.For example, jasmine-rails expects to be able to move JavaScript todifferent depths. So if you do a relative require from spec/javascript toapp/assets/javascripts, your tests will fail to run when RAILS_ENV=test.

So if you really need this, use it. But if you really need it for files thatare not tests, you should definitely figure out an alternative. Supportfor this may go away if we cannot fix the issue(s) with source maps beinginvalid.

Deploying to Heroku

Heroku is a very common target for deploying. You'll have to add custombuildpacks that runbundle andnpm install on the target machine.

$ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-nodejs.git$ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-ruby.git

Using Browserify Transforms

You can easily use a browserify transform by making some additions to yourpackage.json and creating a .babelrc. For example, here is how you can add ES6 support in your app:

  1. Addbabelify andbabel-preset-es2015 to yourpackage.json in your app's root directory either by editing the file directly and runningnpm install or usingnpm install babelify --save andnpm install babel-preset-es2015 --save
  2. Update yourpackage.json to contain the babelify transform by adding the following lines
   "browserify": {    "transform": [      [        "babelify"      ]    ]  }
  1. Create a.babelrc file in the project root with the following contents
{  "plugins": [],  "presets": ["es2015"]}
  1. Create some.es6 files and require them withvar m = require('./m.es6') orimport m from './m.es6'
  2. Restart your server, and you now have ES6 support!

Troubleshooting

Clear the asset pipeline cache

The Rails asset pipeline caches some files in thetmp directory insideRails root. It can happen that sometimes the cache does not get invalidatedcorrectly. You can manually clear the cache in at least two ways:

  1. rake tmp:cache:clear
  2. rm -rf ./tmp (when in the root directory of the Rails project)

The second method is definitely brute force but if you experience issues,it is definitely worth trying before spending too much time debuggingwhy something that is browserified appears to not match the sources files.

Javascript Tests

If you want to usebrowserify to process test files as well, you willneed to configurebrowserify-rails to process files in yourspec ortestdirectories.

config.browserify_rails.paths <<->(p){p.start_with?(Rails.root.join("spec/javascripts").to_s)}

Acceptance Test Failures

If you have Sprockets precompile multiple JS files, each of which includecertain browserified files, your acceptance tests may timeout before someof the assets have finished compiling.

To avoid this problem, runrake assets:precompile before running youracceptance tests.

Contributing

Pull requests appreciated. Pull requests will not be rejected based onideological neurosis of either the NodeJS or the Ruby on Rails communities.In other words, technical needs are respected.

Running the dummy Rails app

There is a dummy rails app intest/dummy. You can change to that directoryand runbundle install and thenbundle exec rails server. You can seethe test JavaScript files inapp/assets/javascripts so try loading one --for examplehttp://localhost:3000/assets/application.js.

You can use this dummy app to try out your coding/refactoring/hacking ideasand also see how the tests are written. To run the tests, runbundle exec rake testin the root directory of the browserify-rails code (not in the dummy app).

Potential areas of change (contributions welcome)

Multiple modules

Often one has one main module (say a library module) and other modules thatconsume the main module. It would be nice to be able to establish thisrelationship in the YAML file to avoid having to manually manage the requireand external entries for the involved modules.

Alternatives

Use webpack or browserify directly instead of the asset pipeline

Use a tool like ProcMan to kick off a webpack or browserify process to rebuild your JavaScript on change. Reference the bundle in your Rails template and away you go. With webpack, you can even use the dev server and point to the dev server port in your Rails template to load JavaScript directly from webpack (it'll block on build so you'll always get your latest code). This does require configuring webpack hot middleware to have a port (see__webpack_hmr goes to the wrong port and fails).

Contributors

About

Browserify + Rails = a great way to modularize your legacy JavaScript

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors47

Languages


[8]ページ先頭

©2009-2025 Movatter.jp