这是xue源码学习记录,如有错误请指出,谢谢!相互学习相互进步。

vue源码目录为

vue
├── src        #vue源码
├── flow       #flow定义的数据类型库(vue通过flow来检测数据类型是否正确)
├── examples   #demo
├── scripts    #vue构建命令
├── ...    

vue内部代码模块比较清晰,这边主要分析scripts内部代码,讲解vue是如何进行构建的.
首先你必须要懂一些rollup,vue内部是通过rollup来进行构建的,rollup是一款js的构建工具,
将各个小模块打包成一个总的模块(只针对js文件,比较轻量,不会有css,img等压缩,比较适合开发插件,
如果是ui组件库的话,还是webpack构建会比较好。)
rollup说明文档:https://rollupjs.cn/

文件主要是scripts下的alias.js,config.js和build.js三个文件组成

alias

主要就是提供文件对应的路径

const path = require('path')const resolve = p => path.resolve(__dirname, '../', p)// 以下是设置别名,与对应的真实文件路径
module.exports = {vue: resolve('src/platforms/web/entry-runtime-with-compiler'),compiler: resolve('src/compiler'),core: resolve('src/core'),shared: resolve('src/shared'),web: resolve('src/platforms/web'),weex: resolve('src/platforms/weex'),server: resolve('src/server'),entries: resolve('src/entries'),sfc: resolve('src/sfc'),test: resolve('src/test') // 这个是测试目录是自己添加的
}

其中test是我自己加的,为了测试打包

config

config是为了提供打包的基础配置(即rollup打包配置文件格式),由于打包内容比较多,
所以做成可配置的

