In front of the writing
Since the abandonment of jQ framework, has been using VUE, write a large and small project, of course, also wrote a lot of bugs, the source will occasionally in-depth, but there has been no systematic summary and collation. So I am going to make a small record of source code in gold, also as a note, on the project has been VUE2 +, so from the most familiar source 2.+ start to speak, the knife is not mistakenly cut wood, we start from flow, of course, there will be a small partner said 3.0, there is a need to see 2.+ source? Well, that’s a matter of opinion
flow
Flow is facebook’s JavaScript static type checking tool. The vue.js2.0 source code makes use of Flow for static type checking, so knowing Flow helps us to read the source code. Of course, in 2021, we’ll be asking why we use flow instead of TS. Here’s your big answer:
The bottom line is ecology, cost, in short,Being is reasonableTo highlight,
How Flow works
Generally, type checking can be done in two ways:
1. Type inference: Infer the type of a variable from the context in which it is used, and then check the type against these inferences.
2. Type comments: Make comments in advance about the types we expect. Flow will make decisions based on these comments. Type determination It does not require any code changes to perform type checking, minimizing developer effort. It doesn’t force you to change your development habits because it automatically inferences the type of the variable. This is known as type inference and is one of the most important features of Flow.
Here’s a simple example:
/*@flow*/
function split(str) {
return str.split(' ')
}
split(11)
Copy the code
Flow checks the above code with an error because the split function expects a string as an argument, and we entered a number. Type annotations As mentioned above, type inference is one of the most useful features of Flow, and you don’t need to write type annotations to get useful feedback. However, in some specific scenarios, adding type annotations can provide a better and more explicit basis for checking. Consider this code:
/*@flow*/
function add(x, y){
return x + y
}
add('Hello', 11)
Copy the code
Flow can’t detect any errors when it looks at this code because syntactically, + can be used for strings as well as numbers, and we didn’t specify that add() must be a number. In this case, we can use type annotations to indicate the desired type. Type annotations start with a colon: and can be used in function arguments, return values, and variable declarations. If we add a type comment to the previous section of code, it will look like this:
/*@flow*/
function add(x: number, y: number): number {
return x + y
}
add('Hello', 11)
Copy the code
Now Flow can check for errors because the expected type of the function argument is a number, and we supplied a string. An array of
/*@flow*/
var arr: Array<number> = [1, 2, 3]
arr.push('Hello')
Copy the code
The format of an Array type annotation is Array, with T representing the data type of each item in the Array. In the above code, arR is an array where each item is a number. If we add a string to the array, Flow will check for errors. For more information, please refer to the official documents
Introduction to the entire Vue directory structure
For an intuitive view of directories, use the tree command to view the folders in the SRC directory. Get a general idea of the structure of the source code,
├─ CodeGen │ ├─ Directives │ ├─ Parser │ ├─ Component # VUE keep-alive │ ├─ Component # VUE keep-alive │ ├─ CodeGen │ ├─ Directives │ ├─ Component # VUE keep-alive │ ├─ Component # VUE ├─ bass exercises │ ├─ Bass Exercises │ ├─ Bass Exercises │ ├─ Bass Exercises │ ├─ Bass Exercises │ ├─ Bass Exercises │ ├─ Bass Exercises │ ├─ Bass Exercises ├ ─ platforms # platform code │ ├ ─ web # web logic - vue │ │ ├ ─ compiler │ │ ├ ─ the runtime │ │ ├ ─ server │ │ └ ─ util │ └ ─ weex # weex logic - │ app ├─ Compiler │ ├─ Runtime │ ├─ util │ ├─ SFC │ ├─ utilCopy the code
complier
This contains all the compiled code of Vue. The component template tempalte, which we usually write the most, is parses into ast syntax tree. Of course, there are AST syntax tree optimization, code generation and other functions. Compilation can be done at build time (with auxiliary plug-ins such as WebPack and Vue-Loader); You can also do this at run time, using vue.js, which includes build functionality. Obviously, compilation is performance intensive, so it’s better to compile offline.
core
The core directory contains the core code for vue.js, including built-in components, global API encapsulation, Vue instantiation, observers, virtual DOM, utility functions, and more. This code is the soul of vue.js, and it’s where we’ll focus our analysis.
platforms
Vue.js is a cross-platform MVVM framework, it can run on the Web, also can cooperate weeX run on the NatVIE client. The two directories represent the two main entries, packaged as vue.js running on the Web and weex.
server
Vue.js 2.0 supports server-side rendering. All server-side rendering related logic is in this directory. Note: This part of the code is running on the server side of node.js, not to be confused with the browser side of vue.js. The main work of server-side rendering is to render the components as HTML strings on the server side, send them directly to the browser, and finally “mix” the static markup into a fully interactive application on the client side.
sfc
Usually we develop vue.js with webPack builds and then write components in a.vue single file.
shared
Vue.js defines some tool methods, which are shared by vue.js on the browser side and vue.js on the server side. The code logic in this directory will parse the.vue file contents into a JavaScript object.
Packaging process
Find entry file
First, we can find the build script command in the package.json file, and then find the corresponding entry from the command scripts/build.js
{
"script": {
"build": "node scripts/build.js",
"build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
"build:weex": "npm run build --weex"
}
}
Copy the code
Find the file
let builds = require('./config').getAllBuilds()
// filter builds via command line arg
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 {
// filter out weex builds by default
builds = builds.filter(b => {
return b.output.file.indexOf('weex') === -1
})
}
build(builds)
Copy the code
Take the config file from the config file, then take the parameters from the command, filter them to the parameters we want, and finally build vue.js for different purposes
Output dist according to configuration
You can look at the dist directory
The config. Js file
Let’s go back to the configuration file we just read: require(‘./config’).getallbuilds ()
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
},
'web-runtime-cjs-prod': {
entry: resolve('web/entry-runtime.js'),
dest: resolve('dist/vue.runtime.common.prod.js'),
format: 'cjs',
env: 'production',
banner
}
....
Copy the code
Just so you know, this is actually a rollup rule. The entry attribute indicates the address of the JS file to be built, and the dest attribute indicates the address of the JS file to be built. The format attribute indicates the format of the build. CJS indicates that the built file complies with the CommonJS specification. Es indicates that the built file complies with the ES Module specification. Umd means that the built file complies with the UMD specification.
In fact, follow the trail, carefully you will find that the config file building entry is the Web and Wexx js below the Platforms folder, here for example
src/platforms/web/entry-runtime.js
src/platforms/web/entry-runtime-with-compiler.js
Copy the code
We can find the entry we need through the packaged configuration. The two differences are whether to include compiler logic. In development, we usually use entry Runtime, which can reduce the vUE size. The.vue file is compiled using a Vue-loader, which is not related to the term compiler.
new Vue({
template:`<div></div>`
})
Copy the code
If you want to parse a template like this, you need to use the compiler entry