国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

vue-cli3.0源碼分析@vue/cli-----create

JasonZhang / 3323人閱讀

摘要:本文主要學(xué)習(xí)的源碼的記錄。這里有一個(gè)的示例的數(shù)據(jù)會(huì)被插件生成器用來生成相應(yīng)的項(xiàng)目文件。另一個(gè)遠(yuǎn)程版本另外而是通過包獲取的版本。

本文主要學(xué)習(xí)vue-cli3.0的源碼的記錄。源碼地址: https://github.com/vuejs/vue-cli
主要對(duì)packages里面的@vue進(jìn)行學(xué)習(xí)。如下圖    


在圖中我們可以看到vue-cli中,不僅僅有初始化工程,還有許多通用的工具、插件。接下來我們就對(duì)這些插件進(jìn)行學(xué)習(xí)。

首先我們來看cli的目錄:
首先來看package.json

{
    "name": "@vue/cli", // 名稱
  "version": "3.5.5", // 版本號(hào)
    "bin": {
        "vue": "bin/vue.js"
      }, // 這個(gè)是用于命令窗口執(zhí)行的命令;如果是全局安裝了,那么vue就是一個(gè)命令值 vue xxxx
"engines": {
    "node": ">=8.9"
  } // 需要的node版本號(hào)
}

我們現(xiàn)在我們可以去看bin/vue.js文件,對(duì)該文件給出注釋,方便閱讀

#!/usr/bin/env node
// 這邊備注是node來解析, 當(dāng)然如果不寫也沒事
// Check node version before requiring/doing anything else
// The user may be on a very old node version
const chalk = require("chalk") // 用于輸出有色彩
const semver = require("semver") // 用于比較版本號(hào)
const requiredVersion = require("../package.json").engines.node // 獲取node版本號(hào)要求
// 檢測(cè)node的版本號(hào),如果不符合要求就給提示
function checkNodeVersion (wanted, id) {
  if (!semver.satisfies(process.version, wanted)) { // process.version表示當(dāng)前node版本
    console.log(chalk.red(
      "You are using Node " + process.version + ", but this version of " + id +
      " requires Node " + wanted + ".
Please upgrade your Node version."
    )) // 給出當(dāng)前vue-cli需要的版本為多少
    process.exit(1)
  }
}

checkNodeVersion(requiredVersion, "vue-cli")

if (semver.satisfies(process.version, "9.x")) {
  console.log(chalk.red(
    `You are using Node ${process.version}.
` +
    `Node.js 9.x has already reached end-of-life and will not be supported in future major releases.
` +
    `It"s strongly recommended to use an active LTS version instead.`
  ))
} // 如果node為9.x那么給出相應(yīng)的提示

const fs = require("fs") // 文件
const path = require("path") // 路徑
const slash = require("slash") // 用于轉(zhuǎn)換 Windows 反斜杠路徑轉(zhuǎn)換為正斜杠路徑  => /
const minimist = require("minimist") // 用來解析從參數(shù)

// enter debug mode when creating test repo
if (
  slash(process.cwd()).indexOf("/packages/test") > 0 && ( // process.cwd()為當(dāng)前絕對(duì)路徑,如F:packages@vuecliin
    fs.existsSync(path.resolve(process.cwd(), "../@vue")) ||
    fs.existsSync(path.resolve(process.cwd(), "../../@vue"))
  )
) {
  process.env.VUE_CLI_DEBUG = true
}

const program = require("commander") // node對(duì)話,輸入
const loadCommand = require("../lib/util/loadCommand") // 用于查找模塊

program
  .version(require("../package").version)
  .usage(" [options]")

上述是一些檢測(cè)的代碼。
之后就要開始交互式的命令了。

1.create入口

我們可以看到program.command就是創(chuàng)建的一個(gè)命令,后面會(huì)有很多的命令create,add,invoke等等,這一節(jié)主要來講解create

