All Tags
On this page

新款vue-cli之create-vue源码阅读总结

#vue #source-code
avatar
jerrywu001
创建时间:2023-09-04 06:13:20

最近vue3已成为默认版本,而新版脚手架create-vue也随之浮出水面 正如它的介绍"An easy way to start a Vue project"一样,源码也是清晰易懂 下面对其用到的知识点做个总结:

使用方式

远程命令

npm init vue@3

# 其实背后的逻辑是npm做了个转换:
# 参见:
# https://docs.npmjs.com/cli/v6/commands/npm-init
# https://juejin.cn/post/6948202986573135908

#即等效于
# npx create-vue@3

clone源码运行

cd create-vue
npm run build # 将index.js转成commonjs形式,输出outfile.cjs
node outfile.cjs

远程命令也是运行的outfile.cjs文件, 可参加package.json中的bin配置

{
  "bin": {
    "create-vue": "outfile.cjs"
  },
}

package.json中设置type: 'module'

源码package.json中设置了type: 'module',意思是说如果js文件采用的是es module格式书写,可以不用转换成demo.cjs

// demo.js
import path from 'path';

consoloe.log(path)
demo.js
node demo.js

# 如果没有type: 'module'配置,需要转成demo.cjs

template增量覆盖

// 思路:简洁 清晰 易懂
const templateRoot = path.resolve(__dirname, 'template')
const render = function render(templateName) {
  const templateDir = path.resolve(templateRoot, templateName)
  renderTemplate(templateDir, root) // utils\renderTemplate.js
}

// 首先拉取template/base作为初始化模板
render('base')

// 比如这里用户选择了jsx,则拉取template/config/jsx
// 然后renderTemplate函数去做merge即可
if (needsJsx) {
  render('config/jsx')
}
// ...

命令行参数解析

相当于vue-cli中commander的简化版本

查看源码(index.js),可以看到cli预设了一些默认参数,如下:

// --default
 // --typescript / --ts
 // --jsx
 // --router / --vue-router
 // --pinia
 // --with-tests / --tests (equals to `--vitest --cypress`)
 // --vitest
 // --cypress
 // --eslint
 // --eslint-with-prettier (only support prettier through eslint for simplicity)
 // --force (for force overwriting)

当使用预设参数后,将跳过问题询问,直接拉对应模板到本地,比如:

npx create-vue@3 --ts

# 不过 npm init vue@3 --ts 居然没有生效,不知道作者是不是没有测试

问题答案统计

prompts

统计问题答案,并以对象的形式输出 相当于vue-cli中使用的inquirer

answers

gradient-string

Beautiful color gradients in terminal output

gradient-string

gradient-string

源码路径:utils\banner.js

// generated by the following code:
//
// require('gradient-string')([
//   { color: '#42d392', pos: 0 },
//   { color: '#42d392', pos: 0.1 },
//   { color: '#647eff', pos: 1 }
// ])('Vue.js - The Progressive JavaScript Framework'))
//
// Use the output directly here to keep the bundle small.

const banner =
  '\x1B[38;2;66;211;146mV\x1B[39m\x1B[38;2;66;...'

export default banner
utils\banner.js

文字颜色格式化

kolorist

Tiny library to put colors into stdin/stdout 相当于vue-cli中使用的chalk

kolorist

pinia

一个更加简洁的状态管理

pinia

vitest

参见以下文章

vitest体验(兼容jest api)

git submodule

基操,这里不做过多介绍 playground文件夹就是个submodule

# 源码根目录下
git submodule init
git submodule update

js语法书写shell

以js的方式去写shell脚本

zx

  • 源码中的使用:

scripts\snapshot.mjs 需要先npm run build

#!/usr/bin/env zx
import 'zx/globals'

$.verbose = false

const featureFlags = ['typescript', 'jsx', 'router', 'pinia', 'vitest', 'cypress']

// The following code & comments are generated by GitHub CoPilot.
function fullCombination(arr) {
  // ...

  return combinations
}

const flagCombinations = fullCombination(featureFlags)
flagCombinations.push(['default'])

// `--with-tests` are equivalent of `--vitest --cypress`
// Previously it means `--cypress` without `--vitest`.
// Here we generate the snapshots only for the sake of easier comparison with older templates.
// They may be removed in later releases.
const withTestsFlags = fullCombination(['typescript', 'jsx', 'router', 'pinia']).map((args) => [
  ...args,
  'with-tests'
])
withTestsFlags.push(['with-tests'])

flagCombinations.push(...withTestsFlags)

const playgroundDir = path.resolve(__dirname, '../playground/')
const bin = path.posix.relative('../playground/', '../outfile.cjs')

cd(playgroundDir)
for (const flags of flagCombinations) {
  const projectName = flags.join('-')
  console.log(`Creating project ${projectName}`)

  await $`node ${[bin, projectName, ...flags.map((flag) => `--${flag}`), '--force']}`
}

pnpm

可自行搜索进行了解

https://pnpm.io/

husky7

git hooks

https://typicode.github.io/husky

npm-run-all

https://www.npmjs.com/package/npm-run-all

cypress

https://www.cypress.io/