{"id":16877182,"url":"https://github.com/rmacklin/sprockets-bumble_d","last_synced_at":"2025-10-06T00:56:24.571Z","repository":{"id":43834991,"uuid":"67844502","full_name":"rmacklin/sprockets-bumble_d","owner":"rmacklin","description":"Sprockets plugin to transpile modern javascript using Babel, useful while migrating to ES6 modules","archived":false,"fork":false,"pushed_at":"2022-02-16T20:44:40.000Z","size":153,"stargazers_count":32,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-20T22:51:37.194Z","etag":null,"topics":["asset-pipeline","babel","babel-plugin","es2015","es2015-modules","es6-modules","incremental","javascript-globals","migration","rails","sprockets","sprockets-plugin","sprockets-transformer","umd-modules"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rmacklin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-10T01:53:46.000Z","updated_at":"2023-02-15T15:23:20.000Z","dependencies_parsed_at":"2022-08-21T00:50:57.383Z","dependency_job_id":null,"html_url":"https://github.com/rmacklin/sprockets-bumble_d","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/rmacklin/sprockets-bumble_d","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmacklin%2Fsprockets-bumble_d","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmacklin%2Fsprockets-bumble_d/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmacklin%2Fsprockets-bumble_d/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmacklin%2Fsprockets-bumble_d/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rmacklin","download_url":"https://codeload.github.com/rmacklin/sprockets-bumble_d/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmacklin%2Fsprockets-bumble_d/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278542675,"owners_count":26004061,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asset-pipeline","babel","babel-plugin","es2015","es2015-modules","es6-modules","incremental","javascript-globals","migration","rails","sprockets","sprockets-plugin","sprockets-transformer","umd-modules"],"created_at":"2024-10-13T15:42:01.759Z","updated_at":"2025-10-06T00:56:24.546Z","avatar_url":"https://github.com/rmacklin.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sprockets::BumbleD\n\nThis gem provides a plugin for [Sprockets] that enables you to transpile modern\njavascript using [Babel].\n\nA primary use case for this gem is to incrementally migrate your\nSprockets-powered javascript codebase to ES6 modules. This works by\n[transforming] them to [UMD] modules that preserve your existing global variable\nreferences (hence the name: Babel + UMD = BumbleD). Once an entire subtree of\nyour javascript module tree is written in ES6 modules, this frees you up to\nbundle that javascript using a more modern tool (e.g. [rollup] or [webpack]).\n\nThat said, this gem can be used for general purpose babel transpilation within\nthe Sprockets pipeline.\n\n[Babel]: https://babeljs.io\n[rollup]: https://rollupjs.org\n[Sprockets]: https://github.com/rails/sprockets\n[transforming]: https://en.wikipedia.org/wiki/Bumblebee_(Transformers)\n[UMD]: https://github.com/umdjs/umd\n[webpack]: https://webpack.js.org/\n\n## Background\n\nES6 modules are the new standard. The syntax is great: it's concise and\nstraightforward, and the static and explicit nature of `import` and `export`\nstatements make your code a complete spec of its dependencies and how to\nresolve them. This means that moving to ES6 modules also makes moving away\nfrom Sprockets `//= require` directives for javascript bundling (and Sprockets\nin general) much easier.\n\nBut when faced with a large legacy codebase, it's not feasible to convert\neverything to ES6 modules at once. Thus, the goal is to be able to convert\nmodule-by-module from explicitly exporting a global variable (and depending on\nother modules' global variables) to following the ES6 module format, which we'll\nthen transpile to UMD that is compatible with non-converted code (e.g. existing\nUMD modules and plain old global-dependent scripts).\n\nSprockets::BumbleD accomplishes this goal by providing a Sprockets transformer\nthat acts on `.es6` files (this file extension is\n[configurable](#customizing-the-file-extension)). These files are transpiled by\nBabel and the [ES2015 -\u003e UMD modules transform] plugin, preserving any globals\nthat you've [registered](#registering-globals).\n\n[ES2015 -\u003e UMD modules transform]: https://github.com/babel/babel/tree/v7.3.4/packages/babel-plugin-transform-modules-umd\n\n## Setup\n\n### Installation\n\n1. Add `gem 'sprockets-bumble_d'` to your `Gemfile` (or add a gemspec\ndependency to an [inline engine](#inline-rails-engines) in your app) and\nrun `bundle install`.\n2. Run `npm install --save @babel/core @babel/plugin-external-helpers @babel/plugin-transform-modules-umd @babel/preset-env`\nto install the modules for the default babel config. If you want to\n[customize the babel options](#customizing-your-babel-options), install any\nadditional plugins and presets you want.\n3. Generate the [external helpers] and `//= require` them in at the beginning\nof your application manifest or pull them in with a separate script tag. This\nstep is of course unnecessary if you won't be using the external-helpers\nplugin, but it's highly recommended that you do (to avoid inlining them\neverywhere, which unnecessarily bloats the bundle sent to the browser).\n\n[external helpers]: https://babeljs.io/docs/plugins/external-helpers\n\n### Basic configuration\n\nIn `config/application.rb`:\n```ruby\nextend Sprockets::BumbleD::DSL\n\nconfigure_sprockets_bumble_d do |config|\n  config.babel_config_version = 1\nend\n```\n\nIf you are not using Rails, you must also configure the `root_dir` (see below).\n\n### Customizing the `root_dir`\n\nSprockets::BumbleD needs to know the directory from which node modules are to\nbe resolved (typically, wherever your `package.json` resides). If you're using\nRails, this defaults to `Rails.root.to_s`. If you are not using Rails, or if\nyour node_modules folder is not inside `Rails.root`, you **must** configure the\n`root_dir` setting! For example, if you are configuring Sprockets::BumbleD in\nthe file `config/application.rb` and your `package.json` is located in the\nparent directory, use:\n\n```ruby\nconfigure_sprockets_bumble_d do |config|\n  config.root_dir = File.expand_path('..', __dir__)\n  config.babel_config_version = 1\nend\n```\n\nIf it's in a specific subdirectory, specify that directory instead.\nSprockets::BumbleD doesn't care, as long as its node `require` statements will\nresolve from that directory.\n\n### Customizing your babel options\n\nBy default you get [@babel/preset-env], [@babel/plugin-external-helpers], and\n[@babel/plugin-transform-modules-umd]. If you want to customize this with\ndifferent plugins and presets, specify them in the\n`configure_sprockets_bumble_d` block with the `babel_options` setting. Note\nthat (because it's central to the purpose of this gem)\n@babel/plugin-transform-modules-umd is included for you (unless\nyou [set `transform_to_umd` to `false`](#do-i-have-to-transpile-to-umd-modules))\nand configured to use the [registered globals](#registering-globals), so this\nplugin does not need to be specified when you override the default plugins.\n\n[@babel/preset-env]: https://babeljs.io/docs/en/babel-preset-env\n[@babel/plugin-external-helpers]: https://babeljs.io/docs/en/babel-plugin-external-helpers\n[@babel/plugin-transform-modules-umd]: https://babeljs.io/docs/en/babel-plugin-transform-modules-umd\n\nFor example:\n```ruby\nconfigure_sprockets_bumble_d do |config|\n  config.babel_config_version = 2\n  config.babel_options = {\n    presets: ['@babel/preset-env', '@babel/preset-react'],\n    plugins: ['@babel/plugin-external-helpers', 'custom-plugin']\n  }\nend\n```\n\nYou can specify any options that are allowed in a `.babelrc` file.\n\n### Customizing the file extension\n\nBy default the Sprockets transformer is registered to act on `.es6` files. This\nis configurable:\n```ruby\nconfigure_sprockets_bumble_d do |config|\n  config.babel_config_version = 1\n  config.file_extension = '.babel'\nend\n```\n\n### The `babel_config_version` setting\n\nWhat's this mysterious `babel_config_version` we're setting in the previous\nexamples? Good question. Essentially this is intended to be a value that\ntranslates to the composite version of @babel/core and each babel preset\nand plugin in your application. It's used to expire the cache for compiled\nassets: since different versions of babel and its plugins can result in a\ndifferent transpiled output, we want to be able to invalidate the cache\nwhenever we change our babel configuration. So, when you upgrade @babel/core\nor you add/remove/upgrade a babel plugin or preset, you'd increment this\nversion which will cause the Sprockets transformer's cache key to change.\n\n### Philosophy\n\nYou should own your babel setup. We want to be able to use the latest versions\nof babel and its plugins as soon as they're available, so this gem doesn't\nvendor any node modules - it's up to the application to provide those to the\ngem. This is what the `root_dir` config is for. It's also why the\n`babel_config_version` setting exists.\n\n### Registering globals\n\n@babel/plugin-transform-modules-umd includes an `exactGlobals` option that lets\nyou specify exactly how to transpile any import statements into the global\nreference it should resolve to. It also lets you specify what global should be\nexported by an ES6 module in the resultant UMD output. (A complete description\nis available in [babel PR #3534].)\n\n[babel PR #3534]: https://github.com/babel/babel/pull/3534\n\nIn `config/application.rb`, after `extend Sprockets::BumbleD::DSL`:\n```ruby\nregister_umd_globals :my_app,\n  'my/great/thing' =\u003e 'MyGreatThing',\n  'her/cool/tool'  =\u003e 'herCoolTool'\n```\n\nDoing this will allow:\n```js\nimport GreatThing from 'my/great/thing';\n```\nto be transpiled to:\n```js\nfactory(/* ... */ global.MyGreatThing);\n```\nin the globals branch of the transpiled UMD output. Similarly, the above map\nalso specifies that the exports of the ES6 module `her/cool/tool` will be\nassigned to the `herCoolTool` global.\n\nThat is, registering these globals provides both:\n- a way to depend on existing globals in ES6 modules\n- a way to declare the global an ES6 module should export, to be used in\nexisting UMD modules or direct global references\n\nAs a corollary, if you are writing a new ES6 module that is only used by other\nES6 modules, you would not need to register a global for that module's export.\n\nExported globals can also be nested objects and the transform will properly\nhandle creating the necessary prerequisite assignments. For example with this\nregistration:\n```ruby\nregister_umd_globals :my_app,\n  'her/cool/tool' =\u003e 'Her.Cool.Tool'\n```\nthe compiled `her/cool/tool` module will contain:\n```js\nglobal.Her = global.Her || {};\nglobal.Her.Cool = global.Her.Cool || {};\nglobal.Her.Cool.Tool = mod.exports;\n```\n\n#### Inline Rails engines\n\nIf you have a large application, you may have split it into multiple inline\nrails engines (as described in [this talk]). Inline engines with their own\nassets should own the registration of globals for these assets. This is\nsupported in Sprockets::BumbleD:\n\n[this talk]: https://www.youtube.com/watch?v=-54SDanDC00\n\nin `some_engine/engine.rb`:\n```ruby\nextend Sprockets::BumbleD::DSL\n\nregister_umd_globals :some_engine,\n  'some_namespace/first_module'  =\u003e 'SomeNamespace.firstModule',\n  'some_namespace/second_module' =\u003e 'SomeNamespace.secondModule',\n  'another_thing/mod'            =\u003e 'anotherModule'\n```\n\nSince module globals should only be registered in the engine (or top level\napplication) where the module lives, `register_umd_globals` will raise\n`Sprockets::BumbleD::ConflictingGlobalRegistrationError` if a module is\nregistered a second time. Of course, this still can't prevent you from\nregistering globals (that had not already been registered) in the wrong engine.\n\n### Reminder about Rails reloading\n\nAs with any `config` changes, updates to the globals registry are not\nreloaded automatically; you must restart your server for the changes to take\neffect.\n\n### Do I have to transpile to UMD modules?\n\nNo, you can transpile to other module formats (e.g. AMD). You'd just be using\nless of this gem's API surface area \u003csup\u003e1\u003c/sup\u003e. You can set `transform_to_umd` to\n`false` in your `configure_sprockets_bumble_d` block, and\n[override the default plugins](#customizing-your-babel-options) to use a\ndifferent module transform. For example if you're using an AMD loader like\n[almond], you could configure modules to be transpiled to AMD like so:\n\n[almond]: https://github.com/requirejs/almond\n\n```rb\nconfigure_sprockets_bumble_d do |config|\n  config.root_dir = File.expand_path('..', __dir__)\n  config.babel_config_version = 1\n  config.transform_to_umd = false\n  config.babel_options = {\n    presets: ['@babel/preset-env'],\n    plugins: ['@babel/plugin-external-helpers', '@babel/plugin-transform-modules-amd']\n  }\nend\n```\n\nYou can reference the [5.0_amd test app](./test/test_apps/5.0_amd) which\ndemonstrates this in a full application.\n\n\u003csup\u003e\u003csup\u003e1\u003c/sup\u003e Of course if you're doing this, you wouldn't ever call\n`register_umd_globals`\u003c/sup\u003e\n\n## Similar projects\n\n- [babel-schmooze-sprockets] - This takes a similar approach, but it requires\n  Sprockets 4 (which is still in beta), and it doesn't offer a way to register\n  globals within inline engines. Additionally, it diverges in\n  [philosophy](#philosophy) by vendoring some node_modules.\n- [sprockets-es6] - This was the common solution for ES6 transpilation within\n  Sprockets for a while, but it takes a very different approach. Instead of\n  relying on node and the npm ecosystem, it uses [ruby-babel-transpiler], which\n  is stuck on babel 5. This means you cannot configure custom babel plugins\n  (which means you can't use `exactGlobals` to specify what it should transform\n  globals to in the UMD modules transform).\n- [sprockets 4] - This takes the same approach as sprockets-es6 so it suffers\n  from the same limitations as sprockets-es6\n\n[babel-schmooze-sprockets]: https://github.com/fnando/babel-schmooze-sprockets\n[ruby-babel-transpiler]: https://github.com/babel/ruby-babel-transpiler\n[sprockets-es6]: https://github.com/TannerRogalsky/sprockets-es6\n[sprockets 4]: https://github.com/rails/sprockets/tree/v4.0.0.beta4\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frmacklin%2Fsprockets-bumble_d","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frmacklin%2Fsprockets-bumble_d","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frmacklin%2Fsprockets-bumble_d/lists"}