zoro-cli
Version:
https://github.com/vuejs/vue-cli
114 lines (101 loc) • 3.13 kB
JavaScript
const debug = require('debug')('webpack-config')
const WebpackChain = require('webpack-chain')
const merge = require('webpack-merge')
const { defaultsDeep } = require('lodash')
const path = require('path')
const PluginAPI = require('./PluginAPI')
const { defaults } = require('./options')
const envUtil = require('./env')
function resolvePlugins() {
/* eslint-disable import/no-dynamic-require */
const idToPlugin = id => ({
id: id.replace(/^.\//, 'plugin:'),
apply: require(id),
})
/* eslint-enable import/no-dynamic-require */
const plugins = [
// config plugins are order sensitive
'./config/base',
'./config/eslint',
'./config/babel',
'./config/css',
'./config/dev',
'./config/prod',
// app/lib should come at the end, since they may modify the above plugins
'./config/app',
'./config/lib',
].map(idToPlugin)
return plugins
}
class Config {
constructor(options = {}) {
const { args = {} } = options
this.context = process.cwd()
this.webpackChainFns = []
this.webpackRawConfigFns = []
this.initPkg()
this.initProjectOptions()
this.plugins = resolvePlugins()
this.plugins.forEach(({ id, apply }) => {
apply({
api: new PluginAPI(id, this),
// 所有的配置统一合并在 options 里面
options: {
...this.projectOptions,
...args,
},
envUtil,
args,
pkg: this.pkg,
})
})
// apply webpack configs from project config file
if (this.projectOptions.chainWebpack) {
this.webpackChainFns.push(this.projectOptions.chainWebpack)
}
if (this.projectOptions.configureWebpack) {
this.webpackRawConfigFns.push(this.projectOptions.configureWebpack)
}
}
initPkg() {
const pkgPath = path.join(this.context, 'package.json')
/* eslint-disable import/no-dynamic-require */
this.pkg = require(pkgPath)
/* eslint-enable import/no-dynamic-require */
}
initProjectOptions() {
let projectOptions = {}
try {
/* eslint-disable import/no-dynamic-require */
projectOptions = require(path.join(this.context, 'project.config'))
/* eslint-enable import/no-dynamic-require */
} catch (e) {
console.log('could not load project.config')
}
this.projectOptions = defaultsDeep(projectOptions, defaults())
debug(this.projectOptions)
}
resolveChainableWebpackConfig() {
const chainableConfig = new WebpackChain()
// apply chains
this.webpackChainFns.forEach(fn => fn(chainableConfig))
return chainableConfig
}
resolveWebpackConfig(chainableConfig = this.resolveChainableWebpackConfig()) {
// get raw config
let config = chainableConfig.toConfig()
// apply raw config fns
this.webpackRawConfigFns.forEach(fn => {
if (typeof fn === 'function') {
// function with optional return value
const res = fn(config)
if (res) config = merge(config, res)
} else if (fn) {
// merge literal values
config = merge(config, fn)
}
})
return config
}
}
module.exports = Config