UNPKG

4.18 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { cachedSetProperty } = require("../util/cleverMerge");
9const ContextElementDependency = require("./ContextElementDependency");
10const RequireContextDependency = require("./RequireContextDependency");
11const RequireContextDependencyParserPlugin = require("./RequireContextDependencyParserPlugin");
12
13/** @typedef {import("../../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
14/** @typedef {import("../Compiler")} Compiler */
15
16/** @type {ResolveOptions} */
17const EMPTY_RESOLVE_OPTIONS = {};
18
19class RequireContextPlugin {
20 /**
21 * Apply the plugin
22 * @param {Compiler} compiler the compiler instance
23 * @returns {void}
24 */
25 apply(compiler) {
26 compiler.hooks.compilation.tap(
27 "RequireContextPlugin",
28 (compilation, { contextModuleFactory, normalModuleFactory }) => {
29 compilation.dependencyFactories.set(
30 RequireContextDependency,
31 contextModuleFactory
32 );
33 compilation.dependencyTemplates.set(
34 RequireContextDependency,
35 new RequireContextDependency.Template()
36 );
37
38 compilation.dependencyFactories.set(
39 ContextElementDependency,
40 normalModuleFactory
41 );
42
43 const handler = (parser, parserOptions) => {
44 if (
45 parserOptions.requireContext !== undefined &&
46 !parserOptions.requireContext
47 )
48 return;
49
50 new RequireContextDependencyParserPlugin().apply(parser);
51 };
52
53 normalModuleFactory.hooks.parser
54 .for("javascript/auto")
55 .tap("RequireContextPlugin", handler);
56 normalModuleFactory.hooks.parser
57 .for("javascript/dynamic")
58 .tap("RequireContextPlugin", handler);
59
60 contextModuleFactory.hooks.alternativeRequests.tap(
61 "RequireContextPlugin",
62 (items, options) => {
63 if (items.length === 0) return items;
64
65 const finalResolveOptions = compiler.resolverFactory.get(
66 "normal",
67 cachedSetProperty(
68 options.resolveOptions || EMPTY_RESOLVE_OPTIONS,
69 "dependencyType",
70 options.category
71 )
72 ).options;
73
74 let newItems;
75 if (!finalResolveOptions.fullySpecified) {
76 newItems = [];
77 for (const item of items) {
78 const { request, context } = item;
79 for (const ext of finalResolveOptions.extensions) {
80 if (request.endsWith(ext)) {
81 newItems.push({
82 context,
83 request: request.slice(0, -ext.length)
84 });
85 }
86 }
87 if (!finalResolveOptions.enforceExtension) {
88 newItems.push(item);
89 }
90 }
91 items = newItems;
92
93 newItems = [];
94 for (const obj of items) {
95 const { request, context } = obj;
96 for (const mainFile of finalResolveOptions.mainFiles) {
97 if (request.endsWith(`/${mainFile}`)) {
98 newItems.push({
99 context,
100 request: request.slice(0, -mainFile.length)
101 });
102 newItems.push({
103 context,
104 request: request.slice(0, -mainFile.length - 1)
105 });
106 }
107 }
108 newItems.push(obj);
109 }
110 items = newItems;
111 }
112
113 newItems = [];
114 for (const item of items) {
115 let hideOriginal = false;
116 for (const modulesItems of finalResolveOptions.modules) {
117 if (Array.isArray(modulesItems)) {
118 for (const dir of modulesItems) {
119 if (item.request.startsWith(`./${dir}/`)) {
120 newItems.push({
121 context: item.context,
122 request: item.request.slice(dir.length + 3)
123 });
124 hideOriginal = true;
125 }
126 }
127 } else {
128 const dir = modulesItems.replace(/\\/g, "/");
129 const fullPath =
130 item.context.replace(/\\/g, "/") + item.request.slice(1);
131 if (fullPath.startsWith(dir)) {
132 newItems.push({
133 context: item.context,
134 request: fullPath.slice(dir.length + 1)
135 });
136 }
137 }
138 }
139 if (!hideOriginal) {
140 newItems.push(item);
141 }
142 }
143 return newItems;
144 }
145 );
146 }
147 );
148 }
149}
150module.exports = RequireContextPlugin;