Skip to content

Instantly share code, notes, and snippets.

@ahoward
Last active January 31, 2017 13:23
Show Gist options
  • Save ahoward/7592792 to your computer and use it in GitHub Desktop.
Save ahoward/7592792 to your computer and use it in GitHub Desktop.
mix and match sprockets, bower, and npm modules with impunity (in middleman / rails is similar)
# this directive processor enhances sprockets with the ability to load bower
# and npm packages
#
# usage is simple
#
# //= browserify 'my_library'
# window.MyLibrary
# browserify.modules['my_library']
#
# if you would like to to control the name of what's loaded do this
#
# //= browserify 'my_library' 'Foo'
# window.Foo
# browserify.modules['my_library']
#
# obviously you need to add you npm packages to sprockets' normal lookup path,
# something like this in middleman, and similar for rails
#
module ::Sprockets
module Browserify
class DirectiveProcessor < ::Sprockets::DirectiveProcessor
def process_browserify_directive(path, *args)
name = args.shift || (File.basename(path).split('.').first)
pathname = context.resolve(path)
context.depend_on_asset(pathname)
browserify_modules[name] = pathname
end
def browserify_modules
@browserify_modules ||= Hash.new
end
def process_source
super
ensure
browserify_modules.each do |name, pathname|
@result << compile(name, pathname)
end
end
def compile(name, pathname)
pathname = pathname.to_s
id = Browserify.identifier
dirname = test(?d, pathname) ? pathname : File.dirname(pathname)
key = File.basename(dirname)
success = false
result = nil
cmd = "PATH=./node_modules/.bin:$PATH browserify --standalone #{ id } #{ dirname }"
result = `#{ cmd }`
unless $?.exitstatus.zero?
warn "#{ cmd } # FAILED"
abort
end
<<-__
// browserify: #{ dirname } ...
//
#{ result }
this.browserify = this['browserify'] || {};
this.browserify['modules'] = this.browserify['modules'] || {};
this.browserify['modules'] = this.browserify['modules'] || {};
this.browserify['modules']['#{ key }'] = this['#{ id }'];
this['#{ name }'] = this.browserify['modules']['#{ key }'];
//
// browserify: #{ dirname } .
__
end
def Browserify.identifier
(@identifier ||= "@").succ!
end
end
end
end
after_configuration do
sprockets.unregister_processor('application/javascript', ::Sprockets::DirectiveProcessor)
sprockets.register_processor('application/javascript', ::Sprockets::Browserify::DirectiveProcessor)
end
# add bower modules to the sprockets asset path - load them with //= browserify 'package_name'
#
after_configuration do
@bower_config = JSON.parse(IO.read("#{root}/.bowerrc"))
directory = File.join("#{root}", @bower_config["directory"])
sprockets.append_path(directory)
glob = File.join(directory, '*')
Dir.glob(glob) do |entry|
next unless test(?d, entry)
sprockets.append_path(entry)
end
end
# add npm modules to the sprockets asset path - load them with //= browserify 'package_name'
#
after_configuration do
glob = File.join('node_modules', '*')
Dir.glob(glob) do |entry|
next unless test(?d, entry)
sprockets.append_path(entry)
end
end
# let node (and browserify) know about packages we have installed in sprockets
#
after_configuration do
node_path = [sprockets.paths, (ENV['NODE_PATH'].split(':') if ENV['NODE_PATH'])].compact.flatten.join(':')
ENV['NODE_PATH'] = node_path
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment