Как работает vuecli

Vue.js

vue-cli — это официальный инструмент командной строки для создания шаблонов для Vue.js. Мы можем использовать его для быстрого создания проектов Vue.js. Основная функция vue-cli — инициализация проектов. Вы можете использовать официальные шаблоны или пользовательские шаблоны для создания проектов. , А начиная с версии 2.8.0, vue-cli добавилbuildкоманда, которая позволяет вам запускать приложение Vue.js с нулевой конфигурацией. Далее давайте рассмотрим, как работает vue-cli.

Установить глобально

Во-первых, vue-cli — это пакет узла, и его можно передать прямо в терминале.vueВызов команды, поэтому vue-cli необходимо установить глобально.Когда npm устанавливает пакет глобально, он в основном делает две вещи:

  1. Установите пакет в глобальный каталог node_modules.
  2. Создайте соответствующую команду в каталоге bin и свяжите ее с соответствующим исполняемым скриптом.

Глядя на package.json vue-cli, вы можете найти следующий код:

{
  "bin": {
    "vue": "bin/vue",
    "vue-init": "bin/vue-init",
    "vue-list": "bin/vue-list",
    "vue-build": "bin/vue-build"
  }
}

Таким образом, после глобальной установки vue-cli, npm поможет вам зарегистрироватьсяvue, vue-init, vue-list, vue-buildэти команды.

Структура проекта

Сам проект vue-cli не большой, а структура проекта следующая:

.
├── bin
├── docs
├── lib
└── test
    └── e2e

binКаталог - это исполняемый файл,docsВот новые функцииvue buildдокументация,libэто разделенная библиотека классов,testНиже приведен тестовый файл, давайте сосредоточимся наbinфайлы в каталоге.

bin/vue

Первый взглядbin/vue, содержание очень короткое, только следующий код:

#!/usr/bin/env node

require('commander')
  .version(require('../package').version)
  .usage('<command> [options]')
  .command('init', 'generate a new project from a template')
  .command('list', 'list available official templates')
  .command('build', 'prototype a new project')
  .parse(process.argv)

vue-cli основан наcommander.jsнаписано, поддерживаетсяGit-style sub-commands, поэтому выполнитеvue initможет достигать иvue-initТот же эффект.

bin/vue-init

см. далееbin/vue-init,vue-initОсновная функция — генерировать прототипы проектов по заданному шаблону. Файл сначала представляет некоторые зависимые модули и вспомогательные функции в lib, потому что команда init должна получить хотя бы один параметр, поэтомуvue-initПервое, что нужно выполнить, это проверить входные параметрыhelpфункция, если параметры не переданы, будет напечатано приглашение, а если параметры переданы, операция будет продолжена.

Далее идет процесс разбора параметров:

var template = program.args[0]
var hasSlash = template.indexOf('/') > -1
var rawName = program.args[1]
var inPlace = !rawName || rawName === '.'
var name = inPlace ? path.relative('../', process.cwd()) : rawName
var to = path.resolve(rawName || '.')
var clone = program.clone || false