program
  .command("create ")
  .description("create a new project powered by vue-cli-service")
  .option("-p, --preset ", "Skip prompts and use saved or remote preset")
  .option("-d, --default", "Skip prompts and use default preset")
  .option("-i, --inlinePreset ", "Skip prompts and use inline JSON string as preset")
  .option("-m, --packageManager ", "Use specified npm client when installing dependencies")
  .option("-r, --registry ", "Use specified npm registry when installing dependencies (only for npm)")
  .option("-g, --git [message]", "Force git initialization with initial commit message")
  .option("-n, --no-git", "Skip git initialization")
  .option("-f, --force", "Overwrite target directory if it exists")
  .option("-c, --clone", "Use git clone when fetching remote preset")
  .option("-x, --proxy", "Use specified proxy when creating project")
  .option("-b, --bare", "Scaffold project without beginner instructions")
  .option("--skipGetStarted", "Skip displaying "Get started" instructions")
  .action((name, cmd) => {
    const options = cleanArgs(cmd)

    if (minimist(process.argv.slice(3))._.length > 1) {
      console.log(chalk.yellow("
 Info: You provided more than one argument. The first one will be used as the app"s name, the rest are ignored."))
    }
    // --git makes commander to default git to true
    if (process.argv.includes("-g") || process.argv.includes("--git")) {
      options.forceGit = true
    }
    require("../lib/create")(name, options)
  })

這邊創(chuàng)建了一個(gè)command("create "),如果是全局安裝了@vue-cli3.0,那么就可以使用

vue create xxxx yyy

xxx yyy為文件名稱和option這些參數(shù)配置項(xiàng)。
我們來看一下分別有哪些配置項(xiàng):

-p, --preset        忽略提示符并使用已保存的或遠(yuǎn)程的預(yù)設(shè)選項(xiàng)
-d, --default                   忽略提示符并使用默認(rèn)預(yù)設(shè)選項(xiàng)
-i, --inlinePreset        忽略提示符并使用內(nèi)聯(lián)的 JSON 字符串預(yù)設(shè)選項(xiàng)
-m, --packageManager   在安裝依賴時(shí)使用指定的 npm 客戶端
-r, --registry             在安裝依賴時(shí)使用指定的 npm registry
-g, --git [message]             強(qiáng)制 / 跳過 git 初始化,并可選的指定初始化提交信息
-n, --no-git                    跳過 git 初始化
-f, --force                     覆寫目標(biāo)目錄可能存在的配置
-c, --clone                     使用 git clone 獲取遠(yuǎn)程預(yù)設(shè)選項(xiàng)
-x, --proxy                     使用指定的代理創(chuàng)建項(xiàng)目
-b, --bare                      創(chuàng)建項(xiàng)目時(shí)省略默認(rèn)組件中的新手指導(dǎo)信息
-h, --help                      輸出使用幫助信息

在action中就是進(jìn)入命令后的執(zhí)行代碼,以下部分主要就是提取-g命令,

const options = cleanArgs(cmd)

    if (minimist(process.argv.slice(3))._.length > 1) {
      console.log(chalk.yellow("
 Info: You provided more than one argument. The first one will be used as the app"s name, the rest are ignored."))
    }
    // --git makes commander to default git to true
    if (process.argv.includes("-g") || process.argv.includes("--git")) {
      options.forceGit = true
    }
2.基礎(chǔ)信息驗(yàn)證

接下來就是進(jìn)入create.js文件

