Vue3源码实现(一)- 环境搭建

前言

最近在看 Vue3 源码,为了加深理解和串联起来整体的逻辑,下面我们也构建一个自己的 mini-vue ,麻雀虽小,五脏俱全。本文先把环境搭起来。

开发环境搭建

搭建 Monorepo 环境

Vue3 使用的是 pnpm workspace 来实现 monorepo ( pnpm 是快速、节省磁盘空间的包管理器,采用符号链接的方式来管理模块 )

  1. 全局安装 pnpm

    npm install pnpm -g #全局安装pnpm
    pnpm init -y # 初始化配置文件
    
  2. 配置 .npmrc 文件

    在这里 vue3 源码 并没有配置该文件,因为没有对应的需求,我是在 pnpm 上找到的,便于我们后续引用一些包的依赖,例如:我们在全局安装了 vue ,默认情况下,它里面的依赖不会被提升到 node_modules 下,所以我们添加了如下配置,该设置可以将所依赖的模块提升到 node_modules 中,在 npm 下是不需要配置的

    shamefully-hoist=true 或者
    public-hoist-pattern=*
    

    image.png

    效果如下图:左侧是没有添加配置,右侧是加了配置的,node_module 里面的依赖有了明显的不同

  3. 配置 pnpm-workspace.yaml 文件

    该配置定义了 工作空间的根目录,也就是我们的 packages 目录

    packages:
        - 'packages/*'
    

    image.png

    当我们配置了该文件后,以后安装依赖会报如下错误,解决办法就是 在最后追加 -w 的标识,表示我要安装在 workspace-root 的下面

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/de87b64148a548c1b9012b8ba2ab5d84~tplv-k3u1fbpfcp-watermark.image?)
  1. 安装开发时依赖
    pnpm install typescript esbuild minimist -w -D
    
  2. 配置 tsconfig.json:目的是在 packages 里面 一个模块引用其他的模块,使用 ts 来支持导入,不至于导入报错,编辑器飘红
    {
       "compilerOptions": {
         "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
         "module": "ESNext",                                /* Specify what module code is generated. */
         "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
         "baseUrl": ".",                                  /* Specify the base directory to resolve non-relative module names. */
         "lib": ["esnext", "dom"],
         "paths": {
           "@vue/*": ["packages/*/src"]
         },                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
         "sourceMap": true,
         "outDir": "dist",                                   /* Specify an output folder for all emitted files. */
         "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
         "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
    
         /* Type Checking */
         "strict": true,                                      /* Enable all strict type-checking options. */
         "skipLibCheck": true,                                 /* Skip type checking all .d.ts files. */
         "resolveJsonModule": true
       }
     }
    
  3. 开发时打包配置:scripts/dev.js:基于 esbuild 实现开发环境打包,使用 minimest 来解析命令行参数,进一步可以设置打包产物的路径 和 输出产物的类型格式,如 iife || cjs || esm
    const args = require("minimist")(process.argv.slice(2));
    const { build } = require("esbuild");
    const { resolve } = require("path");
    
    const target = args._[0];
    const format = args.f;
    
    const pkg = require(resolve(__dirname, `../packages/${target}/package.json`))
    
    const outputFormat = format.startsWith('global') ? 'iife' : format === 'cjs' ? 'cjs' : 'esm' 
    
    const outfile = resolve(__dirname, `../packages/${target}/dist/${target}.${format}.js`)
    
    build({
     entryPoints: [resolve(__dirname, `../packages/${target}/src/index.ts`)],
     outfile,
     bundle: true,
     sourcemap: true,
     format: outputFormat,
     globalName: pkg.buildOptions.name,
     platform: format === 'cjs' ? 'node' : 'browser',
     watch: {
       onRebuild(error) {
         if (!error) console.log('rebuild~~');
    
       }
     }
    }).then(() => {
     console.log('watching~~');
    })
    
    
  4. 设置 package.jsonscripts 命令 执行上一步脚本,并通过设置参数作为入参。
    "scripts": {
       "dev": "node scripts/dev.js reactivity -f global"
    }
    

响应式模块配置先行

因为下一节我们重点实现响应式模块,所以这里我们先配置下打包相关。

./packages
 ├─ reactivity
     ├─ src
         └─ index.ts
     └─  package.json
// packages/reactivity/package.json
{
   "name": "@vue/reactivity", // 和 core 保持一致
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "buildOptions": {
     "name": "VueReactivity", // 打包后暴露出去的方法名字
     "formats": [ // 定义打包格式
       "global",
       "cjs",
       "esm-bundler"
     ]
   }
 }

猜你喜欢

转载自juejin.im/post/7123886199311499271
今日推荐