亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

vue-cli系列之vue-cli-service整體架構淺析

2019-11-19 12:17:48
字體:
來源:轉載
供稿:網友

概述

vue啟動一個項目的時候,需要執行npm run serve,其中這個serve的內容就是vue-cli-service serve??梢?,項目的啟動關鍵是這個vue-cli-service與它的參數serve。接下來我們一起看看service中主要寫了什么東東(主要內容以備注形式寫到代碼中。)。

關鍵代碼

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-service中的new Service,加載插件信息,緩存到Service實例的plugins變量中。

當得到命令行參數后,在通過new Service的run方法,執行命令。

該run方法中調用了init方法獲取到項目中的配置信息(默認&用戶的合并),例如用戶的配置在vue.config.js中。

init過程中通過pluginAPI這個類,將service和插件plugins建立關聯。關系存放到service.commands中。
最后通過commands[cmdArgName]調用該方法,完成了插件方法的調用。

初次閱讀,只是看到了命令模式的實際應用。能想到的好就是,新增加一個插件的時候,只需要增加一個插件的文件,并不需要更改其他文件的邏輯。其他的部分,再慢慢體會吧。。。以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
爱福利视频一区| 亚洲国产一区二区三区在线观看| 国产欧美在线看| 国内免费精品永久在线视频| 北条麻妃99精品青青久久| 亚洲性av网站| 2019精品视频| 国产精品白嫩初高中害羞小美女| 91成品人片a无限观看| 日韩激情av在线免费观看| 美女啪啪无遮挡免费久久网站| 精品国产乱码久久久久久婷婷| 欧美综合第一页| 欧美性极品xxxx做受| 亚洲美女性视频| 国产精品美女www爽爽爽视频| 亚洲色图第三页| 97久久久免费福利网址| 欧美国产日韩一区二区三区| 亚洲成人免费在线视频| 国自产精品手机在线观看视频| 中文字幕精品一区久久久久| 久久久久久久久久久久久久久久久久av| 中文字幕亚洲天堂| 国产精品网址在线| 欧美理论片在线观看| 日韩在线视频网| 日韩av片免费在线观看| 国产精品专区一| 97国产精品久久| 国产精品人人做人人爽| 中文字幕亚洲一区二区三区五十路| 日韩在线视频国产| 成人激情视频在线观看| 综合av色偷偷网| 亚洲一区制服诱惑| 国产精品欧美在线| 欧美激情aaaa| 日韩中文字幕国产| 国产精品中文在线| 日韩精品视频在线| 日韩在线免费观看视频| 国产玖玖精品视频| 福利视频一区二区| 日韩精品免费综合视频在线播放| 欧美最近摘花xxxx摘花| 伊人久久久久久久久久| 国产精品稀缺呦系列在线| 日韩欧美中文第一页| 92版电视剧仙鹤神针在线观看| 亚洲人成网站999久久久综合| 色噜噜狠狠狠综合曰曰曰| 美日韩在线视频| 麻豆一区二区在线观看| 国产精品人人做人人爽| 亚洲国产美女精品久久久久∴| 欧美国产日韩中文字幕在线| 成人网在线免费看| 中文亚洲视频在线| 久久精品视频播放| 中文在线资源观看视频网站免费不卡| 久久亚洲国产精品成人av秋霞| 欧美亚洲日本网站| 精品亚洲一区二区三区四区五区| 日韩欧美成人网| 久久视频在线直播| 国产精品欧美日韩一区二区| 日韩精品免费在线观看| 高清日韩电视剧大全免费播放在线观看| 久久亚洲精品一区| 久久久影视精品| 久久影视电视剧免费网站| 日韩欧美亚洲国产一区| 国产精品美女www| 成人国产精品日本在线| 成人免费午夜电影| 热99精品里视频精品| 精品国内亚洲在观看18黄| 欧美成人性生活| 亚洲图片制服诱惑| 国产精品igao视频| 国产丝袜一区二区| 91美女福利视频高清| 国产精品麻豆va在线播放| 亚洲第一av网| 91免费高清视频| 视频在线一区二区| 欧美日韩福利视频| 亚洲三级黄色在线观看| 欧美一级淫片播放口| 国产美女精品视频| 亚洲一区二区黄| 最近2019年手机中文字幕| 91精品国产成人www| 91精品国产综合久久香蕉| 91精品国产乱码久久久久久蜜臀| 欧美激情免费视频| 中文字幕欧美日韩精品| 亚洲高清一二三区| 日韩在线免费观看视频| 精品亚洲一区二区| 亚洲人成电影网站色…| 久久久精品日本| 国产91精品久久久久久久| 91久久久久久久久| 欧美性猛交xxxx乱大交| 亚洲欧美在线看| 欧美亚洲国产日韩2020| 久久久久女教师免费一区| 久久久久久久爱| 91精品在线影院| 国模精品视频一区二区| 韩国v欧美v日本v亚洲| 日韩一区二区三区在线播放| 欧美成人网在线| 狠狠做深爱婷婷久久综合一区| 亚洲精品一区av在线播放| 成人在线激情视频| 日韩免费电影在线观看| 日本精品视频网站| 午夜精品久久久99热福利| 国产日韩精品电影| 97国产精品视频人人做人人爱| 成人性生交xxxxx网站| 精品高清美女精品国产区| 1769国产精品| 日韩电影免费观看中文字幕| 夜色77av精品影院| 97婷婷大伊香蕉精品视频| 亚洲国产精品高清久久久| 亚洲日韩欧美视频一区| 55夜色66夜色国产精品视频| 欧美国产亚洲精品久久久8v| 日本国产精品视频| 亚洲欧美999| 国产精国产精品| 久久国产精彩视频| 亚洲人成网站999久久久综合| 欧美性受xxx| 欧美资源在线观看| 98精品国产自产在线观看| 久久综合国产精品台湾中文娱乐网| 成人网页在线免费观看| 69久久夜色精品国产69| 精品国产一区二区三区久久狼5月| 这里只有精品在线播放| 91精品国产自产在线观看永久| 亚洲国产精品资源| 最近中文字幕日韩精品| 欧美极品第一页| 久久精品成人动漫| 国产视频精品一区二区三区| 91国偷自产一区二区三区的观看方式| 欧美精品国产精品日韩精品| 欧美视频免费在线| 亚洲第一区第二区| 97色在线视频观看| 亚洲色在线视频| 亚洲国产中文字幕在线观看| 黄色成人av在线| 亚洲精品自拍第一页| 亚洲激情视频网站| 色婷婷亚洲mv天堂mv在影片| 国产精品高精视频免费|