最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • [Vue源码系列-1]vue3源码架构分析

    正文概述 掘金(我的幸运7)   2021-02-26   930

    1. vue2和vue3的区别

    • vue3的源码采用monorepo管理方式,实现了从模块管理包管理的转变
    • vue2采用的是Flow来做静态类型检测,而vue3使用typescript重构代码,增强类型检测。
    • vue2的方法都放在实例对象上,而vue3中都是函数形式,所以vue3支持tree-shaking,不使用就不会被打包
    • vue2的数据劫持是通过defineProperty,而这也是vue2最大的性能问题,所以vue3中使用Proxy实现数据劫持
    • vue3对模板编译进行了优化,编译时生成Block tree可以收集动态节点,减少比较
    • vue3采用compositionApi进行组织功能,优化复用逻辑,相较于optionApi类型推断更加便捷
    • 增加了 Fragment,TeleportSuspense组件

    2. Vue架构分析

    [Vue源码系列-1]vue3源码架构分析

    2.1 Monorepo

    • 一个仓库中维护多个包
    • 便于版本管理、依赖管理,模块间的引用,调用都非常的方便
    • 缺点就是仓库的体积会变大

    2.2 Vue3的项目结构

    • reactivity:响应式系统
    • runtime-core:与平台无关的运行时核心 (可以创建针对特定平台的运行时 - 自定义渲染器)
    • runtime-dom: 针对浏览器的运行时。包括DOM API,属性,事件处理等
    • runtime-test:用于测试
    • server-renderer:用于服务器端渲染
    • compiler-core:与平台无关的编译器核心
    • compiler-dom: 针对浏览器的编译模块
    • compiler-ssr: 针对服务端渲染的编译模块
    • compiler-sfc: 针对单文件解析
    • size-check:用来测试代码体积
    • template-explorer:用于调试编译器输出的开发工具
    • shared:多个包之间共享的内容
    • vue:完整版本,包括运行时和编译器

    [Vue源码系列-1]vue3源码架构分析

    3. 基于rollup搭建vue3环境

    3.1 安装依赖

    • typescript:支持typescript
    • rollup:打包工具
    • rollup-plugin-typescript2:rollup 和 ts的 桥梁
    • @rollup/plugin-node-resolve:解析node第三方模块
    • @rollup/plugin-json:支持引入json
    • execa:开启子进程方便执行命令
    npm install typescript rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa -D
    

    3.2 workspace配置

    nmp iniy -y		// 初始化 package.json 文件
    npx tsc --init	// 初始化 ts 配置文件
    
    {	// 在package.json 中添加以下字段
      "private":true,
      "workspaces":[
        "packages/*"
      ],
      // ...
    }
    
    • 创建packages文件夹用于管理包模块,文件夹下就是vue的各个包模块了

    • 创建reactivity文件夹,其中src中是核心代码,package.json则是管理当前包的配置文件

    [Vue源码系列-1]vue3源码架构分析

    {
      "name": "@vue/reactivity",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "module": "dist/reactivity.esm-bundler.js",
      "author": "",
      "license": "ISC",
      "buildOptions":{	// 自定义配置,rollup打包时使用
        "name":"VueReactivity",
        "formats":[
          "esm-bundler",
          "cjs",
          "global"
        ]
      }
    }
    

    3.3 配置scripts脚本

    {
    	"scripts": {
        	"dev":"node script/dev.js",			// 打包单个包
        	"build":"node script/build.js"		// 打包所有包
      	}
    }
    
    > script
      - build.js
      - dev.js
    

    build.js

    // 把 packages 目录下的所有包都进行打包
    const fs = require('fs');
    const execa = require('execa'); // 开子进程使用 rollup 打包
    
    const targets = fs.readdirSync('packages').filter(f => {
        if(!fs.statSync(`packages/${f}`).isDirectory()){
            return false;
        }
        return true;
    })
    
    // 对我们目标进行一次打包,并行打包
    async function build(target){
        // rollup -c --environment TARGET:reactivity
        await execa('rollup',['-c','--environment',`TARGET:${target}`],{stdio:'inherit'});  // 将子进程打包的信息共享给父进程
    }
    
    function runParallel(targets,iteratorFn){
        const res = [];
        for(const item of targets){
            const p = iteratorFn(item);
            res.push(p);
        }
        return Promise.all(res);
    }
    
    runParallel(targets,build)
    

    dev.js

    // 只针对具体的某个包打包
    const fs = require('fs');
    const execa = require('execa'); // 开启子进程 进行打包, 最终还是使用rollup来进行打包
    
    const target = 'reactivity'		// 后期可根据传入的target做打包
    
    async function build(target){ 
        await execa('rollup',['-cw','--environment',`TARGET:${target}`],{stdio:'inherit'}); // 当子进程打包的信息共享给父进程
    }
    build(target)
    

    3.4 rollup配置

    rollup.config.js

    import path from 'path';
    import ts from 'rollup-plugin-typescript2'
    import json from '@rollup/plugin-json'
    import resolvePlugin from '@rollup/plugin-node-resolve'
    
    // 根据环境变量中的target属性 获取对应模块中的 pakcage.json
    const packagesDir = path.resolve(__dirname, 'packages'); 
    // packageDir 打包的基准目录
    const packageDir = path.resolve(packagesDir, process.env.TARGET); // 获取要打包的目标目录
    const name = path.basename(packageDir); // 获取打包的名字
    const resolve = p => path.resolve(packageDir, p);	// 永远针对的是某个模块
    const pkg = require(resolve(`package.json`)) // 获取目标对应的package.json
    
    const outputConfigs = {
        'esm-bundler': {
            file: resolve(`dist/${name}.esm-bundler.js`), // webpack打包用的
            format: `es`
        },
        'cjs': {
            file: resolve(`dist/${name}.cjs.js`), // node使用的
            format: 'cjs'
        },
        'global': {
            file: resolve(`dist/${name}.global.js`), // 全局的
            format: 'iife'
        }
    }
    
    const packageOptions = pkg.buildOptions; // 打包的选项
    function createConfig(format, output) {
        output.name = packageOptions.name;
        output.sourcemap = true;
        return {
            input: resolve(`src/index.ts`), // 入口
            output,
            plugins:[
                json(),
                ts({
                    tsconfig:path.resolve(__dirname,'tsconfig.json')
                }),
                resolvePlugin(),
            ]
        }
    }
    // rollup 最终需要到出配置
    export default packageOptions.formats.map(format => createConfig(format, outputConfigs[format]));
    

    起源地下载网 » [Vue源码系列-1]vue3源码架构分析

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元