var tmp = path.join(home, '.vue-templates', template.replace(/\//g, '-'))
if (program.offline) {
  console.log(`> Use cached template at ${chalk.yellow(tildify(tmp))}`)
  template = tmp
}

templateимя шаблона, второй параметр (program.args[1])rawNameимя проекта, если оно не существует или.считается инициализированным в текущем каталоге (inPlace = true), имя проекта по умолчаниюnameТакже текущее имя папки.to— выходной путь проекта, который будет использоваться позже.cloneПараметр определяет, следует ли использовать git clone для загрузки шаблона, что полезно, когда шаблон находится в частном репозитории.offlineПараметр определяет, использовать ли автономный режим.Если используется автономный режим, vue-cli попытается~/.vue-templatesПолучите соответствующий шаблон ниже, вы можете сохранить долгоdownloading templateВремя ожидания, но шаблон не последняя версия не может быть определена.

Вы получите переменную при обработке параметров ранееto, указывающий путь к проекту, который должен быть сгенерирован, если он уже существует, будет выведено предупреждение, чтобы пользователь мог подтвердить, следует ли продолжать, и выполнить после подтвержденияrunфункция:

if (exists(to)) {
  inquirer.prompt([{
    type: 'confirm',
    message: inPlace
      ? 'Generate project in current directory?'
      : 'Target directory exists. Continue?',
    name: 'ok'
  }], function (answers) {
    if (answers.ok) {
      run()
    }
  })
} else {
  run()
}

запустить функциюВ основном он проверяет, является ли шаблон локальным шаблоном, затем получает или загружает шаблон и выполняет его после получения шаблона.generateфункция.

Генерирующая функция генерации является ядром проекта, основной код:

module.exports = function generate (name, src, dest, done) {
  var opts = getOptions(name, src)
  // Metalsmith读取template下所有资源
  var metalsmith = Metalsmith(path.join(src, 'template'))
  var data = Object.assign(metalsmith.metadata(), {
    destDirName: name,
    inPlace: dest === process.cwd(),
    noEscape: true
  })
  opts.helpers && Object.keys(opts.helpers).map(function (key) {
    Handlebars.registerHelper(key, opts.helpers[key])
  })

  var helpers = {chalk, logger}

  if (opts.metalsmith && typeof opts.metalsmith.before === 'function') {
    opts.metalsmith.before(metalsmith, opts, helpers)
  }
  // 一次使用askQuestions, filterFiles, renderTemplateFiles处理读取的内容
  metalsmith.use(askQuestions(opts.prompts))
    .use(filterFiles(opts.filters))
    .use(renderTemplateFiles(opts.skipInterpolation))

  if (typeof opts.metalsmith === 'function') {
    opts.metalsmith(metalsmith, opts, helpers)
  } else if (opts.metalsmith && typeof opts.metalsmith.after === 'function') {
    opts.metalsmith.after(metalsmith, opts, helpers)
  }
  // 将处理后的文件输出
  metalsmith.clean(false)
    .source('.') // start from template root instead of `./src` which is Metalsmith's default for `source`
    .destination(dest)
    .build(function (err, files) {
      done(err)
      if (typeof opts.complete === 'function') {
        var helpers = {chalk, logger, files}
        opts.complete(data, helpers)
      } else {
        logMessage(opts.completeMessage, data)
      }
    })

  return data
}

сначала черезgetOptionsПолучена основная информация о конфигурации некоторых проектов, такая как имя проекта, информация о пользователе git и т. д. затем пройтиmetalsmithкомбинироватьaskQuestions,filterFiles,renderTemplateFilesЭти промежуточные компоненты завершают процесс создания шаблона проекта. **metalsmith** — генератор статических веб-сайтов с плагинами, все работает через плагины, поэтому его можно легко расширить. По коду функции генерации легко увидеть, что процесс генерации проекта в основном состоит из следующих этапов.

Каждый процесс в основном использует следующие библиотеки:

  • getOptions: в основном читается под шаблономmeta.jsonилиmeta.js,meta.jsonОбязательный файл, который предоставляет различную информацию для cli, такую ​​как пользовательские помощники, настраиваемые параметры, правила фильтрации файлов и многое другое. Как написать собственный шаблон, вы можете обратиться кздесь
  • Прочитайте содержимое шаблона через Metalsmith.Следует отметить, что содержимое шаблона в настоящее время еще не обработано, поэтому оно выглядит так:
/* eslint-disable no-new */
new Vue({
  el: '#app',
  {{#router}}
  router,
  {{/router}}
  {{#if_eq build "runtime"}}
  render: h => h(App){{#if_eq lintConfig "airbnb"}},{{/if_eq}}
  {{/if_eq}}
  {{#if_eq build "standalone"}}
  template: '<App/>',
  components: { App }{{#if_eq lintConfig "airbnb"}},{{/if_eq}}
  {{/if_eq}}
}){{#if_eq lintConfig "airbnb"}};{{/if_eq}}
  • Получить индивидуальную конфигурацию: в основном черезasyncа такжеinquirerКооперация завершает набор пользовательских конфигураций.
  • filterFiles: фильтровать файлы поminimatchВыполните сопоставление файлов.
  • Шаблон рендеринга: пройтиconsolidate.jsСотрудничатьhandlebarsфайл рендеринга.
  • выход: прямой выход

vue-initВесь рабочий процесс примерно такой,vue-cliЯвляясь удобным инструментом командной строки, его код также лаконичен и прост для понимания, а проанализировав исходный код, можно найти множество интересных модулей, используемых в нем.

bin/vue-list

vue-listФункция очень проста, потянитеvuejs-templatesинформация о шаблоне и вывод.

bin/vue-build

vue-buildЭто запуск проекта через конфигурацию веб-пакета, если запись только одна.vueкомпонент, используйте значение по умолчаниюdefault-entry.es6Загрузите компонент и визуализацию.

разное

При просмотре исходного кода vue-cli я обнаружилuser-homeЭтот модуль, содержание этого модуля выглядит следующим образом:

'use strict';
module.exports = require('os-homedir')();

os-homedirЭтот пакет являетсяos.homedirполифилл, вWhy not just use the os-home module?вниз, я вижуModules are cheap in Node.jsэтот блог. ФактическиsindresorhusНаписал множество однострочных узловых модулей, и ему также нравятся однострочные узловые модули, потому что чем меньше модуль, тем выше гибкость и возможность повторного использования. Конечно, по поводу One-line модулей у всех разное мнение, ведь не в первый раз слышу слова "просто эта функция может написать пакет в tm". Я думаю это зависит от человека к человеку.Кто sindresorhus,автор многих известных open source проектов,опубликовал 1000+ npm пакетов,и большинство используемых им модулей написаны им самим,поэтому для него с помощью различных удобно использовать «строительные блоки» для формирования «высотных зданий». Однако для других людей, если они привыкли к этому методу, они могут стать более зависимыми от этих вещей, точно так же, как многие фронтенд-разработчики теперь полагаются на фреймворки, а не на фундамент, поэтому я думаю, что этот метод разработки «строительных блоков» вполне подходит. Хорошо, но лучше знать почему. Но я чувствую, что модули One-line малоэффективны, как и модуль user-home, без него,const home = require('os-homedir')();Он также может достичь своей цели. Это может быть связано с обсессивно-компульсивным расстройством. Пользователь-дом родился, и это похоже наnegative-zeroТакие однострочные модули — один из немногих сценариев использования, и никакого удобства они не приносят, особенно в версии 2.0, этот пакет напрямую использует Object.is для суждения:

'use strict';
module.exports = x => Object.is(x, -0);

Я не знаю, что все думают об однострочных модулях?

#### Завершение объявления о вакансии NetEase Koala набирает старших инженеров по разработке интерфейсов в здании NetEase Building, Биньцзян, Ханчжоу.Нажмите на меня, чтобы узнать подробности и отправить резюме.