读vue源码看前端百态1--模块化
栏目: JavaScript · 发布时间: 5年前
内容简介:以在我们执行根据
以 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的实现很简单:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
具体数学(英文版第2版)
[美] Ronald L. Graham、Donald E. Knuth、Oren Patashnik / 机械工业出版社 / 2002-8 / 49.00元
This book introduces the mathematics that supports advanced computer Programming and the analysis of algorithms. The primary aim of its well-known authors is to provide a solid and relevant base of ma......一起来看看 《具体数学(英文版第2版)》 这本书的介绍吧!