create-vue 源码解析(一)

准备工作

先克隆源码到本地

cmd 复制代码
git clone git@github.com:vuejs/create-vue.git

安装依赖,打包可执行文件

cmd 复制代码
pnpm install // 安装依赖
pnpm build // 输出outfile.cjs文件

用 node 启动 outfile.cjs 就可以启动脚手架了

cmd 复制代码
node outfile.cjs

package.json

在看源码之前先热个身,先来看看 package.json 里都有什么

json 复制代码
// package.json
{
  "name": "create-vue",
  "version": "3.7.5",
  "description": "An easy way to start a Vue project",
  // 默认是 CommonJS 规范,Module表示此包采用 ES module 模块化
  "type": "module",
  // bin 定义命令,使该包安装为一个可执行命令
  "bin": {
    "create-vue": "outfile.cjs"
  },
  // 包下载安装完成时包括的所有文件
  "files": [
    "outfile.cjs",
    "template"
  ],
  // 规定该包 node 运行环境版本
  "engines": {
    "node": ">=v16.20.0"
  },
  // npm 脚本命令
  "scripts": {
    "prepare": "husky install",
    "format": "prettier --write .",
    "build": "zx ./scripts/build.mjs",
    "snapshot": "zx ./scripts/snapshot.mjs",
    "pretest": "run-s build snapshot",
    "test": "zx ./scripts/test.mjs",
    "prepublishOnly": "zx ./scripts/prepublish.mjs"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vuejs/create-vue.git"
  },
  "keywords": [],
  "author": "Haoqun Jiang <haoqunjiang+npm@gmail.com>",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/vuejs/create-vue/issues"
  },
  "homepage": "https://github.com/vuejs/create-vue#readme",
  "devDependencies": {
    "@tsconfig/node18": "^18.2.2",
    "@types/eslint": "^8.44.2",
    "@types/node": "^18.17.17",
    "@types/prompts": "^2.4.4", 
    "@vue/create-eslint-config": "^0.3.2",
    "@vue/tsconfig": "^0.4.0",
    "ejs": "^3.1.9", // 模板编译
    "esbuild": "^0.18.20", // 打包
    "esbuild-plugin-license": "^1.2.2",
    "husky": "^8.0.3",
    "kolorist": "^1.8.0", // 命令行美化
    "lint-staged": "^14.0.1",
    "minimist": "^1.2.8", // 解析命令行选项
    "npm-run-all2": "^6.0.6", // 提供npm脚本并行或者串行执行
    "prettier": "^3.0.3",
    "prompts": "^2.4.2", // 命令行提示语
    "zx": "^7.2.3" // google开发的用于写复杂命令脚本的工具,用于替代bash
  },
  "lint-staged": {
    "*.{js,ts,vue,json}": [
      "prettier --write"
    ]
  },
  "dependencies": {
    "pnpm": "^8.6.5"
  }
}

脚手架是如何通过一个命令创建项目的?

npm create

我们可以在 Vue3 的官方网站上看到推荐直接使用 npm create vue@latest 来创建我们的项目,而实际上 npm create vue@latest 就是在使用 create-vue 脚手架,显然这跟 vue-cli 有很大的区别。

vue-cli 需要我们通过 npm install -g @vue/cli 命令在全局安装,该包会在 node 下全局安装一个 vue 命令文件,调用 vue xxx 命令实际上就是在调用这个 vue 文件,然后在 vue 中通过 node.js 运行了 /node_modules/@vue/cli/bin/vue.js 来创建项目。

那么 npm create vue 是为何不需要 npm install 就能直接运行脚手架脚本呢?

从 npm 的官方文档发现 createinit 的一个别名,也就是说 npm create 就等于 npm init

  • npm init / npm create

    初始化一个 package.json 文件

  • npm init <initializer> / npm create <initializer>

    本质上是调用 npm exec create-<initializer> 命令, 也就相当于npx create-<initializer><initializer>可以理解为一个简称,它真正的包名为create-<initializer>,也只有符合这种命名方式的npm包才可以执行这样的命令。

因此,以下命令可以达到与npm create vue@latest同样的效果:

bash 复制代码
npm init vue@latest
npx create-vue@latest
npm exec create-vue@latest

npm create vue 执行流程

首先查找本地的 create-vue npm包,在其中找到 package.json 文件 bin 属性指明的可执行文件,即 outfile.cjs,当本地不存在 create-vue 包时,会从远程源下载该包。

json 复制代码
// package.json
{
  "bin": {
    "create-vue": "outfile.cjs"
  },
}

outfile.cjs 是什么时候产生的?

通过 package.json 我们可以看到 outfile.cjs 是通过 build 命令执行 build.mjs脚本打包生成的,但是我们在 npm create vue 命令期间,是不会调用 build 命令的。

js 复制代码
// build.mjs
await esbuild.build({
  bundle: true,
  entryPoints: ['index.ts'], // 入口文件
  outfile: 'outfile.cjs', // 输出可执行文件
  format: 'cjs',
  platform: 'node',
  target: 'node14',

  plugins: [
    ...
  ]
})

这就与 npm 包发布机制有关,npm publish 会将 package.jsonfiles 属性指明的文件/文件夹发布到 npm 包中。create-vue 在发布npm包之前调用 prepublishOnly 命令,而在 prepublish.mjs 脚本中可以发现 build 命令的身影,也就是这个阶段生成的 outfile.cjs 可执行文件。

好了,热身结束,可以去下一节看看源码了create-vue 源码解析(二)

相关推荐
王解8 分钟前
一篇文章读懂 Prettier CLI 命令:从基础到进阶 (3)
前端·perttier
乐闻x14 分钟前
最佳实践:如何在 Vue.js 项目中使用 Jest 进行单元测试
前端·vue.js·单元测试
檀越剑指大厂28 分钟前
【Python系列】异步 Web 服务器
服务器·前端·python
我是Superman丶30 分钟前
【前端】js vue 屏蔽BackSpace键删除键导致页面后退的方法
开发语言·前端·javascript
Hello Dam32 分钟前
基于 Spring Boot 实现图片的服务器本地存储及前端回显
服务器·前端·spring boot
小仓桑34 分钟前
利用 Vue 组合式 API 与 requestAnimationFrame 优化大量元素渲染
前端·javascript·vue.js
Hacker_xingchen34 分钟前
Web 学习笔记 - 网络安全
前端·笔记·学习
天海奈奈35 分钟前
前端应用界面的展示与优化(记录)
前端
多多*1 小时前
后端并发编程操作简述 Java高并发程序设计 六类并发容器 七种线程池 四种阻塞队列
java·开发语言·前端·数据结构·算法·状态模式
mubeibeinv1 小时前
列表代码思路
前端