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