入口
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一个终端旋转器
网络异常,图片无法展示
|