async function create (projectName, options) {
  // 代理使用 -x 或--proxy參數(shù)配置
  if (options.proxy) {
    process.env.HTTP_PROXY = options.proxy
  }

  const cwd = options.cwd || process.cwd() // 當(dāng)前目錄
  const inCurrent = projectName === "." // 是否存在當(dāng)前目錄
  const name = inCurrent ? path.relative("../", cwd) : projectName // 項(xiàng)目名稱
  const targetDir = path.resolve(cwd, projectName || ".") // 生成項(xiàng)目目錄

  const result = validateProjectName(name) // 驗(yàn)證名稱是否符合規(guī)范
  if (!result.validForNewPackages) {
    console.error(chalk.red(`Invalid project name: "${name}"`))
    result.errors && result.errors.forEach(err => {
      console.error(chalk.red.dim("Error: " + err))
    })
    result.warnings && result.warnings.forEach(warn => {
      console.error(chalk.red.dim("Warning: " + warn))
    })
    exit(1)
  }
  // 檢測(cè)文件是否存在,
  if (fs.existsSync(targetDir)) {
    if (options.force) {
      await fs.remove(targetDir)
      // 這邊強(qiáng)制覆蓋
    } else {
      await clearConsole()
      if (inCurrent) {
        // 這邊提示是否在當(dāng)前文件創(chuàng)建?
        const { ok } = await inquirer.prompt([
          {
            name: "ok",
            type: "confirm",
            message: `Generate project in current directory?`
          }
        ])
        if (!ok) {
          return
        }
      } else {
        // 文件已重復(fù)
        const { action } = await inquirer.prompt([
          {
            name: "action",
            type: "list",
            message: `Target directory ${chalk.cyan(targetDir)} already exists. Pick an action:`,
            choices: [
              { name: "Overwrite", value: "overwrite" },
              { name: "Merge", value: "merge" },
              { name: "Cancel", value: false }
            ]
          }
        ])
        if (!action) {
          return
        } else if (action === "overwrite") {
          console.log(`
Removing ${chalk.cyan(targetDir)}...`)
          await fs.remove(targetDir)
        }
      }
    }
  }
  // 新建構(gòu)造器
  const creator = new Creator(name, targetDir, getPromptModules()) // getPromptModules()為內(nèi)置插件對(duì)話對(duì)象
  await creator.create(options)
}

以上大部分都是定義文件,目錄和一名稱效驗(yàn),文件效驗(yàn),比較簡(jiǎn)單易懂,接下來就是創(chuàng)建Creator構(gòu)造器了

3.Creator構(gòu)造器

這一節(jié)的內(nèi)容會(huì)比較繞一點(diǎn)。
首先我們先來了解一下vue-cli-preset,這是一個(gè)包含創(chuàng)建新項(xiàng)目所需預(yù)定義選項(xiàng)和插件的 JSON 對(duì)象,讓用戶無需在命令提示中選擇它們。
vue create 過程中保存的 preset 會(huì)被放在你的用戶目錄下的一個(gè)配置文件中 (~/.vuerc)。你可以通過直接編輯這個(gè)文件來調(diào)整、添加、刪除保存好的 preset。這里有一個(gè) preset 的示例:

{
  "useConfigFiles": true,
  "router": true,
  "vuex": true,
  "cssPreprocessor": "sass",
  "plugins": {
    "@vue/cli-plugin-babel": {},
    "@vue/cli-plugin-eslint": {
      "config": "airbnb",
      "lintOn": ["save", "commit"]
    }
  }
}

Preset 的數(shù)據(jù)會(huì)被插件生成器用來生成相應(yīng)的項(xiàng)目文件。除了上述這些字段,你也可以為集成工具添加配置:

{
  "useConfigFiles": true,
  "plugins": {...},
  "configs": {
    "vue": {...},
    "postcss": {...},
    "eslintConfig": {...},
    "jest": {...}
  }
}

這些額外的配置將會(huì)根據(jù) useConfigFiles 的值被合并到 package.json 或相應(yīng)的配置文件中。例如,當(dāng) "useConfigFiles": true 的時(shí)候,configs 的值將會(huì)被合并到 vue.config.js 中。

更多關(guān)于 preset 可以前往 vue-cli 官網(wǎng) 插件和 Preset https://cli.vuejs.org/zh/guid...。

在基礎(chǔ)驗(yàn)證完后會(huì)創(chuàng)建一個(gè)Creator實(shí)例

const creator = new Creator(name, targetDir, getPromptModules())
3.1getPromptModules

在分析Creator之前,我們先來看一下getPromptModules是什么。getPromptModules源碼

exports.getPromptModules = () => {
  return [
    "babel",
    "typescript",
    "pwa",
    "router",
    "vuex",
    "cssPreprocessors",
    "linter",
    "unit",
    "e2e"
  ].map(file => require(`../promptModules/${file}`))
}

我們可以在promptModules中分別看到

其中比如unit.js:

