codewithmichael / babel-browser-harness

In-browser CDN-based ES6+ transpiling via Babel
MIT License
1 stars 0 forks source link

BBH ♥ Hello

Installation | External Libraries | Configuration | Separate Scripts | Logging | FAQ | Credit | License

The Babel Browser Harness (BBH) is a simple CDN-based browser polyfill that provides in-browser ES6+ transpiling via Babel using only a single script include.

In other words, it's a quick and easy way to spin up an ES6+ sandbox without worrying about Webpack, Browserify, Gulp, Grunt, etc.

You don't even need a web server!

This makes it ideal for on-the-go prototyping, where you often can't transpile (iOS, Android), and lets you jump right into working with new technologies without investing precious time on system configuration.

Example

<html>
  <head>

    <!-- Include BBH  -->
    <script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>

  </head>
  <body>
    <div id="app">

      <!-- Use "text/babel" script type -->
      <script type="text/babel">

        // Write ES6+

        // Display "BBH ♥ Hello"
        import { welcome } from 'bbh'
        document.getElementById('app').textContent = welcome

      </script>
    </div>
  </body>
</html>

That's it!

BBH will quietly include everything it needs in the background via CDN.


Installation

Check out or install Babel Browser Harness from one of the following locations:

Include bbh.js or bbh.min.js anywhere in your HTML file like so...

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>

...and open or reload the HTML file in your browser.

After a couple of seconds, happiness should appear in your browser console.

Figure A. "What happiness looks like"

BBH ♥ Hello

(BBH is primarily developed and tested using up-to-date Google Chrome)

Note: If you are developing on your mobile device and don't have access to your browser's developer console, you can enable a Firebug Lite console.


External Libraries

BBH uses a module mapping system to handle external libraries such as React, Angular, Underscore, or jQuery.

It can modularize any libraries you've already included in your page, or it can import and modularize them for you.

For details on modularizing your libraries and other available options, see the Configuration section.


Firebug Lite (Developer Console)

Babel Browser Harness is in no way affiliated with or publicly endorsed by Mozilla, Parakey, or the Firebug/Firebug Lite projects or their maintainers.

Firebug Lite is a pared-down, in-browser port of Mozilla's Firebug web development tool. It includes a developer console and DOM inspector which can make working from a mobile device significantly easier.

If you are developing from a mobile device and don't have access to your browser's developer console, you can enable a Firebug Lite console right from your script import with the hash option:

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#firebug"></script>

...or with the following command (after loading bbh.js)...

<script>
  bbh.enableFirebug();
</script>

