-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
Copy pathMultiPlatformPlugin.ts
87 lines (73 loc) · 2.79 KB
/
MultiPlatformPlugin.ts
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
import * as path from 'node:path'
import helper, { REG_NODE_MODULES } from '@tarojs/helper'
interface IOptions {
include?: string[]
chain?: any
}
/**
* @description 此 enhance-resolve 插件用于根据当前编译的平台,解析多端文件的后缀
*
* @property {string} source resolver hook 类别
* @property {string} target 解析完成后需要触发的钩子
* @property {IOptions} options 插件配置项
*
* @example
* there's filepath 'src/index'
* when platform is weapp, we get 'src/index.weapp.[js|ts|jsx|tsx]'
* when platform is h5, we get 'src/index.h5.[js|ts|jsx|tsx]'
* by default, we get 'src/index.[js|ts|jsx|tsx]'
*
* @class MultiPlatformPlugin
*/
export class MultiPlatformPlugin {
private source: string
private target: string
private options: IOptions
constructor (source: string, target: string, options?: IOptions) {
this.source = source
this.target = target
this.options = options || {}
}
public apply (resolver) {
const target = resolver.ensureHook(this.target)
resolver
.getHook(this.source)
.tapAsync('MultiPlatformPlugin', (request, resolveContext, callback) => {
const innerRequest: string = request.request || request.path
if (!innerRequest || (request.context.hasOwnProperty('issuer') && !request.context.issuer)) return callback()
if (!path.extname(innerRequest)) {
let srcRequest: string
if (path.isAbsolute(innerRequest)) {
// absolute path
srcRequest = innerRequest
} else if (!path.isAbsolute(innerRequest) && /^\./.test(innerRequest)) {
// relative path
srcRequest = path.resolve(request.path, request.request)
} else {
return callback()
}
if (REG_NODE_MODULES.test(srcRequest) && !this.includes(srcRequest)) {
return callback()
}
const extensions = this.options.chain?.resolve?.extensions?.values()
const newRequestStr = helper.resolveMainFilePath(srcRequest, extensions)
if (newRequestStr === innerRequest) return callback()
const obj = Object.assign({}, request, {
request: newRequestStr
})
return resolver.doResolve(target, obj, 'resolve multi platform file path', resolveContext, (err, result) => {
if (err) return callback(err)
if (result === undefined) return callback(null, null)
return callback(null, result)
})
}
callback()
})
}
private includes (filePath: string): boolean {
if (!this.options.include || !this.options.include.length) return false
filePath = filePath.replace(/[\\/]/g, '/')
const res = this.options.include.find(item => filePath.includes(item))
return Boolean(res)
}
}