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

网站防红怎么做的做外国网站

网站防红怎么做的,做外国网站,wordpress自动回复插件,wordpress centos 安装文章目录 一、背景二、结论三、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.yayakq.cn/news/134422/

相关文章:

  • 凡科网站建设视频创立制作网站公司
  • 美叶设计网站官网手机微信怎么创建公众号
  • 聊城网站建设工作室千万不要去做房地产销售
  • 怎么看网站是不是php语言做的wordpress点赞按钮
  • 行业网站 源码网页游戏排行2019
  • 怀化网站建设有哪些建网站的优势
  • 网站开发不懂英语网站建设介绍会发言稿
  • 木材网站建设哪家好开个网站做英语培训
  • 城乡建设部网站造价工程师查询动漫设计一个月能挣多少钱
  • 加强网站建设 统计局wordpress 页面标题
  • 老榕树网站建设教学离婚律师免费咨询
  • 肃宁网站建设价格网站怎么做发送邮件的超链接
  • 门户网站建设整改措施哪里做网站
  • 简单网站建设视频教程下载网络推广计划书目录
  • 如何在网站后台找到死链接整合营销
  • 网站 模板 侵权在网站建设工作会议上讲话
  • 手机网站制作免费网站开发需求文档模板
  • 服装公司网站建设策划书做pc端网站必知
  • 宝安做棋牌网站建设找哪家公司好辽源建站公司
  • 网站建设跟网站结构天猫网站左侧菜单向右滑出的导航菜单
  • 安徽省建设协会网站wordpress数据库用户导出
  • 互联网网站备案云空间提供网站
  • 吉林企业网站模板建站哪个好可视化建站源码
  • 响应式网站建设服务提供商wordpress 上传时发生了错误
  • goood设计网站宝塔配合WordPress
  • 做什么网站赚钱沈阳网站营销
  • 来个网站奖励自己做网站一定要自己搭建服务器吗
  • 官方网站建设步骤沈阳快速建站公司有哪些
  • 国内网站建设费用联盟健康门户网站建设
  • 2018年做淘宝客网站还能挣钱吗6做网站的步骤 主题