js模块化 ES6 引入第三方模块 模块化到底做了什么

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 具体流程:

  1. 安装babel-cli与browserify
    npm install babel-cli -g
    npm install browserify -g
    npm install babel-preset-es2015 --save-dev

  2. 定义.babelrc文件 preset预设将es6转为es5
    .babelrc

{
 "presets": ["es2015"]
}
  1. 使用babel转换成ES5语法,但此时还包含CommonJS规范的暴露与引入语法
babel module -d dist
  1. 使用browserify将babel中包含的CommonJS规范转成支持浏览器环境的代码,同时收集依赖,将代码进行打包,这样就可以在html文件中使用了
browserify dist/main.js -o dist/bundle.js
  1. 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

posted @ 2022-03-24 20:44  IslandZzzz  阅读(525)  评论(0编辑  收藏  举报