美文网首页
vue-cli-serve

vue-cli-serve

作者: 许彦峰 | 来源:发表于2022-03-26 15:08 被阅读0次

    入口

    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一个终端旋转器

    相关文章

      网友评论

          本文标题:vue-cli-serve

          本文链接:https://www.haomeiwen.com/subject/esksjrtx.html