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 源码解析(二)

相关推荐
知识分享小能手3 分钟前
Html5学习教程,从入门到精通,HTML5 简介语法知识点及案例代码(1)
开发语言·前端·javascript·学习·前端框架·html·html5
IT、木易6 分钟前
大白话React第二章深入理解阶段
前端·javascript·react.js
晚安72012 分钟前
Ajax相关
前端·javascript·ajax
图书馆钉子户14 分钟前
怎么使用ajax实现局部刷新
前端·ajax·okhttp
bin915330 分钟前
DeepSeek 助力 Vue 开发:打造丝滑的单选按钮(Radio Button)
前端·javascript·vue.js·ecmascript·deepseek
qianmoQ34 分钟前
第五章:工程化实践 - 第五节 - Tailwind CSS 常见问题解决方案
前端·css
那就可爱多一点点1 小时前
超高清大图渲染性能优化实战:从页面卡死到流畅加载
前端·javascript·性能优化
不能只会打代码2 小时前
六十天前端强化训练之第一天HTML5语义化标签深度解析与博客搭建实战
前端·html·html5
OpenTiny社区2 小时前
Node.js技术原理分析系列——Node.js的perf_hooks模块作用和用法
前端·node.js
菲力蒲LY2 小时前
输入搜索、分组展示选项、下拉选取,全局跳转页,el-select 实现 —— 后端数据处理代码,抛砖引玉展思路
java·前端·mybatis