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

ti-commonjs

v0.0.1

Published

Node.js style require() in Titanium via Alloy

Downloads

3

Readme

ti-commonjs Appcelerator Titanium Built with Grunt Gittip

Node.js-style CommonJS in Appcelerator Titanium via Alloy. For full details on what exactly this means, check out Node.js's own documentation on its CommonJS implementation. In addition to this added functionality, ti-commonjs also eliminates all platform-specific disparities in Titanium's CommonJS implementation.

Requirements

It is distinctly possible that ti-commonjs will work with earlier versions of both Titanim and Alloy, but they are untested and unsupported.

Install NPM version

Assuming you're in your Alloy project's root folder (not the app folder):

npm install ti-commonjs --prefix ./app/lib

Aside from installing ti-commonjs, this will also add the alloy.jmk file (or modifications to existing alloy.jmk) necessary to post-process your generated runtime files. Read here for more details on alloy.jmk files.

Usage

absolute paths (relative to "Resources" folder)

require('/foo/bar');

relative paths

require('../../someModule');
require('./someModuleInCurrentFolder');
require('.././some/ridiculous/../../path');

loading from node_modules folder

Load modules installed via npm in Resources/node_modules. Full details here.

var _ = require('underscore');
require('ti-mocha');

You can also target specific files within those npm installations. For example, let's take should.js. While you can't require it directly in Titanium, due to its reliance on node.js libraries, you can reference the single-file Titanium-compatible version embedded in the installation. This tactic works with almost every npm distributed module that has a browser-compatible version.

var should = require('should'); // ERROR - missing node.js libraries

var should = require('should/should'); // WOOHOO! It works in Titanium.

folders as modules

If a folder contains a package.json, the path in its main property will be loaded as a module. Additionally, a module named index.js can be referenced just by its folder's name. The following example demonstrates both uses. Full details here.

/foo/package.json

{
	"main": "./lib/quux"
}

/app.js

// assuming the module "Resources/foo/lib/quux.js" exists...
var foo = require('/foo');

// assuming the module "Resources/bar/index.js" exists...
var bar = require('/bar');

loading JSON files

You can now load JSON files simply with require().

console.log(require('/package.json').main);

// prints "./lib/ti-commonjs.js"

require.resolve()

Get the full path resolved path to a module.

require.resolve('/foo/bar.js') === require.resolve('/.././foo/../foo/bar');

require.main

Every require function now has a reference to the main module (app.js). Full details here.

/foo/bar.js

require.main.id === '.' && require.main.filename === '/app.js'

load module with or without extensions

require('/foo') === require('/foo.js')

"module" object

Titanium's implementation gives limited access to the properties of the module object. With ti-commonjs.js you have full access to the following properties and functions. Full details here.

Use the Titanium require()

Just in case you still need to use the old require() from Titanium, it's still accessible via tirequire().

require('/foo') === tirequire('foo')

FAQ

Why is this so cool?

Because now you can start leveraging the power of node.js and npm package management in your Alloy apps.

$ npm install --prefix ./app/lib ti-mocha should underscore

alloy.js

var should = require('should/should'), // require the broswer-compatible version in should
	_ = require('underscore');
require('ti-mocha');

describe('ti-commonjs', function() {
	it('should work', function() {
		_.each([1,2,3], function(num) {
			num.should.equal(num);
		});
	});
});
mocha.run();

Should I use ti-commonjs.js?

cons

  • It will probably break your existing Titanium code. The primary reason for this is fundamental difference in specifying absolute paths with Titanium's require() vs. ti-commonjs.js. This example illustrates, assuming that a module exists at Resources/foo/bar.js:
// This is how it's done with Titanium's require()
require('foo/bar');

// and this is how its done with ti-commonjs.js
require('/foo/bar');

pros

  • This is the CommonJS implementation and require() usage that will be supported in Titanium 4.0 (Lovingly being referred to as Ti.Next). You can start future-proofing your apps now.
  • You get all of the great features listed in the Usage section.
  • You can install and distribute modules via npm! no more digging through github or Q&A posts.
  • Eliminates all platform-specific disparities in Titanium's CommonJS implementation.
  • It becomes much easier to port existing node.js modules to Titanium. Many you'll be able to use now without any modifications.
  • It is much easier for incoming node.js developers to start using Titanium with this more familiar CommonJS implementation.

How does it work?

ti-commonjs.js overides the existing Titanium require() to have node.js-style functionality. It sits directly on top of Titanium's existing module implementation so all module caching is preserved, no wheels are re-invented. It does this by invoking the main ti-commonjs function with the current __dirname then returns a curried function as the new require().

To truly make the usage seamless, though, your generated Javascript files need a CommonJS wrapper, much like is done in the underlying engine itself. The wrapper looks like this:

app.js

(function(_require,__dirname,__filename) {
	var require = _require('ti-commonjs')(__dirname);

	// your code..

})(require,'/','/app.js');

Why can't I just create a new require variable?

Because you'd be conflicting with the require already in the scope of every module.

var require = require('ti-commonjs'); // CONFLICT with global require

Why can't I just override require() in my app.js?

I should just be able to take advantage of Titanium's scoping with respect to the app.js file and have require() overridden everywhere, right? Well, you're right, but that's where the problem lies. The issue is that require() needs to be executed relative to the current file's directory when it comes to relative paths. This is further compounded by properties like require.paths. Globally overriding require(), though, will make all paths relative to Resources. Let me demonstrate.

app.js

require = require('ti-commonjs');
require('/1/2/3/threeModule')();

1/2/3/threeModule.js

module.exports = function() {
	// DISASTER! You'd think you were referencing '/1/2/3/../twoModule' here,
	// but because the relative directory was established in the app.js
	// you are instead referencing '/../twoModule'. This will end in a
	// runtime error.
	require('../twoModule')();
};

1/2/twoModule.js

module.exports = function() {
	console.log();
};

What are the caveats?

  • module.parent and module.children cannot be supported since the underlying Titanium require() provides no means to get them or assign them to a module. To be able to support this, a change would be required in Titanium. Fortunately, these are rarely used.
  • This implementation does not load modules with the .node extension, as those are for node.js compiled addon modules, which make no sense in the context of Titanium.
  • ti-commonjs.js does not load from global folders (i.e., $HOME/.node_modules), as they are not relevant to mobile app distributions.