webpack
Version:
Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
142 lines (136 loc) • 3.97 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
;
const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
const ParserHelpers = require("../ParserHelpers");
const nodeLibsBrowser = require("node-libs-browser");
module.exports = class NodeSourcePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
const options = this.options;
if (options === false) {
// allow single kill switch to turn off this plugin
return;
}
const getPathToModule = (module, type) => {
if (type === true || (type === undefined && nodeLibsBrowser[module])) {
if (!nodeLibsBrowser[module]) {
throw new Error(
`No browser version for node.js core module ${module} available`
);
}
return nodeLibsBrowser[module];
} else if (type === "mock") {
return require.resolve(`node-libs-browser/mock/${module}`);
} else if (type === "empty") {
return require.resolve("node-libs-browser/mock/empty");
} else {
return module;
}
};
const addExpression = (parser, name, module, type, suffix) => {
suffix = suffix || "";
parser.hooks.expression.for(name).tap("NodeSourcePlugin", () => {
if (
parser.state.module &&
parser.state.module.resource === getPathToModule(module, type)
)
return;
const mockModule = ParserHelpers.requireFileAsExpression(
parser.state.module.context,
getPathToModule(module, type)
);
return ParserHelpers.addParsedVariableToModule(
parser,
name,
mockModule + suffix
);
});
};
compiler.hooks.compilation.tap(
"NodeSourcePlugin",
(compilation, { normalModuleFactory }) => {
const handler = (parser, parserOptions) => {
if (parserOptions.node === false) return;
let localOptions = options;
if (parserOptions.node) {
localOptions = Object.assign({}, localOptions, parserOptions.node);
}
if (localOptions.global) {
parser.hooks.expression
.for("global")
.tap("NodeSourcePlugin", () => {
const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(
parser.state.module.context,
require.resolve("../../buildin/global")
);
return ParserHelpers.addParsedVariableToModule(
parser,
"global",
retrieveGlobalModule
);
});
}
if (localOptions.process) {
const processType = localOptions.process;
addExpression(parser, "process", "process", processType);
}
if (localOptions.console) {
const consoleType = localOptions.console;
addExpression(parser, "console", "console", consoleType);
}
const bufferType = localOptions.Buffer;
if (bufferType) {
addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer");
}
if (localOptions.setImmediate) {
const setImmediateType = localOptions.setImmediate;
addExpression(
parser,
"setImmediate",
"timers",
setImmediateType,
".setImmediate"
);
addExpression(
parser,
"clearImmediate",
"timers",
setImmediateType,
".clearImmediate"
);
}
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("NodeSourcePlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("NodeSourcePlugin", handler);
}
);
compiler.hooks.afterResolvers.tap("NodeSourcePlugin", compiler => {
for (const lib of Object.keys(nodeLibsBrowser)) {
if (options[lib] !== false) {
compiler.resolverFactory.hooks.resolver
.for("normal")
.tap("NodeSourcePlugin", resolver => {
new AliasPlugin(
"described-resolve",
{
name: lib,
onlyModule: true,
alias: getPathToModule(lib, options[lib])
},
"resolve"
).apply(resolver);
});
}
}
});
}
};