入口
bin/vue-cli-service.js
const services=new Service(process.cwd());
services.run(cmd)
service的构造函数中会加载内置的几个plugins
services.run会调用一个核心函数init
init(){
// 处理.env(.mode?)(.local?)等环境变量,使用了dotenv模块,最终会挂在process.env变量上
this.loadEnv(mode);
this.loadEnv();
// 处理并加载vue.config.js
this.loadUserOptions();
// 处理内置插件,registerCommand,
// 内置插件
// built-in:commands/serve
// built-in:commands/build
// built-in:commands/inspect
// built-in:commands/help
// built-in:config/base
// built-in:config/css
// built-in:config/prod
// built-in:config/app
// 执行插件
this.plugins.forEach((id,apply)=>{
// apply来自loadModule的返回值
apply(new PluginAPI(id,this),this.projectOptions);
});
const {fn} = this.commands;
fn();
}
当执行build命令时,最终的fn
会回调到built-in:command/build
vue-cli-service build
cli-service/lib/commands/build/index.js
api.registerCommand(
'build',
{
// ...一些build命令的参数
},
async (args, rawArgs){
// 中间有许多校验逻辑,最终会调用具体的build
await build(...);
}
)
查看下build的具体实现
async function build(args, api, options){
let webpackConfig
// 根据不同搞的target获取默认的webpackConfig
if(target === 'lib'){
}else if(target ==='wc'||target==='wc-async'){
}else{
webpackConfig=require('./resolveAppConfig');
}
// 校验webpack的配置参数
validateWebpackConfig(webpackConfig);
// 最终还是回到webpack,来生成最终的文件
return new Promise((resolve,reject)=>{
webpack(webpackConfig,(error,stats)=>{
// ...
console.log('Build complete')
})
})
}
重点看下resolveAppConfig.js
module.exports=(api:PluginAPI,args,options){
//本质是: new ()();
const config = api.resolveChainableWebpackConfig();
api.resolveWebpackConfig(config);
}
最终又来到service.js
resolveChainableWebpackConfig(){
const wenpackChain=require('webpack-chain');
let chainableConfig = new wenpackChain();
// 将所有的chain重组,定义了非常多的chains规则,这里集中进行了处理
this.webpackChainFns.forEach(fn => fn(chainableConfig))
return chainableConfig;
}
resolveWebpackConfig(chainConfig){
// ...
let config = chainConfig.toConfig(); // 转换为webpack的配置
// ...
return config;
}
重点就来到了对webpack-chain的配置操作
vue的插件
resolvePlugins(){
const idToPlugin = id => ({
id: id.replace(/^.\//, 'built-in:'),
apply: require(id)
})
// 这部分会检索到devDependencies,换而言之,插件只需要在devDependencies声明后就会生效
const projectPlugins = Object.keys(this.pkg.devDependencies || {})
.concat(Object.keys(this.pkg.dependencies || {}))
.filter(isPlugin)
.map(id => {
if (
this.pkg.optionalDependencies &&
id in this.pkg.optionalDependencies
) {
let apply = () => {}
try {
apply = require(id)
} catch (e) {
warn(`Optional dependency ${id} is not installed.`)
}
return { id, apply }
} else {
return idToPlugin(id)
}
})
plugins = builtInPlugins.concat(projectPlugins)
}
所以插件一般的格式为
module.exports=(api:PluginAPI, options){
// ...
// 以下是2个比较重要的函数,可以修改webpack的配置
api.chainWebpack((webpackConfig)=>{
});
api.configureWebpack((webpackConfig)=>{
});
}
再回头看下PluginAPI,就一目了然,对整体越来越理解了
总结
简单来说,就是对webpack包装了一层cli,使用起来无须关注过多的webpack相关的配置,同时也可以充分利用webpack的生态。
收获
ora一个终端旋转器
网友评论