读vue源码看前端百态1--模块化
栏目: JavaScript · 发布时间: 7年前
内容简介:以在我们执行根据
以 vue2.0 为例
在我们执行 npm run dev 时,会看到 package.json 中,有
"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev" 复制代码
根据 scripts/config.js 文件中的配置:
// 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
}
复制代码
这里注意到 format 参数的值为 umd ,
注意看这个文件,在 builds 对象中还有
// Runtime+compiler CommonJS build (CommonJS)
'web-full-cjs': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.common.js'),
format: 'cjs',
alias: { he: './entity-decoder' },
banner
},
// Runtime+compiler CommonJS build (ES Modules)
'web-full-esm': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.esm.js'),
format: 'es',
alias: { he: './entity-decoder' },
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
},
复制代码
我们看到三种模块: CommonJS 、 ES Modules 和 umd
什么是模块?
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
模块化
接下来,我们来学习下常用的模块:
CommonJS
常用的Node便是采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。
在 服务器端 ,模块的加载是运行时同步加载的;
在 浏览器端 ,模块需要提前编译打包处理。
我们一起来看一看CommonJS的例子:
// example.js
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
exports.addX = addX;
//index.js
const example = require('./example.js')
console.log(example.x); // 5
console.log(example.addX(1)); // 6
example.x = 6
console.log(example.addX(1)); // 6
执行node index.js
复制代码
CommonJS语法
暴露模块:module.exports = value 或exports.xxx = value
引入模块:require(xxx),如果是第三方模块,xxx为模块名,如require('express');如果是自定义模块,xxx为模块文件路径,如上例,require('./example.js')
CommonJS加载机制
引入的是暴露值的拷贝,所以要注意
// example.js
var x = {
name: 'kitty'
};
var outputX = function (value) {
return x;
};
module.exports= {
x,
outputX
}
// index.js
const example = require('./example.js')
console.log(example.x); // { name: 'kitty' }
console.log(example.outputX()); // { name: 'kitty' }
example.x.name = 'cat'
console.log(example.x); // { name: 'cat' }
console.log(example.outputX()); //{ name: 'cat' }
执行node index.js
复制代码
CommonJS在浏览器的实现
// example.js 如上
// example2.js
module.exports = function() {
console.log('example2')
}
// index.js
const example = require('./example.js')
const example2 = require('./example2.js')
example2();
console.log(example.x);
// index.html
<html>
<body>
<script src="./index.js"></script>
</body>
<html>
复制代码
直接启动 index.html , 打开控制台,会发现:
上面说了,模块需要提前编译打包处理。 这里我们用browerify打包一下
// 全局安装
npm install browserify -g
// 根目录下运行
browserify index.js -o bundle.js
// index.html替换script引用地址
<html>
<body>
<script src="./bundle.js"></script>
</body>
<html>
复制代码
可以看一看打包过后的bundle.js
直接启动 index.html , 打开控制台,会发现,哈哈,你成功了!!!
ES6模块
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
是不是感觉似懂非懂,没有关系,我们就是例子为王。
ES6模块语法
暴露模块:export命令用于规定模块的对外接口,比如 export xxx , xxx是一个对象;或者指定默认输出,用到export default命令,比如 export default xxx 。
引入模块:import命令用于引入其他模块提供的功能。比如 import xxx from ** ,其中xxx是要加载的变量名或函数名;指定默认输出时,xxx可以为匿名函数指定的任意名字。
ES6加载机制
CommonJS引入的是暴露值的拷贝,而ES6是对值的引用。
// example.js
export let x = 5;
export function addX () {
return x++;
};
//index.js
import { x, addX } from './example.js'
console.log(x); // 5
addX()
console.log(x); // 6
复制代码
执行 node index.js ,怎么回事?
SyntaxError: Unexpected token import 复制代码
这是因为node尚未支持ES6的module方式,所以我们需要babel-cli进行将ES6编译为ES5代码。
- 更换目录
example.js -> src/example.js index.js -> src/index.js 复制代码
2.全局安装 babel-cli
npm install babel-cli -g
3.定义 .babelrc 文件
{
"presets": ["es2015"]
}
复制代码
4.使用ES6编译为ES5代码:
babel src -d lib 复制代码
- 好了,你可以进入lib文件夹,运行
node index.js,就可以输出结果了。
ES6在浏览器的实现
// index.html
<html>
<body>
<script src="./lib/index.js"></script>
</body>
<html>
复制代码
有报错了,但是是不是看起来很熟悉呢?
是的!
模块需要提前编译打包处理。
你知道怎么做了?
答对了!
// 全局安装
npm install browserify -g
// 根目录下运行
browserify lib/index.js -o bundle.js
// index.html替换script引用地址
<html>
<body>
<script src="./bundle.js"></script>
</body>
<html>
复制代码
当然可以看看lib文件夹中的ES6转换ES5代码以及打包过后的bundle.js,这里就不说了。 直接启动index.html, 打开控制台,会发现,哈哈,你成功了!!!
UMD
UMD (Universal Module Definition), 希望提供一个前后端跨平台的解决方案(支持AMD与CommonJS模块方式)。
CommonJS加载模块是同步的,Node.js主要用于 服务器编程 ,模块文件一般已经存在于本地磁盘,所以加载起来比较快,所以CommonJS规范比较适用;
而AMD是非同步加载模块,允许指定回调函数,在 浏览器环境 下,要从服务器加载模块,这时就必须采用非同步模式,因此浏览器一般采用的是AMD规范。
AMD语法规范
暴露模块:
define([有依赖模块,无依赖可以省略],
function() {
return 模块
})
复制代码
引入模块:
require([依赖模块],callback) 复制代码
AMD加载机制
RequireJS是一个 工具 库,主要用于客户端的模块管理。它的模块管理遵守AMD规范,RequireJS的基本思想是,通过 define 方法,将代码定义为模块;通过 require 方法,实现代码的模块加载。
AMD在浏览器的实现
// example.js
define(function (){
var add = function (x,y){
return x+y;
}
return {
add
}
}
// index.js
(function () {
require.config({
paths: {
example: './example' // 不能写example.js会报错
}
})
require(['example'], function(example) {
console.log(example.add(2, 2))
})
})()
// require.js
复制这个
https://requirejs.org/docs/release/2.3.6/minified/require.js的代码
// index.html
<html>
<body>
<script data-main="./index.js" src="./require.js"></script>
</body>
<html>
复制代码
直接启动index.html, 打开控制台,会发现,哈哈,你成功了!!!
打开控制台network,看到分步加载
UMD的实现很简单:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ActionScript 3.0 Cookbook
Joey Lott、Darron Schall、Keith Peters / Adobe Dev Library / 2006-10-11 / GBP 28.50
Well before Ajax and Microsoft's Windows Presentation Foundation hit the scene, Macromedia offered the first method for building web pages with the responsiveness and functionality of desktop programs......一起来看看 《ActionScript 3.0 Cookbook》 这本书的介绍吧!