This repository has been archived by the owner on Sep 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 63
/
index.js
119 lines (106 loc) · 3.54 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import _ from 'lodash'
import fs from 'fs'
import path from 'path'
import { stubs } from './listing'
import { features, overrides } from './mapping'
const lodashRoot = path.dirname(require.resolve('lodash'))
const normalize = (string) => string.replace(reFwdSep, rsSysSep)
const reFwdSep = /\//g
const rsSysSep = _.escapeRegExp(path.sep)
const reLodashRes = RegExp(normalize('lodash(?:/(?!fp/)|-amd/|-es/|\\.\\w+/)'))
const reExplicitReq = RegExp('^lodash(?:/|-amd/|-es/|\\.\\w+/)\\w+$')
function getPatterns(options) {
const result = []
_.forOwn(features, (pairs, key) => {
if (!options[key]) {
result.push(...pairs)
}
})
return result
}
/*----------------------------------------------------------------------------*/
class LodashModuleReplacementPlugin {
constructor(options) {
this.matches = []
this.options = Object.assign({}, options)
this.patterns = getPatterns(this.options)
this.resolve = this.resolve.bind(this)
}
apply(compiler) {
const resolve = _.memoize(this.resolve, ({ resource }) => resource)
/* Webpack >= 4 */
if (compiler.hooks) {
compiler.hooks.normalModuleFactory.tap('LodashModuleReplacementPlugin', (nmf) => {
nmf.hooks.afterResolve.tap('LodashModuleReplacementPlugin', (data) => {
if (data) {
data.resource = resolve(data)
}
return data
})
})
} else {
compiler.plugin('normal-module-factory', (nmf) => {
nmf.plugin('after-resolve', (data, callback) => {
if (data) {
data.resource = resolve(data)
return callback(null, data)
}
return callback()
})
})
}
}
resolve({ rawRequest, resource }) {
let result = resource
if (!reLodashRes.test(resource)) {
return result
}
const isExplicit = reExplicitReq.test(rawRequest)
const resName = path.basename(resource, '.js')
const resRoot = path.dirname(resource)
if (isExplicit) {
// Apply any feature set overrides for explicitly requested modules.
const override = overrides[path.basename(rawRequest, '.js')]
if (!_.isMatch(this.options, override)) {
this.patterns = getPatterns(Object.assign(this.options, override))
}
}
this.patterns.forEach((pair) => {
// Replace matches as long as they aren't explicit requests for stubbed modules.
const isStubbed = _.includes(stubs, pair[1])
if (resName != pair[0] || (isExplicit && isStubbed)) {
return
}
const moduleFilename = `${pair[1]}.js`
let modulePath = path.join(resRoot, moduleFilename)
let exists = fs.existsSync(modulePath)
if (isStubbed && !exists) {
exists = true
modulePath = path.join(lodashRoot, moduleFilename)
}
if (exists) {
result = modulePath
this.matches.push([resource, result])
return false
}
})
return result
}
};
/*----------------------------------------------------------------------------*/
export default function Plugin(nodeResolve, options) {
// For Webpack.
if (this instanceof Plugin) {
return new LodashModuleReplacementPlugin(nodeResolve)
}
// For Rollup.
const _resolveId = nodeResolve.resolveId
const resolver = new LodashModuleReplacementPlugin(options)
const resolve = _.memoize(resolver.resolve, ({ resource }) => resource)
return Object.assign({}, nodeResolve, {
resolveId(importee, importer) {
return _resolveId(importee, importer)
.then((id) => resolve({ 'rawRequest': importee, 'resource': id }))
}
})
};