UNPKG

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