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`: Additional paths to search for required modules. For example, if `requirePaths` is
|
81 | 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`.
|
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
|
98 | var requizzle = require('requizzle');
|
99 |
|
100 | // Say hello and goodbye to each module.
|
101 | var 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!"
|
112 | var myModule = logRequire('mymodule');
|
113 |
|
114 | // Look for modules in the current module's `lib` directory, and force child
|
115 | // modules to do the same.
|
116 | var path = require('path');
|
117 | var 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')`.
|
123 | var foo = extraPathRequire('./foo');
|
124 | ```
|
125 |
|
126 |
|
127 | ## Troubleshooting ##
|
128 |
|
129 | Here are some problems you may run into when you use Requizzle, along with solutions to each
|
130 | problem. 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 |
|
134 | Requizzle adds minimal overhead to the module-loading process. However, your code will run _much_
|
135 | slower 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 |
|
140 | If Requizzle seems to slow down your app, look for module calls that are within function scope, then
|
141 | move them to each module's top-level scope. You can find the biggest offenders by using Node.js's
|
142 | built-in `--prof` option to profile your app, then running [node-tick][] to create a report that
|
143 | shows 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 |
|
149 | Do you have any [circular dependencies][circular] in the modules that aren't working? Circular
|
150 | dependencies can cause unusual behavior with Requizzle, just as they can without Requizzle. Try
|
151 | breaking 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 |
|
157 | Fair 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.
|
165 | Paths in the `before` property will be searched first; paths in the `after` property will be
|
166 | searched last.
|
167 | + 0.1.1 (June 2014): If the `requirePaths` option is used, the module loader now searches the extra
|
168 | paths first rather than last.
|
169 | + 0.1.0 (June 2014): Initial release.
|
170 |
|
171 | ## Acknowledgements ##
|
172 |
|
173 | Requizzle is very loosely adapted from Johannes Ewald's [rewire](https://github.com/jhnns/rewire)
|
174 | module, which is designed to modify a module's behavior for unit testing. If Requizzle doesn't meet
|
175 | your needs, please take a look at rewire!
|
176 |
|
177 |
|
178 | ## License ##
|
179 |
|
180 | [MIT license](LICENSE).
|