module.exports = cli => {
  cli.injectFeature({
    name: "Unit Testing",
    value: "unit",
    short: "Unit",
    description: "Add a Unit Testing solution like Jest or Mocha",
    link: "https://cli.vuejs.org/config/#unit-testing",
    plugins: ["unit-jest", "unit-mocha"]
  })

  cli.injectPrompt({
    name: "unit",
    when: answers => answers.features.includes("unit"),
    type: "list",
    message: "Pick a unit testing solution:",
    choices: [
      {
        name: "Mocha + Chai",
        value: "mocha",
        short: "Mocha"
      },
      {
        name: "Jest",
        value: "jest",
        short: "Jest"
      }
    ]
  })

  cli.onPromptComplete((answers, options) => {
    if (answers.unit === "mocha") {
      options.plugins["@vue/cli-plugin-unit-mocha"] = {}
    } else if (answers.unit === "jest") {
      options.plugins["@vue/cli-plugin-unit-jest"] = {}
    }
  })
}

我們可以看到這部其實(shí)就是對(duì)一些內(nèi)置插件的一些配置項(xiàng),用于對(duì)話后來進(jìn)行安裝,

cli.injectFeature:是用來注入featurePrompt,即初始化項(xiàng)目時(shí),選擇的babel、typescript等
cli.injectPrompt:是根據(jù)選擇的 featurePrompt 然后注入對(duì)應(yīng)的 prompt,當(dāng)選擇了 unit,接下來會(huì)有以下的 prompt,選擇 Mocha + Chai 還是 Jest
cli.onPromptComplete: 就是一個(gè)回調(diào),會(huì)根據(jù)選擇來添加對(duì)應(yīng)的插件, 當(dāng)選擇了 mocha ,那么就會(huì)添加 @vue/cli-plugin-unit-mocha 插件
3.2 new Creator

接下來我們來看一下其構(gòu)造函數(shù)

constructor (name, context, promptModules) {
    super()

    this.name = name // 目錄名稱
    this.context = process.env.VUE_CLI_CONTEXT = context // 當(dāng)前目錄
    const { presetPrompt, featurePrompt } = this.resolveIntroPrompts() // 之前預(yù)制的插件,和項(xiàng)目的一些feature
    this.presetPrompt = presetPrompt
    this.featurePrompt = featurePrompt
    this.outroPrompts = this.resolveOutroPrompts() // 其他的插件
    this.injectedPrompts = [] // 當(dāng)選擇featurePrompt時(shí),注入的prompts
    this.promptCompleteCbs = []
    this.createCompleteCbs = []

    this.run = this.run.bind(this)

    const promptAPI = new PromptModuleAPI(this)
    promptModules.forEach(m => m(promptAPI))
  }

上述代碼我們主要來看一下PromptModuleAPI,其他都是一些變量初始化的定義

module.exports = class PromptModuleAPI {
  constructor (creator) {
    this.creator = creator
  }

  injectFeature (feature) {
    this.creator.featurePrompt.choices.push(feature)
  }

  injectPrompt (prompt) {
    this.creator.injectedPrompts.push(prompt)
  }

  injectOptionForPrompt (name, option) {
    this.creator.injectedPrompts.find(f => {
      return f.name === name
    }).choices.push(option)
  }

  onPromptComplete (cb) {
    this.creator.promptCompleteCbs.push(cb)
  }
}

這邊是創(chuàng)建一個(gè)PromptModuleAPI實(shí)例,并通過promptModules.forEach(m => m(promptAPI)),將預(yù)設(shè)的內(nèi)置插件加入到
this.creator.featurePrompt,this.creator.injectedPrompts和this.creator.promptCompleteCbs中

3.3getPreset

在創(chuàng)建了Creator實(shí)例后,然后調(diào)用了create方法

await creator.create(options)

create方法源碼,這段代碼比較簡(jiǎn)單,主要是判斷是否有-p,-d,-i的配置項(xiàng)來直接安裝,如果沒有的話,就進(jìn)入對(duì)話模式this.promptAndResolvePreset,來選擇性的安裝

const isTestOrDebug = process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG
    const { run, name, context, createCompleteCbs } = this

    if (!preset) {
      // 是否存在 -p 或--preset
      if (cliOptions.preset) {
        // vue create foo --preset bar
        preset = await this.resolvePreset(cliOptions.preset, cliOptions.clone)
      } else if (cliOptions.default) {
        // 是否有-d或--default的命令,如果有則,默認(rèn)直接安裝
        // vue create foo --default
        preset = defaults.presets.default
      } else if (cliOptions.inlinePreset) {
        // 是否有--inlinePreset或-i來注入插件
        // vue create foo --inlinePreset {...}
        try {
          preset = JSON.parse(cliOptions.inlinePreset)
        } catch (e) {
          error(`CLI inline preset is not valid JSON: ${cliOptions.inlinePreset}`)
          exit(1)
        }
      } else {
        preset = await this.promptAndResolvePreset()
      }
    }

