1 ES6模块化
使用export 或 export default暴露,使用import引入
ES6比较独特的一点就是,使用export暴露时,一个模块可以暴露多个对象
2 暴露模块
单次暴露
export default {
fn: () => console.log('module1 fn')
}
多次暴露
let fn = () => console.log('module2 fn')
let fn2 = ()=>console.log('module2 fn2')
export {
fn
}
export {
fn2
}
3 引入模块
import module1 from './module/module1.js'
import {fn,fn2} from './module/module2.js'
module1.fn()
fn()
fn2()
3 使用模块
入口文件 main.js
import module1 from './module1.js'
import {fn,fn2} from './module2.js'
import module3 from './module3.js'
module1.fn()
fn()
fn2()
module3.fn()
html
<script src="./main.js" type="module"></script>
4 引入第三方模块 import导入npm下载的包 babel与browserify打包代码
npm i jquery@1 --save
module3.js
import $ from 'jquery'
export default {
fn: () => $('body').css('background', 'lightblue')
}
juqery是npm下载的包,无法使用import直接导入
使用babel将import语法转为ES5,但此时代码在导入导出时遵循的时CommonJs规范,我们需要在浏览器运行,因此可以使用browserify再次转换成
4.1 具体流程:
-
安装babel-cli与browserify
npm install babel-cli -g
npm install browserify -g
npm install babel-preset-es2015 --save-dev -
定义.babelrc文件 preset预设将es6转为es5
.babelrc
{
"presets": ["es2015"]
}
- 使用babel转换成ES5语法,但此时还包含CommonJS规范的暴露与引入语法
babel module -d dist
- 使用browserify将babel中包含的CommonJS规范转成支持浏览器环境的代码,同时收集依赖,将代码进行打包,这样就可以在html文件中使用了
browserify dist/main.js -o dist/bundle.js
- html引入browserify打包之后的代码
<script src="./dist/bundle.js" type="module"></script>
5 模块化到底做了什么
阅读browserify翻译过后的代码,得到以下几点心得
5.1 模块的本质
模块其实就是一个自执行函数 IIFE,自执行函数的函数体用来执行模块代码,自执行函数的形参中的第一个对象用来收集模块
至于为什么要封装成一个IIFE? 因为浏览器并不支持模块化,因此用函数作用域去hack模块化效果
(function(){
/*
在这里执行模块代码
*/
})(
{
/*
在这里存储模块,收集模块依赖
*/
}
)
5.2 模块的存储与执行,模块的依赖收集
上面说到自执行函数的形参中的第一个对象用来收集模块
该对象以数字键的形式存储模块,键对应的值为一个数组
该数组中第一个元素以函数的形式存储模块代码,数组中第二个元素以对象的形式收集该模块的依赖
(function(){
/*
在这里执行模块代码
*/
})(
{
1: [
function (require, module, exports) {
"use strict";
/*
模块代码
...
*/
},
{
/*
这里是模块的依赖
以'模块路径':'模块对应的键'的形式存在
如:{"./module1": 2, "./module2": 3}
表示有一个模块1,在形参中对应的键是2
*/
}
]
}
)
6 browserify如何支持Commonjs规范中的require语法?
对于CommonJs来说,模块的暴露其实就是向外给出一份exports对象的拷贝
browseify要做的事情其实就是拿到导出的exports对象,再将其以形参的形式放进编译后的模块执行函数中供其使用
这样,模块通过拿到exports对象的形式实现了模块导入,也就实现了在浏览器端对服务器require语法的hack