关于 vue/cli 脚手架实现项目编译运行的源码解析

news2024/9/21 14:45:42

1.vue项目运行命令解析

在日常开发中,vue 项目通过vue-cli-service脚手架包将项目运行起来,常用的命令例如:

npm run serve

npm run build

上述执行命令实际一般对应为项目中 package.json 文件的 scripts属性中编写的脚本命令,在项目目录中的终端运行时即匹配到对应的脚本命令,例如:

匹配对应的脚本命令,例如npm run serve ,即运行 vue-cli-service serve 脚本命令,此时,会去加载项目中 node_modules 文件夹中的.bin 文件找到对应的执行文件,如下:

 2.关于 node_modules 中 vue-cli-service 文件的加载过程

在加载 vue-cli-service 文件的过程,我们知道mode_modules 中.bin 文件对应的是链接文件,即实际会找到 node_modules 文件夹下的vue-cli-service 依赖包中的对应vue-cli-service.js文件加载运行

即找到 node_modules 文件夹下的@vue包下面的cli-service包下的vue-cli-service.js 文件进行运行,如下:

可以看到.bin 文件中的 vue-cli-service 文件与@vue/cli-service/bin/vue-cli-service.js 文件内容一致,实际运行的也是@vue/cli-service/bin/vue-cli-service.js,可以发现文件中主要引入了../lib/Service文件,并创建 service 类,调用 service 类中的 run 方法,接下来就是对应找到service 类中对应的 run 方法的运行内容。

注意:传入 run 方法中的 command在运行 npm run serve时,这时的 command即等于字符串 serve  即脚本命令中的后面的参数

我们找到/lib/Service 文件,如下:

可以看到 run 方法中主要调用了 fn 函数,fn 从方法中的 command中取出,command从 this.commands通过[name]取出,即 this.commands['serve'],但是在该文件中可以看到 commands 并没有什么初始化赋值操作,如下:

此时回到 run 方法中可以看到在执行 fn 函数前,主要执行了这两个方法,我们主要看 init 初始化函数,setPluginsToSkip 方法主要是做对一些内置 plugins 进行忽略

    // --skip-plugins arg may have plugins that should be skipped during init()
    // 需要忽略的默认 plugins
    this.setPluginsToSkip(args)

    // load env variables, load user config, apply plugins
    this.init(mode)

找到 init() 方法, 如下

在 init 方法中我们主要看这段代码,其他代码是主要做一些配置处理,实际主要是看 apply 方法的的调用

    this.plugins.forEach(({ id, apply }) => {
      if (this.pluginsToSkip.has(id)) return
      apply(new PluginAPI(id, this), this.projectOptions)
    })

可以看到是对文件中的 this.plugins 进行循环,结构每个 item 中的 apply 方法进行调用,我们找到 plugins 的初始化,如下:

可以看到,Service 类中初始化是对 plugins 赋值通过调用了 resolvePlugins 方法进行初始化,如下:

在resolvePlugins 方法中我们可以看到遍历了builtInPlugins,进行赋值给 plugins 并返回

此时回到 init 方法中对 this.plugins的遍历即 apply 调用:

我们即可得知,apply 的调用,是对 resolvePlugins方法中的的 require(id)调用,如下:

在 run serve的时候,实际即对应 require('./commands/serve')去加载对应该文件,我们进入到该文件, 如下:

查看./commands/serve文件可以看到,文件主要导出了上述的回调函数,回调函数内部调用了api.registerCommand函数,关于为什么可以取到到 api.registerCommand调用,我们就要回到apply() 函数调用的时候的传参,如下:

可以看到是创建了 PluginAPI这个类,并把 id 传入(./commands/serve等等)及当前上下文 this,我们找到 PluginAPI的类文件,如下:

可以看到PluginAPI类中的定义了registerCommand方法,而该方法的内容中可以看到对 this.service.commands[name] 赋值了{fn,opts}对象,这就解释了前面@vue/cli-service/bin/vue-cli-service.js中的 run 方法为什么可以取出 fn 函数进行调用,即下图:

此时我们最后来看 fn函数,对应的是什么内容,如下:

最后我们去看 serve()函数内容, 如下:

3.找到 webpack加载文件处