先判斷 vue create 命令是否帶有 -p 選項(xiàng),如果有的話會(huì)調(diào)用 resolvePreset 去解析 preset。resolvePreset 函數(shù)會(huì)先獲取 ~/.vuerc 中保存的 preset, 然后進(jìn)行遍歷,如果里面包含了 -p 中的 ,則返回~/.vuerc 中的 preset。如果沒有則判斷是否是采用內(nèi)聯(lián)的 JSON 字符串預(yù)設(shè)選項(xiàng),如果是就會(huì)解析 .json 文件,并返回 preset,還有一種情況就是從遠(yuǎn)程獲取 preset(利用 download-git-repo 下載遠(yuǎn)程的 preset.json)并返回。

上面的情況是當(dāng) vue create 命令帶有 -p 選項(xiàng)的時(shí)候才會(huì)執(zhí)行,如果沒有就會(huì)調(diào)用 promptAndResolvePreset 函數(shù)利用 inquirer.prompt 以命令后交互的形式來獲取 preset,下面看下 promptAndResolvePreset 函數(shù)的源碼:

async promptAndResolvePreset (answers = null) {
    // prompt
    if (!answers) {
      await clearConsole(true)
      answers = await inquirer.prompt(this.resolveFinalPrompts()) 
      // 交互式命令對(duì)話,安裝defalut和Manually select features
    }
    debug("vue-cli:answers")(answers)

    if (answers.packageManager) {
      saveOptions({
        packageManager: answers.packageManager
      })
    }

    let preset
    if (answers.preset && answers.preset !== "__manual__") { // 如果是選擇本地保存的preset(.vuerc)
      preset = await this.resolvePreset(answers.preset)
    } else {
      // manual
      preset = {
        useConfigFiles: answers.useConfigFiles === "files",
        plugins: {}
      }
      answers.features = answers.features || []
      // run cb registered by prompt modules to finalize the preset
      this.promptCompleteCbs.forEach(cb => cb(answers, preset))
    }

    // validate
    validatePreset(preset)

    // save preset
    if (answers.save && answers.saveName) {
      savePreset(answers.saveName, preset)
    }

    debug("vue-cli:preset")(preset)
    return preset
  }

看到這里會(huì)比較亂的,preset會(huì)比較多,我們?cè)賮砜匆幌聄esolveFinalPrompts源碼

 resolveFinalPrompts () {
    // patch generator-injected prompts to only show in manual mode
    this.injectedPrompts.forEach(prompt => {
      const originalWhen = prompt.when || (() => true)
      prompt.when = answers => {
        return isManualMode(answers) && originalWhen(answers)
      }
    })
    const prompts = [
      this.presetPrompt,
      this.featurePrompt,
      ...this.injectedPrompts,
      ...this.outroPrompts
    ]
    debug("vue-cli:prompts")(prompts)
    console.log(1, prompts)
    return prompts
  }

這里我們可以看到presetPrompt, featurePrompt, injectedPrompts, outroPrompts 合并成一個(gè)數(shù)組進(jìn)行返回,
presetPrompt是預(yù)設(shè)的,當(dāng)上一次選擇manually模式進(jìn)行了預(yù)設(shè),并保存到.vuerc中,那么初始化的時(shí)候會(huì)列出已保存的插件
featurePrompt就是內(nèi)置的一些插件
injectedPrompts是通過-i命令來手動(dòng)注入的插件
outroPrompts是一些其他的插件。
這邊對(duì)話完之后,就要開始依賴的安裝了。

4依賴安裝

我們繼把create中的代碼往下走