const path = require('path')
const buble = require('rollup-plugin-buble')
// 提供modules名称的 alias 和reslove 功能
const alias = require('rollup-plugin-alias')
// 将CommonJS模块转换为 ES2015供Rollup 处理
const cjs = require('rollup-plugin-commonjs')
// 变量替换,可以将动态设置的变量提取出来在配置文件中设置
const replace = require('rollup-plugin-replace')
// 帮助 Rollup 查找外部模块,然后安装
const node = require('rollup-plugin-node-resolve')
const flow = require('rollup-plugin-flow-no-whitespace')
const version = process.env.VERSION || require('../package.json').version
// 下面是weex服务器端代码,不需要管
// const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version// 这边是打包完成后模块外部首行注释代码
const banner = `/** test-vue.js v${version}* (C) 2014-${new Date().getFullYear()} Enan You* @author zhengjie*/`
// 获取文件夹路径别名
const aliases = require('./alias')
// 寻找路径
const resolve = p => {const base = p.split('/')[0]if (aliases[base]) {return path.resolve(aliases[base], p.slice(base.length + 1))} else {return path.resolve(__dirname, '../', p)}
}
// 设置打包参数
// 这边把原先vue打包文件去除,替换成知己的一个测试文件
const builds = {'test-cjs': {entry: resolve('test/main.js'),dest: resolve('dist/test-cjs.js'),format: 'cjs', // csj格式 module.exportsbanner},'test-es': {entry: resolve('test/main.js'),dest: resolve('dist/test-es.js'),format: 'es', // es格式 export defaultbanner},'test-umd': {entry: resolve('test/main.js'),dest: resolve('dist/test-umd.js'),format: 'umd', // 浏览器格式 returnbanner}
}// 根据上面builds打包转换成rollup打包格式
function getConfig(name) {const opts = builds[name]const config = {input: opts.entry,external: opts.external,plugins: [replace({__WEEX__: !!opts.weex,__WEEX_VERSION__: null,__VERSION__: version}),flow(),buble(),alias(Object.assign({}, aliases, opts.alias))].concat(opts.plugins || []),output: {file: opts.dest,format: opts.format,banner: opts.banner,name: opts.moduleName || 'Vue'}}// 如果是开发模式if (opts.env) {config.plugins.push(replace({'process.env.NODE_ENV': JSON.stringify(opts.env)}))}// 增加属性Object.defineProperty(config, '_name', {enumerable: false,value: name})return config
}if (process.env.TARGET) {module.exports = getConfig(process.env.TARGET)
} else {exports.getBuild = getConfigexports.getAllBuilds = () => Object.keys(builds).map(getConfig)
}

其中里面的builds已被替换成我自己的测试文件,用于测试打败es,模块化和浏览器的不同格式。

build

build文件就是根据配置文件进行打包,打包模式分为全部打包,或者是可配置打包,
如果运行npm run build,将会打包所有的配置,
而运行npm run build '参数', 则根据参数配置进行打包

const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const rollup = require('rollup')
const uglify = require('uglify-js')
// 检测是否有dist文件
if (!fs.existsSync('dist')) {fs.mkdirSync('dist')
}let builds = require('./config').getAllBuilds()// build后面输入的参数
if (process.argv[2]) {// 过滤出需要打包的数组const filters = process.argv[2].split(',')builds = builds.filter(b => {return filters.some(f => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1)})
} else {// 这边过滤出weex,不需要管builds = builds.filter(b => {return b.output.file.indexOf('weex') === -1})
}
// 把需要打包的打包出来
build(builds)
// 打包函数
function build(builds) {let built = 0const total = builds.lengthconst next = () => {buildEntry(builds[built]).then(() => {built++if (built < total) {next()}}).catch(logError)}next()
}
// 单个配置文件打包
function buildEntry(config) {const output = config.outputconst {file, banner} = output// 是否为压缩文件const isProd = /min\.js$/.test(file)return rollup.rollup(config).then(bundle => bundle.generate(output)).then(({code}) => {// 压缩我文件if (isProd) {var minified = (banner ? banner + '\n' : '') + uglify.minify(code, {output: {ascii_only: true},compress: {pure_funcs: ['makeMap']}}).codereturn write(file, minified, true)} else {return write(file, code)}})
}function write(dest, code, zip) {return new Promise((resolve, reject) => {function report (extra) {console.log(blue(path.relative(process.cwd(), dest)) + ' ' + getSize(code) + (extra || ''))resolve()}fs.writeFile(dest, code, err => {if (err) return reject(err)if (zip) {zlib.gzip(code, (err, zipped) => {if (err) return reject(err)report(' (gzipped: ' + getSize(zipped) + ')')})} else {report()}})})
}
// 计算文件大小
function getSize (code) {return (code.length / 1024).toFixed(2) + 'kb'
}
// 输入错误信息
function logError (e) {console.log(e)
}
function blue (str) {return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
}

测试文件

main.js

import foo from './foo';
export default function () {console.log(foo)
}

foo.js

export default "hello rollup"

通过npm run build打包测试,会在dist文件打包出test-cjs.js,test-es.js,test-umd.js
文件内容如下:
test-cjs.js

/** test-vue.js v1.0.0* (C) 2014-2018 Enan You* @author zhengjie*/'use strict';var foo = "hello rollup"function main () {console.log(foo);
}module.exports = main;

test-es.js

/** test-vue.js v1.0.0* (C) 2014-2018 Enan You* @author zhengjie*/var foo = "hello rollup"function main () {console.log(foo);
}export default main;

test-umd.js

/** test-vue.js v1.0.0* (C) 2014-2018 Enan You* @author zhengjie*/(function (global, factory) {typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :typeof define === 'function' && define.amd ? define(factory) :(global.Vue = factory());
}(this, (function () { 'use strict';var foo = "hello rollup"function main () {console.log(foo);
}return main;})));

这个构建的过程不难,比起webpack的配置文件要容易懂很多
懂得了vue的构建,接下来就可以开始vue源码的学习了

vue源码构建代码分析相关推荐

  1. iris流程图_GitHub - LeoIris/vue: vue源码逐行注释分析+40多m的vue源码程序流程图思维导图 (diff部分待后续更新)...

    vue源码业余时间差不多看了一年,以前在网上找帖子,发现很多帖子很零散,都是一部分一部分说,断章的很多,所以自己下定决定一行行看,经过自己坚持与努力,现在基本看完了 .这个vue源码逐行分析,我基本每 ...

  2. Vue 合同模板_vue源码逐行注释分析+40多m的vue源码程序流程图思维导图

    vue源码业余时间差不多看了一年,以前在网上找帖子,发现很多帖子很零散,都是一部分一部分说,断章的很多,所以自己下定决定一行行看,经过自己坚持与努力,现在基本看完了,差ddf那部分,因为考虑到自己要换 ...

  3. 深入剖析Vue源码 - 响应式系统构建(上)

    从这一小节开始,正式进入Vue源码的核心,也是难点之一,响应式系统的构建.这一节将作为分析响应式构建过程源码的入门,主要分为两大块,第一块是针对响应式数据props,methods,data,comp ...

  4. 深入Vue - 源码目录及构建过程分析

    摘要: Vue源码阅读第一步. 原文:深入vue - 源码目录及构建过程分析 公众号:前端小苑 Fundebug经授权转载,版权归原作者所有. 本文主要梳理一下vue代码的目录,以及vue代码构建流程 ...

  5. vue源码分析系列一:new Vue的初始化过程

    import Vue from 'vue'(作者用的vue-cli一键生成) node环境下import Vue from 'vue'的作用是什么意思? 在 NPM 包的 dist/ 目录你将会找到很 ...

  6. vue源码分析系列二:$mount()和new Watcher()的执行过程

    续vue源码分析系列一:new Vue的初始化过程 在initMixin()里面调用了$mount() if (vm.$options.el) {vm.$mount(vm.$options.el);/ ...

  7. vue源码解析(3)—— Vue.js 源码构建

    Vue.js 源码构建 Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下. 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.json ...

  8. 大前端-Vue源码分析

    Vue源码解析-响应式原理 以下内容来自 拉勾教育大前端训练营 笔者在学习过程中对笔记进行的一个整理 心得体会 嘿嘿嘿~~~ 首先说说拉勾教育大前端训练营的课程视频吧,课程的质量是真的很好哦,并且已经 ...

  9. [Vue源码分析]谷歌翻译后,Vue双向数据绑定失效了?

    前言: 最近运营反馈了一个问题:谷歌浏览器打开第三方储值平台,使用谷歌浏览器自带的翻译功能后,选择商品没有计算总额. 首先可以肯定的是这不是bug,这个平台已经兼容了13种语言,只是运营没有通过语言栏 ...

最新文章

  1. 抖音开放平台 php-sdk 注意事项
  2. CentOS7和CentOS6怎样开启MySQL远程访问
  3. Linux 系统 vsftpd时区问题的解决
  4. linux下redis权限,Linux(Centos)下Redis开机自启设置
  5. php微信支付接口开发程序(概念篇)
  6. java-什么是实例初始化块?
  7. 下列php语法描述错误的是,下列关于对象替换语法规则的描述中,错误的是( )。...
  8. android 播放音乐卡顿,Android MediaPlayer+SeekBar播放音频出现卡顿边长可能问题
  9. 大家都来测试测试自己的flex水平
  10. maven怎么引入自定义(本地/第三方)jar图文教程
  11. 韩顺平 java笔记 第3讲 运算符 流程控制
  12. crossentropy java_示例CrossEntropyLoss用于pytorch中的3D语义分段
  13. 达人评测 华为watch gt2和gt选哪个好
  14. not authorized on test to execute command { $eval: \return 1111\
  15. word两种html区别,word文本框有哪两种方式?
  16. js 十六进制,八进制,二进制
  17. 中国移动下月发布5G套餐:“三不一快”策略方便终端入网
  18. 给未来的电子工程师nbsp;---电子牛人给…
  19. 计算机资源管理器经常停止运行,解决win10资源管理器经常停止工作的方法
  20. 千里姻缘:晒晒你拥有什么样的“恋人指数”

热门文章

  1. 使用maven下载依赖包及maven常见问题汇总
  2. .NET设计模式(4):建造者模式(Builder Pattern)(转)
  3. 收集的一些操作系统面试题
  4. Silverlight中多个Xaml之间的切换/调用/弹出/传参数(转)
  5. poladuo network 轻松解决Windows系统棘手问题
  6. 【按住你的心】——Android开发CheckBoxRadioButton控件的简单使用
  7. 详解:XenServer丢失存储库SR解决方法
  8. 32.2. ntpdate
  9. 张思华:希望通过创新加深NetApp与中国的联系
  10. 2016年3月23日作业(项目进度管理、项目成本管理)