当前位置: 首页 > 后端技术 > Node.js

vue源码构建代码分析

时间:2023-04-03 21:00:03 Node.js

此为xue源码学习记录,如有错误请指出,谢谢!互相学习,互相提高。vue源码目录为vue├──src#vue源码├──flow#flow定义数据类型库(vue使用flow检测数据类型是否正确)├──examples#demo├──scripts#vue构建命令├──...vue的内部代码模块比较清晰。这里主要分析脚本的内部代码,讲解vue是如何构建的。首先,你必须了解一些rollup。Vue是通过rollup在内部构建的。rollup是一个js构建工具,将每个小模块打包成一个总模块(只针对js文件,比较轻量,没有css,img等压缩,比较适合开发插件,如果是ui组件库,或者webpack施工会更好。)rollup文档:https://rollupjs.cn/该文件主要由scripts下的alias.js、config.js和build.js组成。别名主要是提供文件对应的路径。constpath=require('path')constresolve=p=>path.resolve(__dirname,'../',p)//下面是设置别名,对应真实文件路径module.exports={vue:解析('src/platforms/web/entry-runtime-with-compiler'),编译器:解析('src/编译器'),核心:解析('src/core'),共享:解析('src/shared'),web:resolve('src/platforms/web'),weex:resolve('src/platforms/weex'),server:resolve('src/server'),条目:resolve('src/entries'),sfc:resolve('src/sfc'),test:resolve('src/test')//这个是自己添加的test目录}其中test是自己添加的,用于测试打包configconfig是提供打包的基本配置(即rollup打包配置文件格式),因为打包内容较多,做成可配置的constpath=require('path')constbuble=require('rollup-plugin-buble')//提供模块名的别名和reslove函数constalias=require('rollup-plugin-alias')//将CommonJS模块转成ES2015进行Rollup处理constcjs=require('rollup-plugin-commonjs')//变量替换,可以提取动态设置的变量,在配置文件中设置constreplace=require('rollup-plugin-replace')//帮助Rollup找到外部模块并安装它们constnode=require('rollup-plugin-node-resolve')constflow=require('rollup-plugin-flow-no-whitespace')constversion=process.env.VERSION||require('../package.json').version//下面是weex服务端代码,不用管//constweexVersion=process.env.WEEX_VERSION||require('../packages/weex-vue-framework/package.json').version//这是打包完成后模块外的第一行注释代码。constbanner=`/**test-vue.jsv${version}*(C)2014-${newDate().getFullYear()}尤恩安*@authorzhengjie*/`//获取文件夹路径别名constaliases=require('./alias')//查找路径constresolve=p=>{constbase=p.split('/')[0]if(aliases[base]){returnpath.resolve(aliases[base],p.slice(base.length+1))}else{returnpath.resolve(__dirname,'../',p)}}//设置打包参数//这里去掉原vue打包文件和用测试文件替换它constbuilds={'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格式导出默认横幅},'test-umd':{entry:resolve('test/main.js'),dest:resolve('dist/test-umd.js'),format:'umd',//浏览器格式返回横幅}}//按照上面的builds包转换成rollup包格式functiongetConfig(name){constopts=builds[name]constconfig={input:opts.entry,external:opts.external,plugins:[replace({__WEEX__:!!opts.weex,__WEEX_VERSION__:null,__VERSION__:version}),flow(),buble(),别名(Object.assign({},aliases,opts.alias))].concat(opts.plugins||[]),输出:{文件:opts.dest,格式:opts.format,横幅:opts.banner,名称:opts.moduleName||'Vue'}}//如果是开发模式if(opts.env){config.plugins.push(replace({'process.env.NODE_ENV':JSON.stringify(opts.env)}))}//添加属性Object.defineProperty(config,'_na我',{enumerable:false,value:name})returnconfig}if(process.env.TARGET){module.exports=getConfig(process.env.TARGET)}else{exports.getBuild=getConfigexports.getAllBuilds=()=>Object.keys(builds).map(getConfig)}里面的builds已经换成了我自己的测试文件,用于测试不同格式打败es,模块化和浏览器build构建文件根据配置文件进行打包。打包方式分为全包或可配置包。npmrunbuild会打包所有配置,npmrunbuild'parameter'会根据参数配置打包。constfs=require('fs')constpath=require('path')constzlib=require('zlib')constrollup=require('rollup')constuglify=require('uglify-js')//检测是否有dist文件process.argv[2]){//过滤掉需要打包的数组constfilters=process.argv[2].split(',')builds=builds.filter(b=>{returnfilters.some(f=>b.output.file.indexOf(f)>-1||b._name.indexOf(f)>-1)})}else{//在这里过滤掉weex,不需要管理builds=builds.filter(b=>{returnb.output.file.indexOf('weex')===-1})}//打包需要打包的东西build(builds)//打包函数functionbuild(builds){let建造=0const总计=建造。lengthconstnext=()=>{buildEntry(builds[built]).然后(()=>{built++if(builtbundle.generate(output)).then(({code})=>{//压缩我的文件if(isProd){varminified=(banner?banner+'\n':'')+uglify.minify(code,{output:{ascii_only:true},compress:{pure_funcs:['makeMap']}}).codereturnwrite(file,minified,true)}else{returnwrite(file,code)}})}functionwrite(dest,code,zip){returnnewPromise((resolve,reject)=>{functionreport(extra){console.log(blue(path.relative(process.cwd(),dest))+''+getSize(code)+(extra||''))resolve()}fs.writeFile(dest,code,err=>{if(err)返回拒绝(错误)如果(zip){zlib.gzip(代码,(err,zipped)=>{if(err)returnreject(err)report('(gzipped:'+getSize(zipped)+')')})}else{report()}})})}//计算文件大小functiongetSize(code){return(code.length/1024).toFixed(2)+'kb'}//输入错误信息functionlogError(e){console.log(e)}functionblue(str){return'\x1b[1m\x1b[34m'+str+'\x1b[39m\x1b[22m'}测试文件main.jsimportfoofrom'./foo';exportdefaultfunction(){console.log(foo)}foo.jsexportdefault"hellorollup"通过npmrunbuild打包测试,test-cjs.js、test-es.js、test-umd.js将打包到dist文件中如下:test-cjs.js/**test-vue.jsv1.0.0*(C)2014-2018EnanYou*@authorzhengjie*/'usestrict';varfoo="hellorollup"functionmain(){console.log(foo);}module.exports=main;test-es.js/**test-vue.jsv1.0.0*(C)2014-2018EnanYou*@authorzhengjie*/varfoo="hellorollup"functionmain(){console.log(foo);}exportdefaultmain;test-umd.js/**test-vue.jsv1.0.0*(C)2014-2018尤恩安*@authorzhengjie*/(function(global,factory){typeofexports==='object'&&typeofmodule!=='undefined'?module.exports=factory():typeofdefine==='function'&&define.amd?define(factory):(global.Vue=factory());}(this,(function(){'usestrict';varfoo="hellorollup"函数main(){console.log(foo);}returnmain;})));这个构建过程并不难,比webpack的配置文件要容易理解多了。了解了vue的构建之后,就可以开始学习vue源码了