「试着读读 Vue 源代码」工程目录及本地运行(断点调试)

2,607 阅读3分钟

说明

  • 首先这篇文章是读 vue.js 源代码的梳理性文章,文章分块梳理,记录着自己的一些理解及大致过程;更重要的一点是希望在 vue.js 3.0 发布前深入的了解其原理。

  • 如果你从未看过或者接触过 vue.js 源代码,建议你参考以下列出的 vue.js 解析的相关文章,因为这些文章更细致的讲解了这个工程,本文只是以一些 demo 演示某一功能点或 API 实现,力求简要梳理过程。

  • 如果搞清楚了工程目录及入口,建议直接去看代码,这样比较高效 ( 遇到难以理解对应着回来看看别人的讲解,加以理解即可 )

  • 文章所涉及到的代码,基本都是缩减版,具体还请参阅 vue.js - 2.5.17

  • 如有任何疏漏和错误之处欢迎指正、交流

简单谈谈工程结构

上图简单介绍了整个 vue.js 的工程目录,我们关注的点:

  • 如何使 vue.js 跑起来,即本地运行(降低代码阅读难度)
  • 如何下手阅读,即找到我们所关心的入口(紧接着顺着思路往下走)

本地运行(断点调试)

首先找到 package.json

  ...
  "scripts": {
     "dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",
     "dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-cjs",
     "dev:esm": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-esm",
     "dev:test": "karma start test/unit/karma.dev.config.js",
     "dev:ssr": "rollup -w -c scripts/config.js --environment TARGET:web-server-renderer",
     "dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:web-compiler ",
     "dev:weex": "rollup -w -c scripts/config.js --environment TARGET:weex-framework",
     "dev:weex:factory": "rollup -w -c scripts/config.js --environment TARGET:weex-factory",
     "dev:weex:compiler": "rollup -w -c scripts/config.js --environment TARGET:weex-compiler ",
     "build": "node scripts/build.js",
     "build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
     "build:weex": "npm run build -- weex",
     "test": "npm run lint && flow check && npm run test:types && npm run test:cover && npm run
              test:e2e -- --env phantomjs && npm run test:ssr && npm run test:weex",
     "test:unit": "karma start test/unit/karma.unit.config.js",
  },
  ...

就本地运行、断点调试,我们只需关注 ”dev“ 选项;简单解释一下,npm run dev 执行 scripts/config.js 目标为 web-full-dev

config.js 简单介绍


const builds = {

  ...

  // Runtime+compiler development build (Browser)
  'web-full-dev': {
    entry: resolve('web/entry-runtime-with-compiler.js'),
    dest: resolve('dist/vue.js'),
    format: 'umd',
    env: 'development',
    alias: { he: './entity-decoder' },
    banner
  },

  ...

};

function genConfig(name) {
  const opts = builds[name]; // 映射目标配置
  const config = {
    input: opts.entry,
    external: opts.external,
    plugins: [...].concat(opts.plugins || []),
    output: {
      file: opts.dest,
      format: opts.format,
      banner: opts.banner,
      name: opts.moduleName || 'Vue'
    },
    sourceMap: true // 为了更清晰调试代码,建议你开启
  };

  ...

  return config;
}

if (process.env.TARGET) {
  module.exports = genConfig(process.env.TARGET);
}
...

  • genConfig - config中添加 sourceMap: true, 为了能够在断点调试时,把代码映射到单文件内部。

  • 根据 package.json "dev" 映射知道了 web-full-dev 再由配置文件找到入口文件:entry: resolve('web/entry-runtime-with-compiler.js')

    • "web" 别名配置 - alias.js 查看实际映射为 web: resolve('src/platforms/web')
    • 最终锁定了入口文件:src/platforms/web/entry-runtime-with-compiler.js

执行代码并调试

  • 安装依赖: npm i | yarn

  • 运行: npm run dev | yarn dev

    • 运行后会在 dist 目录下生成两个文件 vue.js vue.js.map
  • 引入生成 vue.js 代码, demo 如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>vue.js DEMO</title>
    <script src="dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <p>{{ message }}</p>
    </div>

    <script>
      new Vue({
        el: '#app',
        data: {
          message: 'hello vue.js'
        }
      });
    </script>
  </body>
</html>

承接下文 - 「试着读读 Vue 源代码」初始化前后做了哪些事情 ❓