UNPKG

4.08 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5"use strict";
6const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
7const ParserHelpers = require("../ParserHelpers");
8const nodeLibsBrowser = require("node-libs-browser");
9
10module.exports = class NodeSourcePlugin {
11 constructor(options) {
12 this.options = options;
13 }
14 apply(compiler) {
15 const options = this.options;
16 if (options === false) {
17 // allow single kill switch to turn off this plugin
18 return;
19 }
20
21 const getPathToModule = (module, type) => {
22 if (type === true || (type === undefined && nodeLibsBrowser[module])) {
23 if (!nodeLibsBrowser[module]) {
24 throw new Error(
25 `No browser version for node.js core module ${module} available`
26 );
27 }
28 return nodeLibsBrowser[module];
29 } else if (type === "mock") {
30 return require.resolve(`node-libs-browser/mock/${module}`);
31 } else if (type === "empty") {
32 return require.resolve("node-libs-browser/mock/empty");
33 } else {
34 return module;
35 }
36 };
37
38 const addExpression = (parser, name, module, type, suffix) => {
39 suffix = suffix || "";
40 parser.hooks.expression.for(name).tap("NodeSourcePlugin", () => {
41 if (
42 parser.state.module &&
43 parser.state.module.resource === getPathToModule(module, type)
44 )
45 return;
46 const mockModule = ParserHelpers.requireFileAsExpression(
47 parser.state.module.context,
48 getPathToModule(module, type)
49 );
50 return ParserHelpers.addParsedVariableToModule(
51 parser,
52 name,
53 mockModule + suffix
54 );
55 });
56 };
57
58 compiler.hooks.compilation.tap(
59 "NodeSourcePlugin",
60 (compilation, { normalModuleFactory }) => {
61 const handler = (parser, parserOptions) => {
62 if (parserOptions.node === false) return;
63
64 let localOptions = options;
65 if (parserOptions.node) {
66 localOptions = Object.assign({}, localOptions, parserOptions.node);
67 }
68 if (localOptions.global) {
69 parser.hooks.expression
70 .for("global")
71 .tap("NodeSourcePlugin", () => {
72 const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(
73 parser.state.module.context,
74 require.resolve("../../buildin/global")
75 );
76 return ParserHelpers.addParsedVariableToModule(
77 parser,
78 "global",
79 retrieveGlobalModule
80 );
81 });
82 }
83 if (localOptions.process) {
84 const processType = localOptions.process;
85 addExpression(parser, "process", "process", processType);
86 }
87 if (localOptions.console) {
88 const consoleType = localOptions.console;
89 addExpression(parser, "console", "console", consoleType);
90 }
91 const bufferType = localOptions.Buffer;
92 if (bufferType) {
93 addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer");
94 }
95 if (localOptions.setImmediate) {
96 const setImmediateType = localOptions.setImmediate;
97 addExpression(
98 parser,
99 "setImmediate",
100 "timers",
101 setImmediateType,
102 ".setImmediate"
103 );
104 addExpression(
105 parser,
106 "clearImmediate",
107 "timers",
108 setImmediateType,
109 ".clearImmediate"
110 );
111 }
112 };
113 normalModuleFactory.hooks.parser
114 .for("javascript/auto")
115 .tap("NodeSourcePlugin", handler);
116 normalModuleFactory.hooks.parser
117 .for("javascript/dynamic")
118 .tap("NodeSourcePlugin", handler);
119 normalModuleFactory.hooks.parser
120 .for("javascript/esm")
121 .tap("NodeSourcePlugin", handler);
122 }
123 );
124 compiler.hooks.afterResolvers.tap("NodeSourcePlugin", compiler => {
125 for (const lib of Object.keys(nodeLibsBrowser)) {
126 if (options[lib] !== false) {
127 compiler.resolverFactory.hooks.resolver
128 .for("normal")
129 .tap("NodeSourcePlugin", resolver => {
130 new AliasPlugin(
131 "described-resolve",
132 {
133 name: lib,
134 onlyModule: true,
135 alias: getPathToModule(lib, options[lib])
136 },
137 "resolve"
138 ).apply(resolver);
139 });
140 }
141 }
142 });
143 }
144};