vue项目启动探究(vue-cli-service)

执行 npm run dev 命令后 , 入口配置为 package.json , 代码片段如下 :

{ 
  ...
  "script":{
    "dev": "vue-cli-service serve",
	...
  },
  ...
}

根据package.json中的内容 , 执行./node_modules/.bin/vue-cli-service , 里面代码片段如下 : 

node  "%~dp0\..\@vue\cli-service\bin\vue-cli-service.js"

上面代码片段中 , 可以看到执行了 node命令运行 vue-cli-service.js , 找到 ./node_modules/@vue/cli-service/bin/vue-cli-service.js 这个node入口, 代码片段如下

  const Service = require('../lib/Service')
  const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
  
  //... ... ...
  
  // 执行service方法传入:'serve'、agrs、['serve','--open',...]
  service.run(command, args, rawArgv).catch(err => {
    error(err)
    process.exit(1)
  })

上面代码实例化了 Service类并执行run方法 ; 其中 Service类来自 node_modules\@vue\cli-service\lib\Service.js , 代码片段如下

// ... ...
module.exports = class Service {
  //构造函数 , 初始化配置
  constructor(context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {
    ...
    // 获取package.json中的依赖
    this.pkg = this.resolvePkg(pkg)

    //初始化相关插件。相关插件包括:内联插件、package.json中的cli-plugin-*插件。内联插件包含serve、build、inspect等。    
    // 如果有内联插件,不使用package.json中找到的插件
    // 最终得到的plugins为内置插件+@vue/cli-plugin-*
    // {id: 'xxx',apply: require('xxx')}
    this.plugins = this.resolvePlugins(plugins, useBuiltIn)

    // 解析每个命令使用的默认模式
    //{ serve: 'development',
    // build: 'production',
    // inspect: 'development' }
    this.modes = this.plugins.reduce((modes, { apply: { defaultModes }}) => {
      return Object.assign(modes, defaultModes)
    }, {})
  }

  resolvePkg (inlinePkg, context = this.context) {...}

  init (mode = process.env.VUE_CLI_MODE) {...}

  loadEnv (mode){...}

  setPluginsToSkip (args) {...}

  resolvePlugins (inlinePlugins, useBuiltIn){...}

  async run (name, args = {}, rawArgv = []){
    ...
    //name=serve ; 执行 /node_modules/@vue/cli-service/lib/commands/serve.js
    let command = this.commands[name]
    ...
    const { fn } = command
    return fn(args, rawArgv)
  }

  resolveChainableWebpackConfig () {...}

  resolveWebpackConfig (chainableConfig = this.resolveChainableWebpackConfig()){...}

  //加载用户配置。读取vue.config.js文件内部的配置
  loadUserOptions () {
    const possibleConfigPaths = [
      process.env.VUE_CLI_SERVICE_CONFIG_PATH,
      './vue.config.js',
      './vue.config.cjs'
    ]
    ...
  }
}

最终执行的node_modules/@vue/cli-service/lib/commands/serve.js 内注册serve时传递的方法。
webpack获取到配置之后,实例化Compiler 传递给webpackDevServer,通过webpackDevServer实现自动编译和热更新。

// serve.js serve函数
async function serve (args) {
  //创建webpack编译器
  const compiler = webpack(webpackConfig)
  // compiler.run()即可完成一次编译打包

  // 创建本地服务
  const server = new WebpackDevServer(compiler, Object.assign({
      clientLogLevel: 'none',
      historyApiFallback: {
        disableDotRule: true,
        rewrites: [
          { from: /./, to: path.posix.join(options.baseUrl, 'index.html') }
        ]
      },
      contentBase: api.resolve('public'),
      watchContentBase: !isProduction,
      hot: !isProduction,
      quiet: true,
      compress: isProduction,
      publicPath: options.baseUrl,
      overlay: isProduction // TODO disable this
        ? false
        : { warnings: false, errors: true }
    }, projectDevServerOptions, {
      https: useHttps,
      proxy: proxySettings,
  }))
  
  return new Promise((resolve, reject) => {
    compiler.hooks.done.tap('vue-cli-service serve', stats => {
        // ...
    })
    // ...
    server.listen(port, host, err => {
        if (err) {
          reject(err)
        }
    })
  })
}

 

posted on 2022-01-05 17:49  hi-gdl  阅读(5410)  评论(0编辑  收藏  举报

导航