vue cli源码学习之cli-service

vue cli源码学习之cli-service

目录结构分析

cli-service/ :根目录,代表项目的主要服务模块 ,用于提供命令行服务插件功能

tests / :测试文件夹,通常用于存放自动化测试代码。文件夹命名约定为 tests,可能包含单元测试或集成测试,用于验证项目功能的正确性。

bin/ :存放可执行文件或脚本,通常包含启动 CLI 服务的入口文件。例如,可以包含一个启动脚本(如 cli-service),用于用户直接在命令行中调用。

generator/ :用于生成代码的模块,通常包含脚手架代码或代码生成器的逻辑。generator 目录下可能会包含模板和代码生成逻辑,用于生成项目中的文件或初始化项目配置。

lib/ :库文件夹,包含项目的核心逻辑代码,主要是供外部调用的核心函数和类等。通常在项目中引用这些功能模块实现特定功能。

migrator/ :用于 管理迁移脚本 的目录。该文件夹通常包含数据迁移或版本迁移的逻辑,如数据库结构的迁移等。适用于项目的升级或数据结构的演变。

types/类型声明文件夹。通常用于 TypeScript 项目,定义接口和类型,以确保类型安全和代码的可维护性。类型声明可以为其他模块提供类型支持。

.npmignore:文件用于指定哪些文件和文件夹在发布到 npm 时应被忽略。通过 .npmignore 文件可以控制不需要的文件或目录(如测试文件夹、配置文件等)不会被包含在 npm 包中。

package.json :项目的配置文件,定义了项目的基本信息(如名称、版本、依赖项、脚本等),也是 npm 项目必须包含的文件。通过 package.json 可以管理项目的依赖、命令和元数据。

README.md :项目的自述文件,通常用于向用户介绍项目的功能、安装方法、使用指南等。README.md 文件在 GitHub 和 npm 上也会展示出来,帮助用户了解和使用项目。

webpack.config.js :Webpack 的配置文件,用于配置项目的打包过程。Webpack 是一个前端打包工具,配置文件定义了如何处理、打包项目中的资源(如 JavaScript、CSS、图像等)。

bin/ 目录下的启动脚本

vue-cli-service 的命令行脚本 ,主要功能是启动 Vue CLI 服务。以下是代码的主要作用和流程:
1.检查 Node.js 版本:

使用 semver 模块 检查当前运行的 Node.js 版本是否满足 package.json 中定义的版本要求。

如果不满足要求,输出错误信息并终止进程。

2. 创建服务实例

导入 Service 类并创建一个服务实例。服务的上下文是当前工作目录或环境变量VUE_CLI_CONTEXT 指定的目录。

3.解析命令行参数:

使用 minimist 模块解析命令行参数。

定义了一些布尔类型的选项,如 modern、report、open 等。

这些选项是命令行参数,用于配置和控制 vue-cli-service 的行为。以下是每个选项的作用:

构建 相关选项:
modern :启用现代模式 构建,生成现代 JavaScript 代码以利用新浏览器的特性。
report :生成构建报告 ,通常用于分析打包后的文件大小和依赖关系。
report-json :生成 JSON 格式 的构建报告。
inline-vue :将 Vue 的运行时内联到构建的包 中。
watch :在开发模式下监听文件变化,自动重新构建。

服务 相关选项:
open :在启动开发服务器后自动打开浏览器
copy :将本地 URL 复制到剪贴板。
https :使用 HTTPS 协议启动开发服务器。

检查相关选项
verbose :启用详细模式 ,输出更详细的日志信息,通常用于调试。

这些选项可以通过命令行传递给 vue-cli-service,以便在开发和构建过程中自定义其行为。

4. 获取并运行命令:

从解析的参数中获取要执行的命令。
调用服务实例的 run 方法 执行命令,并传递解析的参数

如果执行过程中出现错误,捕获错误并输出,然后终止进程。

Vue CLI 的一个入口脚本,用于根据用户输入的命令和参数启动相应的服务或构建任务

generator/路径下的index.js文件

Vue CLI 服务生成器 的模块,主要用于根据用户的选项配置项目的模板和依赖 。以下是代码的主要功能:
1.模板渲染:

使用 api.render 方法渲染项目模板,并根据是否安装了 Babel 或 TypeScript 插件来决定是否编译代码。

2. 依赖管理:

根据用户选择的 Vue 版本(Vue 2 或 Vue 3),设置相应的项目依赖。

如果是 Vue 2,还会添加 vue-template-compiler 作为开发依赖。

3.脚本和浏览器支持:

扩展 package.json,添加 serve 和 build 脚本,用于启动开发服务器和构建生产环境代码。

配置 browserslist,以支持特定市场份额的浏览器,并根据 Vue 版本决定是否支持 IE 11。

4.CSS 预处理器支持:

根据用户选择的 CSS 预处理器(如 Sass、Less、Stylus),添加相应的开发依赖。

5.Vue 3 兼容性:

如果用户选择了路由或 Vuex,但没有安装相应的插件,则引入默认的路由或 Vuex 配置。

6.额外工具配置:

如果用户提供了额外的配置选项,则将这些配置扩展到 package.json。

7. TypeScript 支持:

如果项目使用 TypeScript,则删除 jsconfig.json 文件,因为 TypeScript 项目通常使用 tsconfig.json。

