UNPKG

6.82 kBMarkdownView Raw
1# Requizzle #
2
3Swizzle a little something into your Node.js modules.
4
5
6## What's Requizzle? ##
7
8Requizzle provides a drop-in replacement for Node.js's `require()` function. This replacement
9allows you to change a module's source code at runtime.
10
11You can use Requizzle in your test cases, or in production code if you like to live dangerously.
12Requizzle has been tested with Node.js 0.10 and 0.11.
13
14
15## How can I change a module with Requizzle? ##
16
17There are several different ways:
18
19### Look for modules in new places ###
20
21With Requizzle, you can add directories to the module lookup path, which forces Node.js to search
22those directories for modules. This can be useful if:
23
24+ You're tired of writing code like `require('../../../../../lib/foo')`.
25+ You want to expose your app's modules to external plugins. (Without Requizzle, it can be tough to
26do this if the plugin is located outside of your app directory.)
27
28### Add code before or after the module's source code ###
29
30Tamper with modules to your heart's delight by adding arbitrary code before or after the module's
31own source code.
32
33### Mess with child modules ###
34
35When you use Requizzle to require a module, you can force each child module's `require` method to
36inherit your changes to the parent module. (By default, only the parent module is changed.)
37
38
39## Will Requizzle break my dependencies? ##
40
41Probably not. It's true that Requizzle gives you plenty of new and exciting ways to tamper with, and
42possibly break, your module dependencies. But Requizzle also tries not to break anything on its own.
43In particular:
44
45+ **Requizzle preserves strict-mode declarations**. If a module starts with a strict-mode
46declaration, Requizzle keeps it in place. Your changes will appear after the strict-mode
47declaration.
48+ **Requizzle leaves native modules alone**. If you use Requizzle to load one of Node.js's built-in
49modules, such as `fs` or `path`, Requizzle won't mess with it.
50
51
52## Installation ##
53
54With npm:
55
56 npm install requizzle
57
58With git:
59
60 git clone git://github.com/hegemonic/requizzle.git
61 cd requizzle
62 npm install
63
64
65## Usage ##
66
67The Requizzle module exports a single function, which returns a drop-in replacement for
68`require()`.
69
70When you call the function, you must pass in an `options` object, which can include any of these
71properties:
72
73+ `extras`: A pair of functions that return text to insert before or after the module's source code.
74Each function accepts two parameters: `targetPath`, the path to the required module, and
75`parentModule`, the `Module` object for the module's parent. Each function must return a string.
76 + `extras.before`: A function that returns text to insert before the module's source code.
77 + `extras.after`: A function that returns text to insert after the module's source code.
78+ `infect`: Determines whether child modules are infected with the same changes as the parent
79module. Set to `true` to force child modules to inherit your changes. Defaults to `false`.
80+ `requirePaths`: Additional paths to search for required modules. For example, if `requirePaths` is
81set to `['/usr/lib/junk/modules']`, and you save a JavaScript module at
82`/usr/lib/junk/modules/mymodule.js`, you can require the module as `mymodule`.
83
84 You can provide an array of paths, which will be searched before the default module paths, or an
85 object with the following properties:
86
87 + `requirePaths.before`: An array of paths to search before the default module paths.
88 + `requirePaths.after`: An array of paths to search after the default module paths. Use this
89 property if you want the module to use its own local dependencies when possible, then fall back
90 to the additional paths if necessary.
91
92 By default, the require path is not changed.
93
94
95## Examples ##
96
97```js
98var requizzle = require('requizzle');
99
100// Say hello and goodbye to each module.
101var logRequire = requizzle({
102 extras: {
103 before: function(targetPath, parentModule) {
104 return 'console.log("Hello %s!", ' + targetPath + ');\n';
105 },
106 after: function(targetPath, parentModule) {
107 return 'console.log("Goodbye %s!", ' + targetPath + ');\n';
108 }
109 }
110});
111// Prints "Hello /path/to/mymodule.js!" and "Goodbye /path/to/mymodule.js!"
112var myModule = logRequire('mymodule');
113
114// Look for modules in the current module's `lib` directory, and force child
115// modules to do the same.
116var path = require('path');
117var extraPathRequire = requizzle({
118 infect: true,
119 requirePaths: [path.join(__dirname, 'lib')]
120});
121// If `foo` needs to require a module in `./lib`, it can use `require('bar')`
122// instead of `require('./lib/bar')`.
123var foo = extraPathRequire('./foo');
124```
125
126
127## Troubleshooting ##
128
129Here are some problems you may run into when you use Requizzle, along with solutions to each
130problem. If you run into any problems that aren't addressed here, please file a new issue!
131
132### Requizzle slowed down my code! A lot! ###
133
134Requizzle adds minimal overhead to the module-loading process. However, your code will run _much_
135slower than usual if you do both of the following:
136
137+ Use Requizzle's `infect` option.
138+ Require modules that have a lot of `require()` calls within the scope of individual functions.
139
140If Requizzle seems to slow down your app, look for module calls that are within function scope, then
141move them to each module's top-level scope. You can find the biggest offenders by using Node.js's
142built-in `--prof` option to profile your app, then running [node-tick][] to create a report that
143shows the number of ticks per function.
144
145[node-tick]: https://github.com/sidorares/node-tick
146
147### Requizzle made my module do something weird! ###
148
149Do you have any [circular dependencies][circular] in the modules that aren't working? Circular
150dependencies can cause unusual behavior with Requizzle, just as they can without Requizzle. Try
151breaking the circular dependency.
152
153[circular]: http://nodejs.org/api/modules.html#modules_cycles
154
155### Requizzle violates the [Law of Demeter][demeter]! It's an unnatural abomination! ###
156
157Fair enough.
158
159[demeter]: http://en.wikipedia.org/wiki/Law_of_Demeter
160
161
162## Changelog ##
163
164+ 0.2.0 (June 2014): The `requirePaths` option can now contain `before` and `after` properties.
165Paths in the `before` property will be searched first; paths in the `after` property will be
166searched last.
167+ 0.1.1 (June 2014): If the `requirePaths` option is used, the module loader now searches the extra
168paths first rather than last.
169+ 0.1.0 (June 2014): Initial release.
170
171## Acknowledgements ##
172
173Requizzle is very loosely adapted from Johannes Ewald's [rewire](https://github.com/jhnns/rewire)
174module, which is designed to modify a module's behavior for unit testing. If Requizzle doesn't meet
175your needs, please take a look at rewire!
176
177
178## License ##
179
180[MIT license](LICENSE).