vue-cli系列之vue-cli-service整体架构的示例分析
发表于:2025-11-14 作者:千家信息网编辑
千家信息网最后更新 2025年11月14日,这篇文章给大家分享的是有关vue-cli系列之vue-cli-service整体架构的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述vue启动一个项目的时候,需
千家信息网最后更新 2025年11月14日vue-cli系列之vue-cli-service整体架构的示例分析
这篇文章给大家分享的是有关vue-cli系列之vue-cli-service整体架构的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
概述
vue启动一个项目的时候,需要执行npm run serve,其中这个serve的内容就是vue-cli-service serve。可见,项目的启动关键是这个vue-cli-service与它的参数serve。
关键代码
vue-cli-service.js
const semver = require('semver')const { error } = require('@vue/cli-shared-utils')const requiredVersion = require('../package.json').engines.node// 检测node版本是否符合vue-cli运行的需求。不符合则打印错误并退出。if (!semver.satisfies(process.version, requiredVersion)) { error( `You are using Node ${process.version}, but vue-cli-service ` + `requires Node ${requiredVersion}.\nPlease upgrade your Node version.` ) process.exit(1)}// cli-service的核心类。const Service = require('../lib/Service')// 新建一个service的实例。并将项目路径传入。一般我们在项目根路径下运行该cli命令。所以process.cwd()的结果一般是项目根路径const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())// 参数处理。const rawArgv = process.argv.slice(2)const args = require('minimist')(rawArgv, { boolean: [ // build 'modern', 'report', 'report-json', 'watch', // serve 'open', 'copy', 'https', // inspect 'verbose' ]})const command = args._[0]// 将参数传入service这个实例并启动后续工作。如果我们运行的是npm run serve。则command = "serve"。service.run(command, args, rawArgv).catch(err => { error(err) process.exit(1)})Service.js
上面实例化并调用了service的run方法,这里从构造函数到run一路浏览即可。
const fs = require('fs')const path = require('path')const debug = require('debug')const chalk = require('chalk')const readPkg = require('read-pkg')const merge = require('webpack-merge')const Config = require('webpack-chain')const PluginAPI = require('./PluginAPI')const loadEnv = require('./util/loadEnv')const defaultsDeep = require('lodash.defaultsdeep')const { warn, error, isPlugin, loadModule } = require('@vue/cli-shared-utils')const { defaults, validate } = require('./options')module.exports = class Service { constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) { process.VUE_CLI_SERVICE = this this.initialized = false // 一般是项目根目录路径。 this.context = context this.inlineOptions = inlineOptions // webpack相关收集。不是本文重点。所以未列出该方法实现 this.webpackChainFns = [] this.webpackRawConfigFns = [] this.devServerConfigFns = [] //存储的命令。 this.commands = {} // Folder containing the target package.json for plugins this.pkgContext = context // 键值对存储的pakcage.json对象,不是本文重点。所以未列出该方法实现 this.pkg = this.resolvePkg(pkg) // **这个方法下方需要重点阅读。** this.plugins = this.resolvePlugins(plugins, useBuiltIn) // 结果为{build: production, serve: development, ... }。大意是收集插件中的默认配置信息 // 标注build命令主要用于生产环境。 this.modes = this.plugins.reduce((modes, { apply: { defaultModes }}) => { return Object.assign(modes, defaultModes) }, {}) } init (mode = process.env.VUE_CLI_MODE) { if (this.initialized) { return } this.initialized = true this.mode = mode // 加载.env文件中的配置 if (mode) { this.loadEnv(mode) } // load base .env this.loadEnv() // 读取用户的配置信息.一般为vue.config.js const userOptions = this.loadUserOptions() // 读取项目的配置信息并与用户的配置合并(用户的优先级高) this.projectOptions = defaultsDeep(userOptions, defaults()) debug('vue:project-config')(this.projectOptions) // 注册插件。 this.plugins.forEach(({ id, apply }) => { apply(new PluginAPI(id, this), this.projectOptions) }) // wepback相关配置收集 if (this.projectOptions.chainWebpack) { this.webpackChainFns.push(this.projectOptions.chainWebpack) } if (this.projectOptions.configureWebpack) { this.webpackRawConfigFns.push(this.projectOptions.configureWebpack) } } resolvePlugins (inlinePlugins, useBuiltIn) { const idToPlugin = id => ({ id: id.replace(/^.\//, 'built-in:'), apply: require(id) }) let plugins // 主要是这里。map得到的每个插件都是一个{id, apply的形式} // 其中require(id)将直接import每个插件的默认导出。 // 每个插件的导出api为 // module.exports = (PluginAPIInstance,projectOptions) => { // PluginAPIInstance.registerCommand('cmdName(例如npm run serve中的serve)', args => { // // 根据命令行收到的参数,执行该插件的业务逻辑 // }) // // 业务逻辑需要的其他函数 //} // 注意着里是先在构造函数中resolve了插件。然后再run->init->方法中将命令,通过这里的的apply方法, // 将插件对应的命令注册到了service实例。 const builtInPlugins = [ './commands/serve', './commands/build', './commands/inspect', './commands/help', // config plugins are order sensitive './config/base', './config/css', './config/dev', './config/prod', './config/app' ].map(idToPlugin) // inlinePlugins与非inline得处理。默认生成的项目直接运行时候,除了上述数组的插件['./commands/serve'...]外,还会有 // ['@vue/cli-plugin-babel','@vue/cli-plugin-eslint','@vue/cli-service']。 // 处理结果是两者的合并,细节省略。 if (inlinePlugins) { //... } else { //...默认走这条路线 plugins = builtInPlugins.concat(projectPlugins) } // Local plugins 处理package.json中引入插件的形式,具体代码省略。 return plugins } async run (name, args = {}, rawArgv = []) { // mode是dev还是prod? const mode = args.mode || (name === 'build' && args.watch ? 'development' : this.modes[name]) // 收集环境变量、插件、用户配置 this.init(mode) args._ = args._ || [] let command = this.commands[name] if (!command && name) { error(`command "${name}" does not exist.`) process.exit(1) } if (!command || args.help) { command = this.commands.help } else { args._.shift() // remove command itself rawArgv.shift() } // 执行命令。例如vue-cli-service serve 则,执行serve命令。 const { fn } = command return fn(args, rawArgv) } // 收集vue.config.js中的用户配置。并以对象形式返回。 loadUserOptions () { // 此处代码省略,可以简单理解为 // require(vue.config.js) return resolved }}PluginAPI
这里主要是连接了plugin的注册和service实例。抽象过的代码如下
class PluginAPI { constructor (id, service) { this.id = id this.service = service } // 在service的init方法中 // 该函数会被调用,调用处如下。 // // apply plugins. // 这里的apply就是插件暴露出来的函数。该函数将PluginAPI实例和项目配置信息(例如vue.config.js)作为参数传入 // 通过PluginAPIInstance.registerCommand方法,将命令注册到service实例。 // this.plugins.forEach(({ id, apply }) => { // apply(new PluginAPI(id, this), this.projectOptions) // }) registerCommand (name, opts, fn) { if (typeof opts === 'function') { fn = opts opts = null } this.service.commands[name] = { fn, opts: opts || {}} }}module.exports = PluginAPI感谢各位的阅读!关于"vue-cli系列之vue-cli-service整体架构的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
插件
命令
项目
配置
方法
实例
函数
参数
用户
代码
信息
路径
处理
运行
内容
形式
结果
重点
整体
架构
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
山东学校时间同步服务器
安卓软件开发平台
怎么查数据库的归档日志
苏州网络技术推荐咨询
先进的软件开发技术
小学生网络安全手抄报素材图片
数据库很难开发
服务器安装程序时间
丰台旧服务器回收价格多少
网络技术教程培训的风险
服务器电源和开关电源的区别
网络安全整体策略和总体方案
上饶市软件开发公司
数据库运行维护工具
重庆4u服务器机箱虚拟主机
网络安全概念的演变过程图片
吃鸡be服务器
两个服务器不在同一局域网同步
孤岛惊魂4服务器不可用怎么回事
赛门铁克一体机可以备份数据库吗
网络安全方面学什么语言好
金山区网络技术服务材料
表格中禁止输入重复数据库
海南百美网络技术控股有限公司
现代软件开发厂家
早期视频服务器解决方案
测试中什么情况会用到数据库
sql安装提示数据库挂起
网络安全 校园欺凌手抄报
即时通讯软件开发语言