重读Vue源码系列二 —— 如何调试Vue源码

1,822 阅读3分钟

无论我们学习任何语言和技术,首先必须要学会调试代码,它可以帮助我们更加直观的了解代码的运行方式、环境变量、报错信息、运行时状态等,这些可以辅助我们更好更快的学习,因此我们在深入学习源码之前先学习vue源码的调试方法~

一、vue例子todomvc中的../../dist/vue.js

image.png

(1)、位置

image.png

(2)、它是啥?

就是构建出来的未压缩源码的vue.js源码,我们可以通过如下方式引入使用

<script src="../../dist/vue.js"></script>

其实Vue文档引用的vue.js就是我们构建生成的../../dist/vue.js,其实他们是同一个东西

<!-- 开发环境版本,包含了有帮助的命令行警告 --> 
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

二、上面的vue.js是怎么构建生成的呢?

(1)从npm run dev开始

先看下package.jsonscripts

"scripts": {
    "dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev"
 }

Rollup是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序,非常适合做类库的构建打包,如果感兴趣可以学习一下。

  • 构建的入口 是scripts/config.js

  • 构建的environmentTARGET:web-full-dev,这个环境变量决定了构建文件的入口以及生成的dist目录文件

    看下scripts/config.js文件的部分代码, 其中process.env.TARGET的值就是环境变量的值'web-full-dev'

    1. 首先会执行如下代码
    //scripts/config.js 
    if (process.env.TARGET) {
      module.exports = genConfig(process.env.TARGET)
    } else {
      exports.getBuild = genConfig
      exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
    }
    
    

    上面的代码实际会运行genConfig(process.env.TARGET),也就是genConfig('web-full-dev')

    1. 接着看下****genConfig('web-full-dev'),这部分代码是生成rollup构建需要的配置文件,其中的关键代码是const opts = builds[name]
    // scripts/config.js
    function genConfig (name) {
      const opts = builds[name] //执行builds['web-full-dev']
      const config = {
        input: opts.entry,
        external: opts.external,
        plugins: [
          flow(),
          alias(Object.assign({}, aliases, opts.alias))
        ].concat(opts.plugins || []),
        output: {
          file: opts.dest,
          format: opts.format,
          banner: opts.banner,
          name: opts.moduleName || 'Vue'
        },
        onwarn: (msg, warn) => {
          if (!/Circular/.test(msg)) {
            warn(msg)
          }
        }
      }
      //其他代码省略了......
      return config
    }
    
    1. builds就是个对象 第二步其实就是在运行 builds['web-full-dev'],builds对象的源码如下~
        // scripts/config.js
        const builds = {
          // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
          'web-runtime-cjs-dev': {
                entry: resolve('web/entry-runtime.js'),
                dest: resolve('dist/vue.runtime.common.dev.js'),
                format: 'cjs',
                env: 'development',
                banner
          },
          
            // 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
          },
          其它的都省略了.......
        }
    

    builds['web-full-dev']返回的结果是下面的对象,只不过路径会被resolve处理成文件的真实路径; Rollup构建之后输出的路径是返回结果的dest: resolve('dist/vue.js'),也就是我们源码中的dist目录中的vue.js

    这样Rollup构建的入口和输出文件就确定了,接着就可以执行构建逻辑了~

    {
        entry: resolve('web/entry-runtime-with-compiler.js'),
        dest: resolve('dist/vue.js'),
        format: 'umd',
        env: 'development',
        alias: { he: './entity-decoder' },
        banner
    }
    
    1. 最后通过Rollup的构建流程,就生成了我们看到的dist目录下的vue.js文件。

    三、那如何调试呢?


    • 1、执行npm run dev

      Rollup会一直监控源码的改变,只要源码src目录下的文件被更改了,就会触发重新编译

image.png

  • 2、断点调式 这样我们就可以在源码中加断点和console调试源码了~

image.png

四、参考资料

Vue.js 技术揭秘