const packageManager = (
      cliOptions.packageManager ||
      loadOptions().packageManager ||
      (hasYarn() ? "yarn" : "npm")
    )

    await clearConsole() // 清空控制臺(tái)
    logWithSpinner(`?`, `Creating project in ${chalk.yellow(context)}.`)
    this.emit("creation", { event: "creating" })

    // get latest CLI version
    const { latest } = await getVersions()
    const latestMinor = `${semver.major(latest)}.${semver.minor(latest)}.0`
    // generate package.json with plugin dependencies
    const pkg = {
      name,
      version: "0.1.0",
      private: true,
      devDependencies: {}
    }
    const deps = Object.keys(preset.plugins)
    deps.forEach(dep => {
      if (preset.plugins[dep]._isPreset) {
        return
      }

      // Note: the default creator includes no more than `@vue/cli-*` & `@vue/babel-preset-env`,
      // so it is fine to only test `@vue` prefix.
      // Other `@vue/*` packages" version may not be in sync with the cli itself.
      pkg.devDependencies[dep] = (
        preset.plugins[dep].version ||
        ((/^@vue/.test(dep)) ? `^${latestMinor}` : `latest`)
      )
    })
    // write package.json
    await writeFileTree(context, {
      "package.json": JSON.stringify(pkg, null, 2)
    })

這邊主要就是獲取cli的版本和生產(chǎn)package.json,其中主要是獲取版本號(hào)

module.exports = async function getVersions () {
  if (sessionCached) {
    return sessionCached
  }

  let latest
  const local = require(`../../package.json`).version
  if (process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG) {
    return (sessionCached = {
      current: local,
      latest: local
    })
  }

  const { latestVersion = local, lastChecked = 0 } = loadOptions()
  const cached = latestVersion
  const daysPassed = (Date.now() - lastChecked) / (60 * 60 * 1000 * 24)

  if (daysPassed > 1) { // 距離上次檢查更新超過一天
    // if we haven"t check for a new version in a day, wait for the check
    // before proceeding
    latest = await getAndCacheLatestVersion(cached)
  } else {
    // Otherwise, do a check in the background. If the result was updated,
    // it will be used for the next 24 hours.
    getAndCacheLatestVersion(cached) // 后臺(tái)更新
    latest = cached
  }

  return (sessionCached = {
    current: local,
    latest
  })
}

// fetch the latest version and save it on disk
// so that it is available immediately next time
async function getAndCacheLatestVersion (cached) {
  const getPackageVersion = require("./getPackageVersion")
  const res = await getPackageVersion("vue-cli-version-marker", "latest")
  if (res.statusCode === 200) {
    const { version } = res.body
    if (semver.valid(version) && version !== cached) {
      saveOptions({ latestVersion: version, lastChecked: Date.now() })
      return version
    }
  }
  return cached
}

這邊主要是有2個(gè)版本變量,一個(gè)是local本地cli版本。另一個(gè)laset遠(yuǎn)程cli版本
另外getAndCacheLatestVersion而是通過 vue-cli-version-marker npm 包獲取的 CLI 版本。
生產(chǎn)package.json之后,我們?cè)诶^續(xù)看后面代碼

const shouldInitGit = this.shouldInitGit(cliOptions)
    if (shouldInitGit) {
      logWithSpinner(`           
               
                                           
                       
                 

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/103403.html

相關(guān)文章

  • vue-cli 3.0 源碼分析

    摘要:寫在前面其實(shí)最開始不是特意來研究的源碼,只是想了解下的命令,如果想要了解命令的話,那么繞不開寫的。通過分析發(fā)現(xiàn)與相比,變化太大了,通過引入插件系統(tǒng),可以讓開發(fā)者利用其暴露的對(duì)項(xiàng)目進(jìn)行擴(kuò)展。 showImg(https://segmentfault.com/img/bVboijb?w=1600&h=1094); 寫在前面 其實(shí)最開始不是特意來研究 vue-cli 的源碼,只是想了解下 n...

    yiliang 評(píng)論0 收藏0
  • vue-cli3.0源碼分析@vue/cli-----add和invoke

    上一篇已經(jīng)講了create命令;那么這一篇我們來看一下add和invoke這個(gè)命令。之所以放一起講,是因?yàn)楫?dāng)add執(zhí)行的時(shí)候,也會(huì)去執(zhí)行invoke add vue add vue-cli-plugin-xxx 或 vue add @vue/xxx 通過這種形式就是vue-cli3.0內(nèi)部能識(shí)別的插件了首先來看一下入口 program .command(add [pluginOptions]...

    sorra 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦的文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

    sutaking 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦的文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

    khs1994 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<