# webpack整理
# 基础概念
# 过滤指定模块的插件
掘金地址:https://juejin.cn/post/7108255306609590286 (opens new window)
const path = require('path')
const fs = require('fs')
const os = require('os')
// 1、只需要在routes/pages添加需要构建的文件名称
// 2、过滤阶段,除了必须的模块,比如common,home
class ineedCompileDirectoryPlugin {
constructor() {
this.name = 'webpack-lingke-ignore-plugin'
this.checkIgnore = this.checkIgnore.bind(this)
this.configPath = path.join(__dirname, './ignore-plugin-config.json')
this.config = null
// 过滤的模块
this.ignoreRoutes = []
this.ignorePages = []
// 过滤正则
this.ignores = []
// 必须,不能被过滤的模块
this.requiredRoutes = ['common', 'dev', 'systemManegement']
this.requiredPages = ['dev', 'error', 'layout', 'system', 'config', 'home']
this.buildAll = false
this.init()
}
isExistConfig() {
return fs.existsSync(this.configPath)
}
init() {
this.config = this.getConfig()
let {
buildRoutes,
buildPages,
buildAll
} = this.config
// config中不管有没有配置,都要加上不能被过滤的模块,否则会影响整个系统项目构建
buildRoutes = [...new Set(buildRoutes.concat(this.requiredRoutes))]
buildPages = [...new Set(buildPages.concat(this.requiredPages))]
console.log("build Routes: ", buildRoutes)
console.log("build Pages: ", buildRoutes)
const routerPath = path.join(__dirname, '../src/router')
const pagePath = path.join(__dirname, '../src/page')
const allRoutes = fs.readdirSync(routerPath, 'utf-8')
const allPages = fs.readdirSync(pagePath, 'utf-8')
const routes = allRoutes.filter(r => !buildRoutes.includes(r) && r.indexOf('.') === -1)
const pages = allPages.filter(p => !buildPages.includes(p) && p.indexOf('.') === -1)
this.ignoreRoutes = routes
this.ignorePages = pages
this.buildAll = buildAll
this.initIgnores()
}
getConfig() {
if (!this.isExistConfig()) {
console.log('=== ignore-plugin初始化配置 ===')
this.initConfig()
console.log('=== ignore-plugin初始化成功,请配置后重新运行命令 ===')
console.log('=== 查看配置文件如下 ===')
console.log('=== ' + this.configPath + ' ===')
process.exit(0)
}
return JSON.parse(fs.readFileSync(this.configPath, 'utf-8'))
}
setConfig(routes, pages) {
const configJson = {
desc: [
"1. buildAll: 构建全部",
"2. routes: 需要构建的路由",
"3. pages: 需要构建的页面",
"4. remarks: 因为项目结构原因,不能清晰找出页面绑定的路由关系,所以只能通过page + route的方式控制构建"
],
buildAll: false,
buildRoutes: routes,
buildPages: pages
}
fs.writeFileSync(this.configPath, JSON.stringify(configJson, null, 2), 'utf-8')
}
initConfig() {
const buildRoutes = [...this.requiredRoutes]
const buildPages = [...this.requiredPages]
// 没有配置时
buildRoutes.push('customerCenter')
buildPages.push('customerCenter')
this.setConfig(buildRoutes, buildPages)
}
initIgnores() {
const platform = os.platform()
const isMac = platform === 'darwin'
console.log("current platform: ", platform)
this.ignoreRoutes.forEach(e => {
let regPath = isMac ? 'src/router/' : 'src\\router\\'
this.ignores.push(new RegExp(regPath + e))
})
this.ignorePages.forEach(e => {
let regPath = isMac ? 'src/page/' : 'src\\page\\'
this.ignores.push(new RegExp(regPath + e))
})
}
checkIgnore(resolveData) {
if (!resolveData) {
return resolveData
}
let {
context,
request
} = resolveData
if (request.indexOf('node_modules') !== -1 || context.indexOf('node_modules') !== -1) {
return resolveData
}
let absReq = ''
// 相对路径,则直接拼接
if (request.indexOf('.') === 0) {
absReq = path.join(context, request)
} else if (request.indexOf('@') === 0) {
// 路径别名,则替换
absReq = request.replace('@', path.join(__dirname, '../src'))
} else {
// 说明它是第三方模块或者内置模块,比如require('fs'), require('core')
// 不需要理会
absReq = ''
}
try {
if (absReq) {
if (absReq.indexOf('src/router') !== -1 || absReq.indexOf('src/page') !== -1) {
// 如果在正则中匹配不到
if (this.ignores.some(r => r.test(absReq))) {
return false
}
}
}
} catch (e) {
console.log('error: ')
console.log(context)
console.log(request)
console.log(absReq)
console.log(e)
}
return resolveData
}
apply(compiler) {
if (this.buildAll) {
return
}
compiler.hooks.normalModuleFactory.tap(this.name, (nmf) => {
nmf.hooks.beforeResolve.tap(this.name, this.checkIgnore)
})
compiler.hooks.contextModuleFactory.tap(this.name, cmf => {
cmf.hooks.beforeResolve.tap(this.name, this.checkIgnore)
})
compiler.hooks.done.tap(this.name, () => {
// 构建结束做些什么
})
}
}
module.exports = {
ineedCompileDirectoryPlugin
}