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