通过loader实现打包优化

一句话总结:通过配置 pitching-loader 实现按需打包,实现开发模式下打包加速。

背景

在翻项目代码时,发现了个比较有意思的设计,总结下来。

适用于当前端项目单一仓库项目比较庞大,而且还是SPA页面时,需要解决使用 webpack 打包会非常之缓慢问题。

若前端项目页面刚好是按照业务维度划分,所以只需要按照启动时配置秩序打包指定文件夹即可。

解法思路

使用 webpack 自定义 loader 过滤跳过打包文件,进而加快打包速度。

pitching-loader 刚好可以在处理前进行判断,具体可看官方。

实践

通过 webpack-chain 进行修改 webpack 配置。

1
2
3
4
// 在开发环境下配置一个自定义loader
if (process.env.BUILD_ENV === 'development') {
chain.module.rule('vue').use('vue-loader-v15').loader(require.resolve('./loaders/partial-loader.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
// partial-loader.js 实现

// SUB_APP 为当前启动需运行的项目(需打包的文件夹名)
const knownModule = [
'folder-a',
'folder-b',
'folder-c',
].filter(i => i !== process.env.SUB_APP)

// 需排除打包的文件夹名称
let excluded = [...knownModule]

function isSkippedPartial(module, resourceQuery, resourcePath) {
const isForceLoad = resourceQuery && resourceQuery.indexOf('force') > -1
if (isForceLoad) {
console.warn('强制 build', resourcePath)
}

const includedReg = new RegExp(`^((?!${excluded.join('|')}).)*$`)
const isExluded = resourcePath && !resourcePath.match(includedReg)

if (!isForceLoad && isExluded) {
let requiredByRoute = false
try {
let issuer = module.issuer
let i = 0
while (i < 6) {
if (!issuer) {
break
}
if (issuer.resource.endsWith('routes.config.js')) {
requiredByRoute = true
break
}
issuer = issuer.issuer
i += 1
}
} catch {
requiredByRoute = false
}
if (requiredByRoute) {
console.warn('忽略 build', resourcePath)
return true
}
}
return false
}

module.exports = code => code

module.exports.pitch = function pitch() {
if (isSkippedPartial(this._module, this.resourceQuery, this.resourcePath)) {
return ''
}
}

参考

编写 loader