可以看到熟悉的Starting development server...,即项目运行时终端中会打印的信息,继续往下查看该函数,最终可以看到运用 webpack 包,并传入config配置解析,并使用 WebpackDevServer 这个 plugin,即开启本地运行的插件, 如下:

函数的最后我们可以看到,启动了 server 的监听函数,即成功将项目编译完成开启本地服务运行,如下:

4.总结

通过解析vue-cli-serve的源码,以上便是 vue-cli脚手架 运用 webpack 进行内部封装,如何实现脚手架内将项目解析打包,加载在内存中,并拉起本地服务,实现本地运行vue项目的流程。

npm run serve -> vue-cli-service.js ->service.run ->service.init ->apply ->require('./commanmds/serve') ->PluginAPI.registerCommand -> serve()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2134424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】——string类的模拟实现

目录 一、string模拟实现 1.1构造析构 1.2迭代器 1.3修改 1.4查找 1.5substr 深浅拷贝的区别 1.6比较函数与流插入流提取 二、string类的拷贝 2.1浅拷贝与深拷贝 2.2传统版与现代版区别 2.3写时拷贝(了解) 三、vs和g下string结构的说明 3.1v…

spring security OAuth2 搭建资源服务器以及授权服务器/jdbc/jwt两种方案

一、认证服务器基于jdbc方式 如果不懂请移步上一篇文章:Spring security OAuth2 授权服务器搭建-CSDN博客 在上一篇文章中,TokenStore的默认实现为 InHenoryTokenStore 即内存存储,对于 CLient 信息,userDetaitsServce 接负责从存…

vue项目如何在js文件中导入assets文件夹下图片

前言: 之前在vuewebpack项目中动态导入图片时,是使用的require()函数。但是在vite中不支持require()函数,换成了new URL()方式。 项目中使用:

使用 element UI 实现自定义日历

效果如下&#xff1a; HTML代码部分&#xff1a; <el-calendar v-model"value"><!-- 这里使用的是 2.5 slot 语法&#xff0c;对于新项目请使用 2.6 slot 语法--><template slot"dateCell" slot-scope"{date, data}"><!--…

简单示例,搞懂PowerBI的ALL(),ALLEXCEPT()和ALLSELECTED()的区别

假设我们有如下数据&#xff0c;我们来统计下各班级的人数 我们在报表页里加上 班级’二班‘ 的筛选条件&#xff0c;此时PowerBI已经自动为我们显示了各班级人数&#xff1a;一班有3人&#xff0c;二班有1人。 根据我们的筛选条件&#xff0c;我们的统计人数应该是按照筛选器&…

解决RabbitMQ设置TTL过期后不进入死信队列

解决RabbitMQ设置TTL过期后不进入死信队列 问题发现问题解决方法一&#xff1a;只监听死信队列&#xff0c;在死信队列里面处理业务逻辑方法二&#xff1a;改为自动确认模式 问题发现 最近再学习RabbitMQ过程中&#xff0c;看到关于死信队列内容&#xff1a; 来自队列的消息可…

【YashanDB知识库】archivelog磁盘满导致数据库abnormal

本文转自YashanDB官网&#xff0c;具体内容可见archivelog磁盘满导致数据库abnormal 【问题分类】功能使用 【关键字】磁盘空间满&#xff0c;archivelog日志&#xff0c;archivelog自动清理 【问题描述】数据库状态变更为abnormal&#xff0c;检查V$DIAG_INCIDENT视图&#…

足底筋膜炎5天自愈方法

足底筋膜炎并没有确切的5天自愈方法。足底筋膜炎是足底筋膜的一种无菌性炎症&#xff0c;主要症状是脚后跟部位的疼痛&#xff0c;这种疼痛通常是由于长时间站立、行走或跑步等引起的足底筋膜过度牵拉所致。由于这是一种慢性炎症&#xff0c;其恢复过程往往需要一定的时间&…

docker查看从当前最后100条起看日志

logs.sh 使用说明 logs.sh 是一个用于查看 Docker 容器日志的脚本。该脚本支持两种使用方式&#xff1a; 默认查看 video-console 容器的日志。通过指定容器 ID 来查看相应容器的日志。 1. 默认方式 不需要任何参数&#xff0c;直接运行脚本&#xff0c;将自动查找名为 vid…

百度副总裁陈洋:大模型让软件开发更高效、更安全

