This is an Xue source code learning record. If there is any error, please point it out. Thank you! Mutual learning and mutual progress.
The vue source code directory is
Vue ── SRC # vue source code ── flow # the Data Type Library defined by flow (vue uses Flow to check whether the data type is correct) ── examples # demo ── scripts # vue build command ──...
The vue internal code module is clear. This section mainly analyzes the internal code of scripts and explains how to build vue.
First, you must understand rollup. vue is built through rollup internally. rollup is a JS build tool,
Package each small module into a general module (only for JS files, relatively lightweight, no compression of CSS, IMG, etc., which is more suitable for development of plug-ins,
If it is a UI component library, it is better to build webpack .)
Rollup documentation: https://rollupjs.cn/
The file consists of alias. JS, config. JS, and build. js files in scripts.
Alias
It mainly provides the corresponding file path
Const Path = require ('path') const resolve = P = & gt; Path. resolve (_ dirname ,'.. /', p) // set the alias and the corresponding real file path 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') // This is the test directory added by yourself}
Test is added by myself.
Config
Config is to provide the basic packaging configuration (that is, the rollup packaging configuration file format), because the packaging content is large,
So it is configurable.
Const Path = require ('path') const buble = require ('rollup-plugin-buble ') // provide the alias and reslove functions of the modules name. Const alias = require ('rollup-plugin-alias ') // convert the commonjs module to es2015 for rollup to process const CJS = require ('rollup-plugin-commonjs') // Replace the variable, you can extract the dynamically set variables and set const replace = require ('rollup-plugin-replace ') in the configuration file. // help rollup find external modules, then install const node = require ('rollup-plugin-node-resolve') const flow = require ('Rollup-plugin-flow-no-whitespace') const version = process. env. version | require ('.. /package. JSON '). version // The following is the weex server code, which does not need to be managed // const weexversion = process. env. weex_version | require ('.. /packages/weex-Vue-framework/package. JSON '). version // here is the comments code const banner = '/** test-vue.js v $ {version} * (c) 2014-$ {new date () after the module is packaged (). getfullyear ()} Enan you * @ author zhengjie */'// get the folder path alias const al Iases = require ('. /alias ') // find the path const resolve = P = & gt; {const base = P. split ('/') [0] If (aliases [base]) {return path. resolve (aliases [base], p. slice (base. length + 1)} else {return path. resolve (_ dirname ,'.. /', p)} // set the packaging parameters // remove the original vue package file and replace it with a test file const builds = {'test-cjs ': {entry: Resolve ('test/main. JS '), DEST: Resolve ('dist/test-cjs.js'), format: 'cjs', // CSJ format module. exports B Anner}, 'test-es ': {entry: Resolve ('test/main. JS '), DEST: Resolve ('dist/test-es.js'), format: 'els', // es format export default banner}, 'test-umd': {entry: resolve ('test/main. JS '), DEST: Resolve ('dist/test-umd.js'), format: 'umd ', // return banner in the browser format} // convert it to The rollup packaging format function getconfig (name) {const opts = builds [name] const Config = {input: opts. entry, external: opts. external, pl Ugins: [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 the development mode is if (OPTs. ENV) {config. plugins. push (replace ({'process. env. node_env ': JSON. stringify (OPTs. ENV)} // Add attribute object. defineproperty (config, '_ name', {enumerable: false, value: name}) return config} If (process. env. target) {module. exports = getconfig (process. env. target)} else {exports. getbuild = getconfig exports. getallbuilds = () = & gt; object. keys (builds ). map (getconfig )}
The builds in it has been replaced with my own test file, which is used to test and defeat es. modularization is different from the browser format.
Build
The Build File is packaged according to the configuration file. The packaging mode is divided into full packaging or configurable packaging,
If you run NPM run build, all configurations will be packaged,
Run the NPM run build 'parameter' and package it according to the parameter configuration.
Const FS = require ('fs') const Path = require ('path') const zlib = require ('zlib') const rollup = require ('rollup ') const uglify = require ('uglify-js') // checks whether the DIST file exists if (! FS. existssync ('dist') {FS. mkdirsync ('dist')} Let builds = require ('. /config '). getallbuilds () // The input parameter if (process. argv [2]) {// filter out the array const filters = process to be packaged. argv [2]. split (',') builds = builds. filter (B = & gt; {return filters. some (F = & gt; B. output. file. indexof (f) & gt;-1 | B. _ name. indexof (f) & gt;-1)} else {// here weex is filtered out, and builds = builds is not required. filter (B = & gt; {return B. output. file. index Of ('weex ') ===- 1})} // package the desired build (builds) // package the function build (builds) {Let built = 0 const Total = builds. length const next = () = & gt; {buildentry (builds [built]). then () = & gt; {built ++ if (built & lt; Total) {next ()}}). catch (logerror)} next ()} // Package function buildentry (config) {const output = config in a single configuration file. output const {file, banner} = output // whether it is a compressed file const isprod =/min \. JS $ /. test (Fi Le) return rollup. rollup (config ). then (bundle = & gt; bundle. generate (output )). then ({code}) = & gt; {// compress my file if (isprod) {var minified = (banner? Banner + '\ N': '') + uglify. minify (Code, {output: {ascii_only: true}, compress: {pure_funcs: ['makemap']}). code return write (file, minified, true)} else {return write (file, code)} function write (DEST, code, zip) {return new promise (resolve, reject) = & gt; {function report (extra) {console. log (blue (path. relative (process. CWD (), DEST) + ''+ getsize (CODE) + (extra |'') Resolve ()} FS. writefile (DEST, code, err = & gt; {If (ERR) return reject (ERR) if (ZIP) {zlib.gzip (Code, (ERR, zipped) = & gt; {If (ERR) return reject (ERR) Report ('(gzipped:' + getsize (zipped) + ')')})} else {report () }})} // calculate the file size function getsize (CODE) {return (code. length/1024 ). tofixed (2) + 'kb'} // enter the error message function logerror (e) {console. log (e)} function blue (STR) {return '\ x1b [1 m \ x1b [34m' + STR +' \ x1b [39m \ x1b [22m '}
Test File
Main. js
import foo from './foo';export default function () { console.log(foo)}
Foo. js
export default "hello rollup"
The NPM run build packaging test will package the test-cjs.js, test-es.js, test-umd.js in the Dist File
The file content is as follows:
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;})));
This building process is not difficult. It is much easier to understand than the webpack configuration file.
After understanding how to build Vue, you can start learning vue source code.
Original article address:
Vue source code build code analysis