Alternately, if you have a local copy of Firebug Lite or prefer a specific version of the library, you can pass an alternate file URL to the enableFirebug() method. You MUST provide any necessary hash options (such as #startOpened) as part of your custom url.

Note: While it is recommended to use the built-in hash option or enableFirebug() method, you can alternately load Firebug Lite manually via a custom script tag. If you choose to do so, it is recommended to import Firebug Lite before bbh.js so it can catch all of BBH's startup messages.


Configuration

Configuration is handled through property modification in the URL hash or using the bbh global variable. All hash options have configuration script equivalents.

Example (URL Hash - Enable React + Firebug Lite and Minify Scripts)

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#react|firebug|minify"></script>

Example (Config Script - Prepare Babel Config and Load a Library Module)

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>
...
<script>
  bbh.babelConfig = {
    presets: ['es2015', 'react'],
    plugins: ['transform-object-rest-spread'],
    minified: true
  }
  bbh.modules = {
    jquery: {
      exports: ['jQuery', '$'],
      src: 'http://code.jquery.com/jquery-3.0.0.min.js'
    }
  }
  bbh.removeModuleScripts = false
</script>

Hash Options

Hash options act as shortcuts to commonly used developer functions and configuration options. This keeps configuration time to a minimum, reduces typed character count for mobile developers, and can retain all of your BBH information in a single script tag at the location of import (for common configurations).

Hash options are set by adding a hash (#) string to the end of the URL in the src attribute of the script tag you use to load BBH:

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#react|minify"></script>

The above example enables React parsing in Babel (in addition to the standard ES2015), and minifies transpiled scripts.

Hash options are separated via the pipe (|) character and may contain an equals sign (=). They can also have comma-separated values assigned to them when appropriate.

When no equals sign is used, the assumed value is true.

Valid hash options are: firebug, minify (or minified), react, registration, plugins, presets.

Options are processed sequentially and may cancel or override each other.

See detailed information on each hash option below.

Note: Hash options are based on document.currentScript and are, therefore, browser-dependent. Most modern browsers support the feature, but if your development environment does not, you should use the standard configuration options.

firebug

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#firebug"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#firebug=true"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#firebug=false"></script>

Enables the Firebug Lite console and developer tool.

Equivalent to calling bbh.enableFirebug().

minify

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#minify"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#minify=true"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#minify=false"></script>

Enables the minified flag in the Babel configuration options.

Equivalent to calling bbh.babelConfig.minified = true.

react

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#react"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#react=true"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#react=false"></script>

Adds or removes the "react" option in the presets property of the Babel configuration.

Equivalent to bbh.babelConfig.presets.push('react').

registration

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#registration"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#registration=true"></script>
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#registration=false"></script>

Enables or disables registration mode for the current file.

See the registration system documentation for more information.

Equivalent to calling bbh.registrationMode().

plugins

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#plugins=plugin1,plugin2"></script>

Directly set the plugins used in the Babel configuration.

Equivalent to calling bbh.babelConfig.plugins = ['plugin1', 'plugin2', ...].

presets

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#presets=preset1,preset2"></script>

Directly set the presets used in the Babel configuration.

Equivalent to calling bbh.babelConfig.presets = ['preset1', 'preset2', ...].


Configuration Options

Configuration options work in all supported modern browsers. They are applied to the global bbh variable in a script tag after bbh.js has been included in your page.

The following configuration options are available:

appendTarget

Example

bbh.appendTarget = document.getElementById('myDiv')

If appendTarget is set, the option defines a target element in which to place all generated script elements.

If appendTarget is not set, BBH will first look for an element with an id="bbh" attribute. If one is not found it will default to the document.body.

autoloadReact

Example

bbh.autoloadReact = false

By default, if the "react" preset is enabled in babelConfig, the react-related libraries (react and react-dom) will automatically be loaded for you, unless you have already specified at least one of them manually in modules.

You can disable this feature by setting autoloadReact to false.

babelConfig

Example

bbh.babelConfig = {
  presets: ['es2015', 'react'],
  plugins: ['transform-object-rest-spread'],
  minified: true
}

The babelConfig property is used to set/update the Babel configuration options. It should accept most valid Babel Options, though most are not usable in a browser context.

The most commonly used options are presets and plugins:

modules

Example (Object)

bbh.modules = {
  jquery: {
    exports: ['jQuery', '$'],
    src: 'http://code.jquery.com/jquery-3.0.0.min.js'
  }
}

Example (Array)

bbh.modules = [
  {
    name: "underscore",
    exports: "_",
    src: "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"
  },
  {
    name: "backbone",
    exports: "Backbone",
    src: "https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"
  },
]

The modules property is primarily used to map external libraries to importable modules. It can be either an Object or an Array. The array syntax (uses a name property) should be used when library loading order is important.

If the src property is defined, the external library will be loaded in the background (via a generated script tag). This allows for all dependency configuration to be managed in one place.

If, you prefer to load the script yourself, or wish to create an importable module inline from existing ES5 code, just leave off the src property. The window globals will be searched for your library module.

Example (Manual Imports)

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>
<script src="http://code.jquery.com/jquery-3.0.0.min.js"></script>

<script> window.MyLib = { message: 'Hello, World!' } </script>

<script>
bbh.modules = {
  jquery: { exports: ['jQuery', '$'] },
  mylib:  { exports: 'MyLib' }
}
</script>

<!-- Use jQuery to populate a div with the message from MyLib -->

<div id="app"></app>

<script type="text/babel">
  import $ from 'jquery'
  import { message } from 'mylib'
  $('#app').text(message)
</script>

Available modules Properties

The following properties may be set in a modules entry:

removeModuleScripts

Example

bbh.removeModuleScripts = false

The removeModuleScripts property is used to keep the script tags generated by defining the modules.src property from being removed from the DOM.

By default, external module script tags are removed after they have been applied to keep the DOM clean for easy debugging.

Set the removeModuleScripts property to false to retain these generated script tags.

removeRegisterScripts

Example

bbh.removeRegisterScripts = false

The removeRegisterScripts property is used to keep the script tags generated by using the register() method from being removed from the DOM.

By default, script tags generated by importing from registered files are removed from the DOM after they have been transpiled to keep the DOM clean for easy debugging.

Set the removeRegisterScripts property to false to retain these imported script tags.


Separate Scripts

Projects can grow quickly, and it is often desirable to break your scripts out into separate files. BBH provides two systems for accomplishing this task—direct script imports and an internal registration system.


Direct Script Imports

<script type="text/babel" name="myscript" src="https://github.com/codewithmichael/babel-browser-harness/raw/master/myscript.js"></script>

A "direct script import" works like any other <script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/.."> import on your page, except that you append the type="text/babel" attribute.

As with inline Babel scripts, you can define a name attribute to specify the module name used for import. If you prefer to use the src path as the module name, you may omit the name attribute all together.

Because script elements of type text/babel do not designate a known browser-compatible script type, they are ignored by the browser and subsequently post-processed by BBH.

File retrieval is performed via AJAX request.

Local Web Server

If you choose to run a local web server, here are a couple of simple options:


Registration System

No web server required!

The registration system is fully functional even when you're developing on your local machine without a web server—i.e. opening local files in your web browser and using the file:// URL scheme.

Instead of performing AJAX requests, registered files are loaded via the postMessage API, which does not require AJAX or CORS to function.

This makes the registration system a viable option for developers working from a mobile device to separate their scripts without the use of an external server.

Registering a Module File

When BBH runs in registration mode, it doesn't transpile scripts found on the page. Instead it waits for a register() request and responds by returning a serialized version of all the <script type="text/babel"> elements on the page. Those elements are then deserialized for transpiling in the calling document.

Example (Loading a Module from an External File)

my-module.html

<!-- MODULE SCRIPT -->
<script type="text/babel" name="my-module">
  export const message = "This message comes from my module!"
</script>

<!-- CONFIG -->
<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#registration"></script>

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>External Module Example</title>
  </head>
  <body>

    <!-- MAIN SCRIPT -->
    <script type="text/babel">
      import { message } from 'my-module'
      document.body.textContent = message
    </script>

    <!-- CONFIG -->
    <script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>
    <script> bbh.register({ src: './my-module.html' }) </script>

  </body>
</html>

In the above example, the main script in index.html wants to load message content from my-module, which is declared in my-module.html. To accomplish this, register() is used to load my-module.html, which has been configured to run BBH in registration mode.

Note: my-module.html used a hash option, #registration, appended to the script tag's src URL to enable registration mode. Alternately, you can initiate registration mode by calling bbh.registrationMode() directly. See the registrationMode() method documentation for further details.

Cross-Origin Issues

If you are loading modules from a remote server or are using a local server with inconsistent origin declarations (such as many mobile device implementations), you may receive the error Cross-origin registration rejected.

If this occurs, you can use the bbh.allowCrossOriginRegistration() method to bypass the problem. However, the option should generally only be used for local development or on a shared development server, as it effectively makes any scripts configured for "registration mode" publicly available.

Note: bbh.allowCrossOriginRegistration() must be called in both the calling and receiving files (after bbh.js has been imported) to enable cross-origin registration, as origin security checks are performed on both ends.

Registration Methods

register()

Example

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>
<script>

  // Single File Registration
  bbh.register({ src: './file.html', timeout: 5000 })

  // Multiple File Registration
  bbh.register([
    { src: './file1.html' },
    { src: './file2.html' }
  ])

</script>

The register() method is used to request the contents of an external file.

register() accepts an options argument in Object format (or an Array of Objects) with the following available properties:

registrationMode()

Example (Hash Option)

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#registration"></script>

Example (Config Option)

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>
<script>

  // Enable
  bbh.registrationMode()

  // Disable
  bbh.registrationMode(false)

</script>

The registrationMode() method is used to set a file to listen for a register() request from a calling file. It must be called within a file for that file to be loadable via the registration system.

Alternately, the shorthand hash option may be used to enable registration mode. This simply entails adding #registration to the end of the BBH script tag's src URL.

allowCrossOriginRegistration()

Example (Enable/Disable)

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js"></script>
<script>

  // Enable
  bbh.allowCrossOriginRegistration()

  // Disable
  bbh.allowCrossOriginRegistration(false)

</script>

The allowCrossOriginRegistration() method is used to disable origin-based security checks on postMessage API events used by the registration system.

This is useful if you want to load a module file from a remote development server or if you are on a mobile device with poorly managed origin declarations.

Note: bbh.allowCrossOriginRegistration() must be called in both the calling and receiving files (after bbh.js has been imported) to enable cross-origin registration, as origin security checks are performed on both ends.

Note: Cross-origin registration should generally only be used for local development or on a shared development server, as it effectively makes any scripts configured for "registration mode" publicly available.


Logging

BBH logs it's progress as it processes your scripts. These logs are available in your browser console.

Note: If you are developing on your mobile device and don't have access to your browser's developer console, you can enable a Firebug Lite console.

BBH ♥ Hello

BBH begins processing with a welcome message. This message is displayed as soon as configuration options have been successfully determined.

BBH ♥ Loading Modules

This message designates that requested scripts from the modules configuration are being downloaded (or loaded from cache), globals are being mapped, and BBH is checking for global leaks.

The duration of this stage is dependent on the speed of your network/internet connection in retrieving external dependencies.

If any requested external libraries cannot be loaded—for example due to a missing file, incorrect url, or unavailable host/CDN—you will receive a console message similar to the following:

BBH ♥ Error Detected :(
BBH ♥ The script "jquery.min.js" is not accessible

Also, if you're using the registration system and a given module doesn't respond within the designated timeout period, you may receive a message like the following:

BBH ♥ Error Detected :(
BBH ♥ Registration didn't resolve: "./module.html" (3000ms)

In this case, it is most likely that you forgot to set the module file to run in registration mode. See the registrationMode() documentation for more details.

BBH ♥ Global Leaks Detected

During the Loading Modules phase, you may receive a message similar to the following:

BBH ♥ Global Leaks Detected: ["jQuery","$"]

This isn't an error. It's just there to let you know that you may have forgotten to map an imported library to a module.

The provided list is a summary of all global variables registered to the window object since BBH was loaded that have not been mapped.

If this message contains variables that are known globals, and you wish to keep them global but want to eliminate the log notice, you can map them using the ignore feature of the modules configuration property.

(See the Configuration section for details on mapping or ignoring globals and imported libraries via the modules property)

BBH ♥ Transpiling

This message designates that all necessary external libraries and modules have been assembled and the process of transforming your custom scripts has begun.

Transpile speed is dependent on your particular machine, but is typically a very fast process.

If any syntax errors are encountered during this phase, you will receive the familiar message...

BBH ♥ Error Detected :(

...followed by a console entry detailing the syntax error and location.

BBH ♥ Running

If you receive this message, BBH has completed transpiling, handed the resultant scripts off to your browser, and is running away.

If any errors occur at this point, they are entirely your fault :D


FAQ

Why isn't my BBH using the heart (♥) symbol?

The heart symbol (♥) is a unicode character in the UTF-8 character set.

At startup BBH checks to see if it is running in a UTF-8 context. If not, it uses a middle dot (·), a character capable of being rendered in the browser's default ISO-8859-1 character set.

If you would like to have UTF-8 character support (and see the heart), you may change the character set for either the entire document or just the BBH script itself (see below).

Document-Level UTF-8 Support

<html>
  <head>
    <meta charset="utf-8" />
    ...

Script-Level UTF-8 Support

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js" charset="utf-8"></script>

Does BBH handle React/JSX syntax?

Yes! Because BBH is based on Babel, it does support React/JSX syntax, but it has to be enabled via a hash or configuration option:

Example - Enable React Using a Hash Option

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#react"></script>

Example - Enable React Using a Configuration Option

bbh.babelConfig = { presets: ["es2015", "react"] };

BBH will automatically import React libraries for you once the "react" preset is defined, but if you prefer a specific version, you can load it using the modules configuration option.

See the Configuration section for more details on module definitions and Babel presets.

See autoloadReact for more information on the automatic loading feature for React libraries.

Can I mix and match normal (ES5) and ES6+ scripts?

Yes, but Babel-transpiled scripts run after all other scripts on the page, so you'll still want to add type="text/babel" to your regular ES5 scripts so they run in sequence.

Don't worry, normal ES5 scripts works just fine when parsed as ES6+, but they'll have the restriction of running as their own module, so you'll have to assign any global variables directly to the window object.

Also, you can use CommonJS module syntax (require, module, exports) if you would like to interact with the module system.

Can I separate my modules into their own files?

Yes, using either direct script imports or the built-in registration system. See the Separate Scripts section for more details.

How can I develop with BBH from my mobile device?

If you're using a mobile editor that has a built-in, WebKit-based preview option (like Working Copy, Textastic, or Coda) then you're ready to go. Just check out or copy this project into your mobile editor and open example.html in your editor's preview mode to test.

Note: Developer console capabilities can vary widely between editors. To provide a consistent JavaScript-based console for debugging on your mobile device, enable the Firebug Lite developer console with a hash or configuration option:

Example - Enable Firebug Lite with a Hash Option

<script src="https://github.com/codewithmichael/babel-browser-harness/raw/master/bbh.js#firebug"></script>

Example - Enable Firebug Lite with a Config Option

<script>
  bbh.enableFirebug();
</script>

Does BBH support valid markup attributes?

It does! The examples provided in the documentation often don't use strictly valid HTML5 attributes. If you require (or just prefer) valid HTML5 attributes, you can replace BBH-specific tag attributes with their data-* equivalent.

Example (Setting the "data-name" attribute)

<!-- Use "data-name" instead of "name" -->
<script type="text/babel" data-name="my-module-name">
  export const message = "I'm a module!"
</script>

Is BBH "production-ready"?

No! BBH is strictly a development tool and should never be used in a production environment. When you feel your code has matured to a serious level, create an appropriate build environment or transpile server-side.

If you need in-browser transpiling, for example to create a user-facing REPL like JSFiddle, consider a dependency-free, packaged library solution like babel-standalone that focuses solely on transpiling.


Credit

Babel Browser Harness is not affiliated with or publicly endorsed by the following projects or their maintainers. Project/Company/Author names are provided solely for the purpose of attribution.


License

MIT