&#x1f381;&#x1f449;点击进入文心快码 Baidu Comate 官网&#xff0c;体验智能编码之旅&#xff0c;还有超多福利&#xff01;&#x1f381; 9月11日-12日&#xff0c;CCS 2024成都网络安全系列活动在成都举行。百度副总裁陈洋出席大会开幕式并进行主题分享。陈洋表示&a…

postgres_fdw访问存储在外部 PostgreSQL 服务器中的数据

文章目录 一、postgres_fdw 介绍二、安装使用示例三、成本估算四、 远程执行选项执行计划无法递推解决 参考文件&#xff1a; 一、postgres_fdw 介绍 postgres_fdw 模块提供外部数据包装器 postgres_fdw&#xff0c;可用于访问存储在外部 PostgreSQL 服务器中的数据。 此模块…

C语言代码练习(第二十三天)

今日练习&#xff1a; 65、有 n 个整数&#xff0c;使前面各数顺序向后移动 m 个位置&#xff0c;最后 m 个数变成最前面 m 个数&#xff0c;写一函数实现以上功能&#xff0c;在主函数中输入 n 个整数和输出调整后的 n 个数。&#xff08;要求用指针&#xff09; 66、 n 个人围…

JavaScript 基础 - 第17天_AJAX综合案例

文章目录 Day02_AJAX综合案例目录学习目标01.案例_图书管理-介绍目标讲解小结 02.Bootstrap 弹框_属性控制目标讲解小结 03.Bootstrap 弹框_JS控制目标讲解小结 04.案例_图书管理\_渲染列表目标讲解小结 05.案例_图书管理\_新增图书目标讲解小结 06.案例_图书管理\_删除图书目标…

网络编程Udp协议

文章目录 UDP协议1、什么是UDP协议&#xff1f;一、定义与基本概念二、主要特点三、报文格式四、应用场景五、总结 2、如何使用Java中的UDP套接字&#xff1f;一、UDP常用APIDatagramSocketDatagramPacket 二、UDP协议下的客户端-服务器服务器客户端 UDP协议 UDP协议&#xff…

电脑怎么录制视频?游戏直播、教学分享必备!

在数字化时代&#xff0c;电脑录屏已成为游戏直播、教学分享、会议记录等多种场景下的必备技能&#xff0c;但有些朋友可能不知道怎么高效又清晰的录制视频&#xff0c;下面就给大家汇总了几个简单方法&#xff0c;一起来学习下吧~ 1. 嗨格式录屏大师 录屏大师软件免费下载_高…

方位大模型教程:从基础入门到实战应用

2024年大西洋彼岸的OpenAi公司&#xff0c;首次向世界吹响「大模型主导未来世界变革」的号角。 AI大模型&#xff0c;正在构建的颠覆力&#xff0c;为了更好的入局AI大模型&#xff0c;这次我特意复盘和整理大模型学习脉络&#xff0c;开了30节大模型的课程&#xff0c;包含大…

推荐一个java屏幕共享项目

java 屏幕共享项目 https://github.com/SpringStudent/JavaDesktopShare

【JAVA入门】Day44 - 字节打印流和字符打印流

【JAVA入门】Day44 - 字节打印流和字符打印流 文章目录 【JAVA入门】Day44 - 字节打印流和字符打印流一、字节打印流二、字符打印流三、输出语句和打印流的关系 打印流也是一种高级包装流&#xff0c;但是它只有输出&#xff0c;没有输入。 打印流一般是指&#xff1a;…

Qt_控件的QWidget属性介绍

目录 1、QWidget的核心属性 2、enabled 3、geometry 3.1 代码测试geometry 4、windowTitle 4.1 代码测试windowTitle 5、windowIcon 5.1 QIcon设置图标 5.2 qrc机制 5.3 代码测试windowIcon 6、windowOpacity 6.1 代码测试windowOpacity 7、cursor 7.1 代码测试…

使用xjar+exe4j+inno setup把加密后的jar打包成exe应用程序并创建服务

1、使用xjar对jar包进行加密 在项目的pom.xml中加入xjar的插件依赖&#xff0c;最好用2.x.x版本&#xff0c;高版本不支持-Dxjar.mode&#xff0c;无法免密码启动 github地址&#xff1a;xjar-maven-plugin <plugin><groupId>com.github.core-lib</groupId>…