npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

broccoli-multi-builder

v0.3.0

Published

write and consume es6 source code, build to amd, globals or commonjs

Downloads

22

Readme

broccoli-multi-builder

Who this is for

This is for library authors who want to:

  • Write ~~ES6~~ ES2015 (and beyond) source code (and use its imports/exports for code organization)
  • Publish their code in a browser-friendly format (AMD or Global) and/or a Node-friendly format (CommonJS)
  • Consume other libraries (via import "other-codebase") in their source code and still be able to publish to the above formats

Caveats

  • Dependency depth of 1
    • this lib does not yet support vendored modules that themselves depend on other modules, however:
    • if each vendored module also adheres to the conventions below, then you can list all of them in vendoredModules and it should still work fine
  • Can only import from a vendored module's top-level namespace (aka import X from "other-pkg" is fine, but import X from "other-pkg/nested/thing" is not)
  • Dependencies are installed from npm (and their code is therefore in the node_modules/ dir)

Conventions

General

  • source code is written in es6 with import/export statements
  • source code is in a top-level /lib dir (configurable via option libDirName)
  • published commonjs code goes into dist/commonjs/<packageName>/
  • published AMD code goes into dist/amd/<packageName>.js (the filename is configurable via option outputFileName)
  • published globals code goes into dist/global/<packageName>.js (the filename is configurable via option outputFileName)
  • the source code (/lib) must also published to npm (so that it can be consumed by libraries that depend on this one, see below)
  • dependencies are explicitly declared when building and:
    • dependencies also adhere to these conventions (with some additional caveats, below)

AMD-specific

  • dependencies must also be written in es6 with import/export statements
  • dependencies' source code is in a lib/ dir (configurable) in that dependency's published npm package
    • this is necessary because when broccoli-multi-builder builds your project for AMD it transpiles and bundles the dependency's source as well, so it must be present
  • An AMD loader is not included by default (to include one, set options.loader = true)
  • The AMD output file is not wrapped in an IIFE

Globals-specific

  • The globals build takes the AMD tree and:
    • includes the loader.js AMD loader
    • in the bottom of the file, appends require('<packageName>')["registerGlobal"](window, document);
    • wraps the file in an IIFE
    • It expects that your package will export a function called registerGlobal that it can call with the arguments (window, document). To override this set options.registerGlobalExport to a different string. The registerGlobal named export from your index.js is where you would do something like window.MyPackageName = X; in order to allow a third-party to use your library as the global MyPackageName.

CommonJS-specific

  • The "main" entry in your package.json must point to "dist/commonjs/<packageName>/index.js" (broccoli-multi-builder will check for this)
  • Third parties who use your library via commonjs will only be able to require('your-package-name');. require calls for sub-directories (like require('your-package/thing');) will not work properly due to the way node's module require system works (it looks for paths relative to the directory root, not relative to the location of the "main" file) and the fact that broccoli-multi-builder publishes your commonJS code in dist/commonjs.
  • The CommonJS build does not attempt to bundle any of the listed vendoredModule dependencies (those should be listed in this library's package.json dependencies so that the transpiled code can use node's standard require mechanism to bring them in)

Publishing conventions

For other users of broccoli-multi-builder

In order to publish your npm module so that another library that uses broccoli-multi-builder can consume it, you must:

  • put your es6 source code in lib/
  • have a lib/index.js that provides the default export for your library
  • be sure to include your lib/ code when publishing to npm

For browser-based users

Browser-based users can download your library via npm install <your-package-name> and find the format they prefer ("amd" or "global") available as a single file in the "dist/` directory, and include that in their project via a mechanism of their choice.

Optionally, you may want to publish via bower as well.

For node-based users

Node-based users can install your library via npm install <your-package-name> and then simply require('your-package-name'); in their code. Node's standard require mechanism will take care of including any other dependencies at that point (although these must be listed in your package.json dependencies).

Usage

To build your es6-based library using broccoli-multi-builder for amd, global or commonjs output:

  • install and save broccoli-multi-builder: npm install --save-dev broccoli-multi-builder
  • install the broccoli cli tool: npm install --global broccoli-cli
  • install and save broccoli as a dependency: npm install --save-dev broccoli
  • install and save broccoli-merge-trees: npm install --save-dev broccoli-merge-trees

Add a Brocfile.js file in the root of your project with the following code:

var multiBuilder = require('broccoli-multi-builder');
var mergeTrees = require('broccoli-merge-trees');

var amdOptions = {
  libDirName: 'path/to/es6/src/directory', // default: 'lib'
  packageName: 'my-package', // influences the name of the built file and directories,
                             // and the source root for the amd modules
  vendoredModules: [] // the npm package names of any other modules that your es6 code
                      // consumes. Those packages must have a file/directory structure
                      // as described below
};

var globalOptions = {
  libDirName: 'path/to/es6/src/directory', // default: 'lib'
  registerGlobalExport: 'registerGlobal', // default: 'registerGlobal'
  packageName: 'my-package', // influences the name of the built file and directories,
                             // and the source root for the amd modules
  vendoredModules: [] // the npm package names of any other modules that your es6 code
                      // consumes. Those packages must have a file/directory structure
                      // as described below
};

var cjsOptions = {
  libDirName: 'path/to/es6/src/directory', // default: 'lib'
  packageName: 'my-package',
  vendoredModules: [] // same as the vendored modules for the amdOptions
}

module.exports = mergeTrees([
  multiBuilder.build('amd', amdOptions),
  multiBuilder.build('global', globalOptions),
  multiBuilder.build('commonjs', cjsOptions)
]);

Ensure you have an index.js file in the root of your lib directory (e.g. lib/index.js) that has a default export. If you are building for globals mode also ensure your index.js exports a function named registerGlobal.

Then do a broccoli build dist to put your cjs and amd output into dist/. Note that broccoli will complain about writing to a directory that already exists so you may need to rm -rf dist first.

Read more about broccoli.js here.

More Caveats

If you are consuming another library built with broccoli-multi-builder:

  • install it using npm install other-package
  • add its name to the array of vendoredModules that you pass to the build method in your Brocfile
  • in your own lib/ es6 code, it should be fine to import default (import X from "other-package") and named exports (import { namedThing} from "other-package")
  • you must not import from anywhere but the module root path (i.e. cannot import X from "other-package/thing") of a vendored module

Remember that npm automatically ignores everything in your .gitignore file, so if you are sensibly ignoring the built artifacts that show up in your dist/ directory, you can do one of these:

  • (preferred, imo) ensure the "files" key in your package.json lists the directories you want to publish (see docs)
  • create an .npmignore file that does not list dist/. That way npm will not ignore dist/ when you publish (see docs)