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

builder-js-package

v1.0.0

Published

A generic build setup for JavaScript packages.

Downloads

14

Readme

builder-js-package

A generic build setup for JavaScript packages.

npm i builder-js-package --save-dev

Short version: Write source code and don't worry about how make it work everywhere.

Long version: A Builder archetype (i.e. shared project structure, shared build configuration, and shared tasks and procedures) for making, building, and publishing JS-only packages in a way that makes them:

  • compatible in many different build systems and environments (f.e. Webpack, Rollup, Babel, Meteor, RequireJS, globals, Node.js)
  • consumable in with different module formats like AMD, UMD, CommonJS, and ES Modules
  • publishable to different registries like NPM, Bower, and JSPM

Example projects using this Builder archetype are:

Notice in those projects that they have no dependencies on any build tools and no build configurations, and that they reference only this shared Builder archetype.

NOTE: This project initially meets needs for my own JavaScript packages, and as such may not be a perfect fit for your needs.

I'd like to make this easy to extend and even more generic to fit any needs, so that only few modifications are needed in order to adopt its use for more specific cases (f.e. adding babel plugins or webpack loaders and configs). See TODO.

Requirements

  • Node v9+ (might work with lower versions, not tested)
  • NPM v5+ (might work with lower versions, not tested)
  • If you don't have a graphical display (f.e. in Linux without a desktop) install xvfb - see https://github.com/electron/electron/blob/v1.4.10/docs/tutorial/testing-on-headless-ci.md

Project Structure

(Note! This part is TODO, but shared configs and procedures work. For now, see the above example projects, which all share a similar structure, to get an idea of how to structure a project in order to use this Builder archetype)

build-init builder-js-package will create a new project with the following structure. If you have an existing package that you'd like to use this on, then you will have to modify it to follow the following structure.

src               # all source files go here, as well as test.js files
  index.js        # entry point
  index.test.js   # co-located test files
  ...             # any other files imported by entry point, and associated test files
tests             # also scanned for test.js files
.gitignore        # things to ignore
package.json
.builderrc        # required, specify this builder archetype in there (see Builder docs).
builder.config.js # optional config options

This builder archetype will output compiled .js files from src along with .js.map source maps into the root of the repo (yes, you read that correctly, you should not have any files at the top level of src that are the same name as files in the root of the repo).

A global.js (and source map) is also outputted, containing the global version of the lib that can be easily loaded on a website using a script tag.

Config

This archetype can be configured with a builder.config.js file at the root of the project.

Options (so far):

module.exports = {
	// If set to `false` or an empty string, then the global build will not add a
	// global variable into the environment. Otherwise, the library's exports will
	// be assigned onto a global variable of the name defined here. Defaults to
	// the name of the package if omitted (minus the @scope/ part if the package
	// names is scoped).
	globalName: '...', // A string, `false`, or `undefined`

	// a list of node modules (by name) that should be compiled.
	nodeModulesToCompile: [
		'some-package',
		// ...
	],

	// TODO babel option
}

Caveat

This Builder archetype uses a combination of Babel to build code. Specifically, it transpiles for..of loops with Babel in "loose" mode, which means the result is not spec compliant, but leaner and faster in many cases although it will not work with Iterators and Generators.

This means, in projects built with this Builder archetype, you'll have to either not iterate on things like Map or Set using for..of directly (f.e. use Arrays instead), or use Array.from. For example:

const items = new Set(...)

// will NOT work
for (const item of items) {
    console.log(item)
}

// works
for (const item of Array.from(items)) {
    console.log(item)
}

const pairs = new Map(...)

// will NOT work
for (const [key, value] of pairs) {
    console.log(key, value)
}

// works
for (const [key, value] of Array.from(pairs)) {
    console.log(ikey, value)
}

TODOs

  • [ ] Allow override of Babel config
  • [ ] Allow override of Webpack config
  • [ ] Don't commit global.js (and its map) on version changes, we can tell people to get it from unpkg, GitHub, and how to build it.
  • [ ] Output both a global.js and global.min.js
  • [ ] Source maps! Important! (so far exists for global.js, but not the other files)
  • [x] Important! Don't run git stash during version script if there's nothing to stash, otherwise it will pop a previous stash after npm version is done.
  • [ ] A project template for generating new projects with builder-init. Probably a Yeoman generator. (update the Project Structure section above accordingly)
  • [x] Testing (added Karma)
  • [ ] Code coverage (Karma is in place, just need to hook up the tasks)
  • [ ] Continuous integration
  • [ ] Fix the previous caveat in a way that can build for both old and new browsers so that at least new browsers don't have a ton of unnecessary overhead in build output. We'll probably use @babel/preset-env for this.
    • [ ] Maybe we can offer a dev and production server that can automatically detect browsers and serve appropriate builds.
  • [ ] Move babel plugins and transforms to a custom babel preset, so we can keep package.json dependencies clean? Other benefits?