这段代码的目的是根据用户的选择自动配置 Vue 项目,以便开发者可以快速启动项目开发。

javascript 复制代码
module.exports = (api, options) => {
  // 渲染模板,判断是否使用 Babel 或 TypeScript
  api.render('./template', {
    doesCompile: api.hasPlugin('babel') || api.hasPlugin('typescript'),
    useBabel: api.hasPlugin('babel')
  })

  // 根据 Vue 版本设置依赖
  if (options.vueVersion === '3') {
    api.extendPackage({
      dependencies: {
        'vue': '^3.2.13' // Vue 3 版本
      }
    })
  } else {
    api.extendPackage({
      dependencies: {
        'vue': '^2.6.14' // Vue 2 版本
      },
      devDependencies: {
        'vue-template-compiler': '^2.6.14' // Vue 2 模板编译器
      }
    })
  }

  // 扩展 package.json 的脚本和浏览器列表
  api.extendPackage({
    scripts: {
      'serve': 'vue-cli-service serve', // 启动开发服务器
      'build': 'vue-cli-service build'  // 构建生产环境代码
    },
    browserslist: [
      '> 1%', // 支持市场份额大于 1% 的浏览器
      'last 2 versions', // 支持最新的两个版本
      'not dead', // 不支持已停止更新的浏览器
      ...(options.vueVersion === '3' ? ['not ie 11'] : []) // Vue 3 不支持 IE 11
    ]
  })

  // 根据选择的 CSS 预处理器添加相应的开发依赖
  if (options.cssPreprocessor) {
    const deps = {
      sass: {
        sass: '^1.32.7',
        'sass-loader': '^12.0.0'
      },
      'dart-sass': {
        sass: '^1.32.7',
        'sass-loader': '^12.0.0'
      },
      less: {
        'less': '^4.0.0',
        'less-loader': '^8.0.0'
      },
      stylus: {
        'stylus': '^0.55.0',
        'stylus-loader': '^6.1.0'
      }
    }

    api.extendPackage({
      devDependencies: deps[options.cssPreprocessor]
    })
  }

  // Vue 3 兼容性:如果选择了路由但没有安装插件,则引入路由配置
  if (options.router && !api.hasPlugin('router')) {
    require('./router')(api, options, options)
  }

  // Vue 3 兼容性:如果选择了 Vuex 但没有安装插件,则引入 Vuex 配置
  if (options.vuex && !api.hasPlugin('vuex')) {
    require('./vuex')(api, options, options)
  }

  // 额外的工具配置
  if (options.configs) {
    api.extendPackage(options.configs)
  }

  // 如果使用 TypeScript,删除 jsconfig.json 文件
  if (api.hasPlugin('typescript')) {
    api.render((files) => delete files['jsconfig.json'])
  }
}

cli-service\generator\template\src\App.vue 文件

这段代码是一个 Vue.js 应用程序的模板文件,通常用于生成一个新的 Vue.js 项目。以下是代码的主要作用和结构:

  1. 模板部分:

    根据 rootOptions.vueVersion 判断使用 Vue 3 还是 Vue 2。

    如果是 Vue 3,直接在根元素下显示 Vue 的 logo 和一个 HelloWorld 组件或欢迎标题。

    如果是 Vue 2,使用一个 div 包裹内容,显示 Vue 的 logo 和一个 HelloWorld 组件或欢迎标题。

    rootOptions.bare 用于判断是否显示 HelloWorld 组件或简单的欢迎标题。

  2. 脚本部分:

    导入 HelloWorld 组件。

    定义一个 Vue 组件,名称为 App,并注册 HelloWorld 组件。

  3. 样式部分:

    根据 rootOptions.cssPreprocessor 判断使用哪种 CSS 预处理器。

    如果不是 stylus,则根据选择的预处理器语言设置样式语言。

    定义了 #app 的样式,包括字体、文本对齐、颜色等。

    这段代码通过条件语句和模板语法,动态生成适合不同项目配置的 Vue.js 应用程序模板。

javascript 复制代码
<template>
<%_ if (rootOptions.vueVersion === '3') { _%>
  <img alt="Vue logo" src="./assets/logo.png">
  <%_ if (!rootOptions.bare) { _%>
  <HelloWorld msg="Welcome to Your Vue.js App"/>
  <%_ } else { _%>
  <h1>Welcome to Your Vue.js App</h1>
  <%_ } _%>
<%_ } else { _%>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <%_ if (!rootOptions.bare) { _%>
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <%_ } else { _%>
    <h1>Welcome to Your Vue.js App</h1>
    <%_ } _%>
  </div>
<%_ } _%>
</template>
<%_ if (!rootOptions.bare) { _%>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>
<style<%-
  rootOptions.cssPreprocessor
    ? ` lang="${
        rootOptions.cssPreprocessor.includes('sass')
          ? 'scss'
          : rootOptions.cssPreprocessor
      }"`
    : ``
%>>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
<%_ } else { _%>
<style lang="stylus">
#app
  font-family Avenir, Helvetica, Arial, sans-serif
  -webkit-font-smoothing antialiased
  -moz-osx-font-smoothing grayscale
  text-align center
  color #2c3e50
  margin-top 60px
</style>
<%_ } _%>
<%_ } _%>
相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
沈梦研5 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
轻口味6 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me7 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架