UNPKG

beidou-webpack

Version:

beidou webpack middleware

351 lines (312 loc) 8.24 kB
'use strict'; const is = require('is'); const Plugin = require('./plugin'); const Rule = require('./rule'); const extend = require('extend2'); function toType(obj) { return {}.toString .call(obj) .match(/\s([a-zA-Z]+)/)[1] .toLowerCase(); } class Factory { init() { this.cssExtract = undefined; this.__envFactories = {}; this.__defineloaders = {}; this.__definePlugins = {}; this.__defineRules = {}; } } class WebpackFactory extends Factory { constructor(config, plugins, rules) { super(); this.__webpackConfig = config || {}; this.__plugins = plugins || {}; this.__rules = rules || []; } /** * return new instance for new env * @param {*} env * @return {Object} */ env(env) { if (!env) { throw new Error('Env param is required!'); } const factories = Object.getPrototypeOf(this).__envFactories; if (factories[env]) { return factories[env]; } else { const factory = new WebpackFactory( Object.assign({}, this.__webpackConfig), Object.assign({}, this.__plugins), [].concat(this.__rules) ); factory.env = env; Object.getPrototypeOf(this).__envFactories[env] = factory; return factory; } } getEnv() { return this.env; } /** * generate final plugins config for webpack config * @return {Array} */ getPluginConfig() { const plugins = []; Object.values(this.__plugins).forEach((v) => { plugins.push(v.init()); }); return plugins; } /** * generate final rules config for webpack config * @return {Array} */ getRuleConfig() { const rules = []; this.__rules.forEach((v) => { rules.push(v.toConfig(this)); }); return rules; } /** * generate final config for webpack config * @return {Object} */ getConfig() { const plugins = this.getPluginConfig(); const rules = this.getRuleConfig(); this.__webpackConfig.plugins = plugins; const { module: mod } = this.__webpackConfig; if (!mod) { this.__webpackConfig.module = { rules, }; } else { this.__webpackConfig.module.rules = rules; } return Object.assign({}, this.__webpackConfig); } set(key, config, force = false) { if (toType(config) !== toType(this.__webpackConfig[key])) { force = true; } if (force || is.string(config)) { this.__webpackConfig[key] = config; } else if (is.object(config)) { this.__webpackConfig[key] = extend( true, this.__webpackConfig[key], config ); } else if (is.array(config)) { this.__webpackConfig[key] = this.__webpackConfig[key].concat(config); } return this; } reset(config) { if (config) { this.__webpackConfig = config; } else { this.__webpackConfig = {}; } return this; } get(key, filter) { const keyData = this.__webpackConfig[key]; if (!keyData && filter) { throw new Error( `webpack don't exist the key , ${key} value is undefined!` ); } if (!filter) { return keyData; } if (is.function(filter)) { return filter(keyData); } else if (is.string(filter) || is.number(filter)) { return keyData[filter]; } else { return null; } } addPlugin(...args) { if (args.length === 1 && is.string(args[0])) { if (this.usePlugin(args[0])) { const plugin = this.usePlugin(args[0]); this.__plugins[plugin.alias] = plugin; return this; } else { throw new Error(`${args[0]} the plugin alias not exsit! `); } } if (args.length === 1 && args[0].constructor === Plugin) { const plugin = args[0]; this.__plugins[plugin.alias] = plugin; return this; } const pluginObj = new Plugin(...args); this.__plugins[pluginObj.alias] = pluginObj; return this; } getPlugin(params) { if (is.string(params)) { return this.__plugins[params]; } else if (is.function(params)) { for (const p of Object.values(this.__plugins)) { if (params(p)) { return p; } } return null; } else { throw new Error('get plugin param type exception!'); } } setPlugin(...args) { let pluginObj = {}; if (args.length === 1 && args[0].constructor === Plugin) { [pluginObj] = args; } else { pluginObj = new Plugin(...args); } this.__plugins[pluginObj.alias] = pluginObj; return this; } definePlugin(...args) { const pluginObj = new Plugin(...args); Object.getPrototypeOf(this).__definePlugins[pluginObj.alias] = pluginObj; return this; } usePlugin(filter) { const definePlugins = Object.getPrototypeOf(this).__definePlugins; if (is.string(filter)) { return definePlugins[filter]; } else if (is.function(filter)) { return filter(Object.values(definePlugins)); } else { throw new Error('use plugin param type exception!'); } } getDefinePlugins() { return Object.getPrototypeOf(this).__definePlugins; } clearPlugin() { this.__plugins = {}; } addRule(...args) { if (args.length === 1 && !is.object(args[0])) { const alias = args[0]; if (this.useRule(alias)) { this.__rules.push(this.useRule(alias)); return this; } else { throw new Error(`${args[0]} the rule alias not exsit! `); } } if (args.length === 1 && args[0].constructor === Rule) { this.__rules.push(args[0]); return this; } const ruleObj = new Rule(...args); this.__rules.push(ruleObj); return this; } getRule(params) { if (is.string(params)) { return this.__rules.find( v => { if (v.alias === params) { return true; } if (v.options && v.options.test) { const regexps = v.options.test; if (Array.isArray(regexps)) { for (const regexp of regexps) { if (regexp.test && regexp.test(params)) { return true; } } } else if (regexps instanceof RegExp && regexps.test(params)) { return true; } } return false; } ); } else if (is.function(params)) { for (const rule of this.__rules) { if (params(rule)) { return rule; } } return null; } else if (is.regexp(params)) { return this.__rules.find( v => v.options.test.toString() === params.toString() ); } else { throw new Error('get rule param type exception!'); } } setRule(...args) { let ruleObj = {}; if (args.length === 1 && args[0].constructor === Rule) { [ruleObj] = args; } else { ruleObj = new Rule(...args); } let exsitRule = this.__rules.find( v => v.alias.toString() === ruleObj.alias.toString() ); if (exsitRule) { exsitRule = ruleObj; } else { this.__rules.push(ruleObj); } return this; } defineRule(...args) { const ruleObj = new Rule(...args); Object.getPrototypeOf(this).__defineRules[ruleObj.alias] = ruleObj; return this; } useRule(filter) { const defineRules = Object.getPrototypeOf(this).__defineRules; if (is.function(filter)) { return filter(Object.values(defineRules)); } if (is.regexp(filter)) { return defineRules[filter.toString()]; } if (is.string(filter)) { const rule = Object.values(defineRules).find(v => v.alias === filter); if (rule) { return rule; } } if (is.string(filter)) { return Object.values(defineRules).find(v => v.options.test.test(filter)); } return null; } getDefineRules() { return Object.getPrototypeOf(this).__defineRules; } clearRule() { this.__rules = []; } defineLoader(name, resolve) { Object.getPrototypeOf(this).__defineloaders[name] = resolve || require.resolve(name); return this; } useLoader(name) { return Object.getPrototypeOf(this).__defineloaders[name]; } } module.exports = WebpackFactory;