前言
Service
的run函数其实很简单,但是第一次看会有点懵
代码很简单,主要做了几件事:
- 确定命令的运行模式
const mode = args.mode || (name === 'build' && args.watch ? 'development' : this.modes[name])
- 设置可忽略的插件
this.setPluginsToSkip(args)
- 初始化
this.init(mode)
- 获取到命令行实体
let command = this.commands[name]
- 运行命令行
...
return fn(args, rawArgv)
主要比较懵的是第四点和第五点 这就要涉及到另外一个类\@vue\cli-service\lib\PluginAPI.js
PluginAPI.js
PluginAPI其实可以理解成为插件的基类,它主要是定义了插件加载时候可用的函数。
在init
代码中有这么一段:
// apply plugins.
this.plugins.forEach(({ id, apply }) => {
if (this.pluginsToSkip.has(id)) return
apply(new PluginAPI(id, this), this.projectOptions)
})
我们在构造函数中整理了plugins列表后,真正把pluginsId转换为command的其实是上面的代码
以serve指令为例
我们可以看到serve的export代码:
//serve,js
module.exports = (api, options) => {
api.registerCommand(
...
)
}
实际上其他指令
build
,help
,inspect
的exports都是一样带有两个参数的函数
接下来我们看看PluginAPI
的registerCommand
方法
registerCommand (name, opts, fn) {
if (typeof opts === 'function') {
fn = opts
opts = null
}
this.service.commands[name] = { fn, opts: opts || {}}
}
所以第四点和第五点的commands
和fn
就是通过这个函数来的。
接下来我们看看serve
的fn
具体做了什么:
- 对一些值进行初始化(http协议的选择,url的组成,proxy等等)
...
// resolve server options
const useHttps = args.https || projectDevServerOptions.https || defaults.https
const protocol = useHttps ? 'https' : 'http'
const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port
const port = await portfinder.getPortPromise()
const rawPublicUrl = args.public || projectDevServerOptions.public
...
- 创建一个webpack的compiler
- 初始化webpack-dev-server
webpack-dev-server一个小型的nodejs静态文件服务器,它可以在compiler生成资源文件后提供Web服务
- 把通过webpack生成的目录文件通过webpack-dev-server发布,并监听变化。
以上就是npm run server
的主要流程。
从上面可以看到核心是在webpack compiler
和webpack-dev-server
所以接下来会进行研究webpack。