Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Last active September 13, 2017 16:03
Show Gist options
  • Save mattdesl/aaf759da84cc44c22305 to your computer and use it in GitHub Desktop.
Save mattdesl/aaf759da84cc44c22305 to your computer and use it in GitHub Desktop.

agnostic modules

Most of the modules I write are "agnostic" in that they should work in Node, browserify, webpack, Rollup, jspm... hell, even Unreal.js. It's just ES5, CommonJS and a few quirks like process.nextTick or require('path') (which browserify and webpack will shim).

Other modules are a bit trickier, and need to include a static asset like HTML, GLSL or another file.

In Node you might see this:

var fs = require('fs')
var path = require('path')
var html = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8')

If I specify brfs in my package.json config, the above code will work fine when the end-user installs and uses my module with browserify (even if it's deep in their dependency tree). The asset gets statically inlined during the bundle step.

This is great since the module has a single entry point for both node and the browser, and I can test/develop with node, nodemon and tape.This approach can even handle large base64/binary files as a Buffer; while it may not be great for a web application, it can be great for quick prototyping in the browser.

However, this approach is incompatible with webpack and other bundlers. Examples of problematic modules which depend on a browserify transform:

solutions

transform-loader

Webpack has a thing called transform-loader. This is more of a hack, and it forces configuration on the end-user of your module. It's not automatically resolved, see #378 – whereas browserify transforms are resolved per module. This is especially annoying with dependencies-of-dependencies.

Further, it assumes that your end-user is either using browserify or webpack. Other bundlers like jspm and Rollup will not work.

Update Jan 2016

ify-loader can now be used in Webpack configs to resolve browserify transforms automatically across your node_modules, as browserify intends it to be. This fixes the automatic transform resolution, but does not solve the end-user configuration problem.

bundling

You can run your module through webpack or browserify, but this will lead to duplication in the end-user's final bundle, since some dependencies may be getting bundled twice and won't be de-duplicated by browserify/webpack.

It also makes your published code pretty ugly to look at, and you'll want to add source maps.

Update Dec 2015

With webpack, you can use external to avoid bundling a module and preserve de-duplication. See the discussion thread below.

babel plugin

I think it would be great if somebody developed a Babel plugin/transform that supports browserify transform streams listed in package.json "browserify" field. This would allow you to transpile the source rather than bundling it, fixing the dedupe issue.

I'm not sure how complex this is, and whether it carries other problems.

Update Jan 2016

babel-plugin-webpack-loaders can now be used which may help build "agnostic modules" by transpiling webpack loaders on pre-publish (like CSS or HTML inlining). However, it is a bit klunky since Babel is not designed to run asynchronous source transforms.

simple transpiler

Another solution is if somebody build a source transpiler that doesn't try to bundle code (like browserify/webpack) but instead just tries to support browserify transforms.

This way you can publish an npm dist that looks exactly like the source entry point, but with static files inlined so that it works in Node, browserify, webpack, etc.

Update Jan 2016

With transpilify (work in progress) you can transpile a source file with simple browserify transforms, but without adding the overhead of the bundler itself.


Sadly all of these solutions require more configuration and setup in one way or another, adding some overhead for module authors. :)

This is closely related with some of the things webpack tries to solve, like handling image and SVG assets. I think it would be novel if there was a standardized solution that supported Node and all modern bundlers... But I think a more realistic goal (for now) is just to get ASCII assets (HTML/GLSL/text/etc) working.

@mattdesl
Copy link
Author

mattdesl commented Jan 3, 2016

Two new things:

@mattdesl
Copy link
Author

mattdesl commented Jan 4, 2016

@ahdinosaur
Copy link

@mattdesl 😻

@tbroyer
Copy link

tbroyer commented Feb 10, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment