当前位置: 首页 > news >正文

广东省建设安全监督站的网站谷歌搜索广告优化

广东省建设安全监督站的网站,谷歌搜索广告优化,做神秘顾客哪个网站好,黑龙江省建设集团网站文章目录 一、背景二、结论三、vitejs/plugin-vue 插件调试前物料准备vuePlugin 入口buildStart 方法transform 方法 四、vue/compiler-sfc 核心包parse 方法compileScript、rewriteDefault 方法compileTemplate 方法 五、整体架构六、总结参考资料 一、背景 最近正在研究 rea…

文章目录

    • 一、背景
    • 二、结论
    • 三、@vitejs/plugin-vue 插件
      • 调试前物料准备
      • vuePlugin 入口
      • buildStart 方法
      • transform 方法
    • 四、@vue/compiler-sfc 核心包
      • parse 方法
      • compileScript、rewriteDefault 方法
      • compileTemplate 方法
    • 五、整体架构
    • 六、总结
    • 参考资料

一、背景

最近正在研究 react jsx 转化为 js 的过程,在学习完成之后,突然想到既然 react 是用过 babel 完成 jsx 的转化,那 vue 是不是也是使用 babel 的呢,带着这些疑问我开始探索 vue 的编译过程,经过一些资料的查询发现好像和 react 不太一样,但是网上却很少有深入的文章,因此我开始对源码的探索。

二、结论

vue 3 组件在编译过程中使用了 babel/parse 处理 script 中 js 代码处理为普通 js 代码,其余解析均未使用;下面我们将从源码层面解读。

三、@vitejs/plugin-vue 插件

调试前物料准备

  • vue 3 + vite
  • vscode

添加入口断点:

在这里插入图片描述

  • 找到入口文件 vite.config.js
  • 找到对应解析插件 vitejs/plugin-vue 插件 并在对应使用处打上断点
  • 在控制台打开 js 调试终端 (调试方法和浏览器类似)
  • 在对应终端启动我们的项目

vuePlugin 入口

进入 vue() 方法调用中,会出现 vuePlugin 方法这个方法暴露了很多配置属性,因为我们目的关注编译打包过程,所以我们这次只需关系核心的 buildStart 和 transform 即可,因此我们在这两个方法中打上断点

// src/index.ts
function vuePlugin(rawOptions = {}) {// xxxx 省略return {name: "vite:vue",handleHotUpdate(ctx) {},config(config) {},configResolved(config) {},configureServer(server) {},// 开始打打包时处理的内容buildStart() {options.compiler = options.compiler || resolveCompiler(options.root);},async resolveId(id) {},load(id, opt) {},// 转化代码时执行的内容transform(code, id, opt) {// xxxx 省略}};
}

buildStart 方法

buildStart 方法主要是在服务启动前拿到编译的配置

在这里插入图片描述

接下来我们在 build 处打上断点看之后的流程,在控制台输入 options 查看其中内容:

在这里插入图片描述

此图可以看出最初 compiler 为空,我们的代码执行了 resolveCompiler 方法,并把结果存入了 options.compiler 中,为了清楚该方法做了什么,我们 step into 看一下这个方法的实现。

在这里插入图片描述

这个代码可以看出其实就是加载了并且返回了 vue/compiler-sfc 这个核心包,那加载这个包是做什么呢,我们可以接着往下看,继续走下一个断点,然后会发现我们项目启动了,并没有走到下一个断点。

在这里插入图片描述

transform 方法

那么是什么时候怎么才能走到我们的 transform 中呢?,(vite 的特点:先启动再根据加载页面按需加载所需要编译的代码),明白这一点之后我们只需要在浏览器访问这个地址:我这里就是 http://localhost:3000/ 访问之后发现我们的断点进入到了 transform 中:

在这里插入图片描述

从这边也可以看出 vite 打包为什么比 webpack 快

继续看 transform 里面的代码,可以看到 return transformMain() 这个就是我们的核心转化方法,我们继续 step into 该方法:

在这里插入图片描述

接着我们看一下这个方法的入参:

  • code: 就是我们的源代码
  • filename:这个文件的路径
  • options:配置项
  • pluginContext:插件的上下文(this)
  • ssr:暂不考虑
  • asCustomElement:暂不考虑

然后我们其实核心要看的就是这个 code -> 原生 js 的转化,因此往下看这个 code 都在哪里使用,首先我们就可以看到 createDescriptor 这个方法,这个时候我们打印一下descriptor 得到如下图:
在这里插入图片描述

发现我们 code 被解析如下三个部分 templatestylesscript。接着看这里的代码发现如下图 3 行代码:

// 解析 descriptor 中的 script 部分
const { code: scriptCode, map } = await genScriptCode(descriptor, options, pluginContext, ssr);// 解析 descriptor 中的 style 部分
const stylesCode = await genStyleCode(descriptor, pluginContext, asCustomElement, attachedProps);// 解析 descriptor 中的 template 部分
const ({ code: templateCode, map: templateMap } = await genTemplateCode(descriptor, options, pluginContext, ssr));

然后在这里其实就比较清晰了,createDescriptor 先对源代码进行了初步解析,然后返回了 descriptor,然后我们进入 genScriptCodegenStyleCodegenTemplateCode 这三个方法进行具体代码转化。

接下来我们看下这四个方法的具体实现(只保留核心代码):

// 得到原始的 descriptor
function createDescriptor(filename, source, { root, isProduction, sourceMap, compiler }) {const { descriptor, errors } = compiler.parse(source, {filename,sourceMap});return { descriptor, errors };
}// 处理 descriptor 中 script 部分
async function genScriptCode(descriptor, options, pluginContext, ssr) {// 只保留核心代码const script = resolveScript(descriptor, options, ssr);scriptCode = options.compiler.rewriteDefault(script.content, "_sfc_main", xxx);return {code: scriptCode,map};
}
// 处理 css 
async function genStyleCode(descriptor, pluginContext, asCustomElement, attachedProps) {//  没有使用 compiler
}
// 处理 template
async function genTemplateCode(descriptor, options, pluginContext, ssr) {const template = descriptor.template;if (!template.lang && !template.src) {return transformTemplateInMain(template.content, descriptor, options, pluginContext, ssr);}
}function transformTemplateInMain(code, descriptor, options, pluginContext, ssr) {const result = compile(code, descriptor, options, pluginContext, ssr);
}function compile(code, descriptor, options, pluginContext, ssr) {const result = options.compiler.compileTemplate(__spreadProps(__spreadValues({}, resolveTemplateCompilerOptions(descriptor, options, ssr)), {source: code}));return result;
}function resolveScript(descriptor, options, ssr) {resolved = options.compiler.compileScript(descriptor, __spreadProps(__spreadValues({}, options.script), {// xxx}));return resolved;
}

genStyleCode 则处理为 import "/Users/zcy/Desktop/毕设/smart-port/src/App.vue?vue&type=style&index=0&lang.less" 后续文章中会介绍为什么这个东西是怎么解析的,本文不会过多讲解。

经过上面代码分析:可以看出核心处理方法为:

options.compiler.compileTemplate、
options.compiler.compileScript、 
options.compiler.rewriteDefault、
options.compiler.parse

此时再看 options.compiler 这个对象是不是很眼熟呢?这个就是在 buildStart 中 获取到的 vue/compiler-sfc 核心包源码如下:

options.compiler = options.compiler || resolveCompiler(options.root);

因此我们要看懂到底是怎么解析 vue 组件的,就需要深入这个包中。

四、@vue/compiler-sfc 核心包

parse 方法

我们在 options.compiler.parse 方法调用处打上断点,然后我们逐层进入方法:

在这里插入图片描述
在这里插入图片描述

我们进入到了 parse 方法这边可以看到有一个 ast 的转化,如下图调用了 compiler.parse 方法,经过分析发现这个方法源于,@vue/compiler-dom ,从这个包的依赖看出并没有使用 babel,略过这个核心包,因此得出结论 parse 方法中没有使用 babel。

在这里插入图片描述

compileScript、rewriteDefault 方法

继续刚才操作我们看 compileScript 方法:

在这里插入图片描述

顺腾摸瓜找到 parser$2 这个变量的源头

var parser$2 = require('@babel/parser');

在这里插入图片描述

rewriteDefault 也是如此:

在这里插入图片描述

因此得出结论在 script 的解析中会使用 @babel/parse。下面为解析后的源码:

import { ref } from 'vue';const _sfc_main = {setup(__props, { expose }) {expose();const state = ref(1)const __returned__ = { state, ref }
Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true })
return __returned__
}
}

compileTemplate 方法

同样使用了 @vue/compiler-dom 进行转化,具体转化细节就不进行详细展开了, 结果会转化为一个 render 函数如下:

import { resolveComponent as _resolveComponent, createVNode as _createVNode, toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"const _hoisted_1 = { id: "nav" }function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {const _component_router_link = _resolveComponent("router-link")const _component_router_view = _resolveComponent("router-view")return (_openBlock(), _createElementBlock(_Fragment, null, [_createElementVNode("div", _hoisted_1, [_createVNode(_component_router_link, { to: "/login" }),_createVNode(_component_router_link, { to: "/" }),_createElementVNode("div", null, _toDisplayString($setup.state), 1 /* TEXT */)]),_createVNode(_component_router_view)], 64 /* STABLE_FRAGMENT */))
}ƒ

在这里插入图片描述

五、整体架构

在这里插入图片描述

六、总结

本文只是出于好奇浅浅研究下了一下 vue3 的编译过程,和其中涉及到 babel 使用的点,对于很多细节没有深入研究,因此只做了一个简单的分析,希望对大家有参考价值。

参考资料

  • 原来 vue3 文件编译是这样工作的!看完后更懂vue3了
http://www.hkea.cn/news/961390/

相关文章:

  • 广告免费设计在线生成网站排名优化
  • 余姚公司网站建设怎么建网址
  • 网站域名授权怎么做市场营销案例100例
  • kindeditor代码高亮 wordpressseo优化排名经验
  • 家乡介绍网页设计上海网站排名优化
  • 广州黄埔网站制作百度sem是什么意思
  • 网站流量分析网站网络推广营销网
  • 化妆品网站建设计划书网站维护是什么意思
  • 建设局网站公告宣传推广的形式有哪些
  • 网站基本架构设计的主要步骤什么软件可以排名次
  • 代做毕业设计网站多少钱网站推广交换链接
  • 苹果指争议广告lg广告北京seo公司网站
  • flash网站制作公司能打开各种网站的浏览器下载
  • 网站开发是叫系统吗站长工具seo排名查询
  • 站长之家html模板西安网站seo技术厂家
  • 重庆网站建设 渝seo交流论坛
  • 洛阳市网站建设宁波seo网络推广软件系统
  • 做网站用建站模版好还是定制好百度站点
  • 关注济南网站建设深圳市企业网站seo
  • 安溪县住房和城乡建设网站色盲
  • 合肥做英文网站今日头条国际军事新闻
  • 西安有哪些做网站的公司好邵阳疫情最新消息
  • asia域名的网站竞价广告
  • 怎么注册公司支付宝账号seo求职信息
  • 多语言网站怎么做网络推广平台公司
  • 山东公司注册网站怎样写营销策划方案
  • 河北省香河县建设局网站中国互联网协会
  • 北京丰台区网站建设游戏推广赚佣金的平台
  • 网站没排名怎么办搜索引擎广告优化
  • wordpress内容主题模板网络网站推广选择乐云seo