前端模块化

文献 www.manongjc.com/detail/51-l...

js加载机制(假设总是本地脚本index.js下载更快)

  • index.js
js 复制代码
try {
    console.log(_.VERSION);
} catch (error) {
    console.log('Lodash Not Available');
}
console.log(document.body ? 'YES' : 'NO');
示例1
  • index.html
js 复制代码
<head>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
  <script src="./index.js"></script>
</head>

<body>
</body>
  • 控台结果
js 复制代码
4.17.10
NO
  • 结果说明:浏览器加载脚本是采用同步模型的,都会阻塞浏览器的解析器,位于该 script 标签以上的 DOM 元素是可用的,位于其以下的 DOM 元素不可用
示例2 script上加上async属性
  • index.html
js 复制代码
<head>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js" async></script>
  <script src="./index.js" async></script>
</head>

<body>
</body>
  • 控台结果
js 复制代码
Lodash Not Available
YES
  • 结果说明:async不会阻塞 HTML 解析器, async 脚本每个都会在下载完成后立即执行,无关 script 标签出现的顺序
示例3 script上加上defer属性
  • index.html
js 复制代码
<head>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js" defer></script>
  <script src="./index.js defer></script>
</head>

<body>
</body>
  • 控台结果
js 复制代码
4.17.10
YES
  • 结果说明:defer不会阻塞 HTML 解析器, - defer 脚本会根据 script 标签顺序先后执行

模块化之前 变量污染,请求多个script脚本性能浪费,依赖模糊

js 复制代码
// 全局定义变量 容易变量污染
function foo(){
}
function bar(){
}
// Namespace模式: 减少全局变量数量,但还是存在污染问题,还是可以通过对象改写数据,不安全
var myUtils = {
  foo:function(){},
  bar:function(){}
}

// 匿名闭包(IIFE模式):
var module = (function () {
    var age = 9;
    var foo = function () {
        console.log('age', age);
    }
    return {
        foo,
        age
    }
})()
module.age++
console.log('module.age', module.age);// 10
module.foo()  // 9

// IIFE模式,传入依赖
var module = (function ($, window) {
    var age = 9;
    var foo = function () {
        console.log('age', age);
    }
    return {
        foo,
        age
    }
})(jQuery, window)

模块化的诞生

目的:为避免全局污染,命名冲突,按需加载,提高复用和可维护性

  • 分类:commonjs amd es6

commonjs

  • CommonJS期初主要用于Node.js环境,采用同步加载模式,如果想运行于浏览器端,需要运行其编译后的产物
  • commonjs表现形式:对外暴露 exports / module.exports,引入则用var module = require('xxx.js')
js 复制代码
 // module1.js 1个文件可以有多个exports
 exports.foo = function(){
   console.log('module1---foo')
 }
 exports.bar = function(){
   console.log('module1---bar')
 }
 
 // module2.js 1个文件只有1个module.exports
 module.exports = {
   foo(){
      console.log('module2---foo')
   }
 }
 // 入口文件 main.js
 var module1 = require('./module1.js')
 var module2 = require('./module2.js')
 module1.foo()
 module2.foo()
 
 //index.html需要运行main.js编译后的产物才不会报错

amd(Requirejs)

  • amd 运行于浏览器端,通过异步加载模块,主要解决全局命名空间污染,相互依赖脚本加载顺序问题
  • amd表现形式:定义模块define(['依赖项'],function(依赖对象){}),引用则通过requirejs
js 复制代码
// module1.js (没有依赖的模块)
define(function(){
  var age = 9;
  function getAge(){
    return age;
  }
  // 暴露
  return {
    getAge
  }
})

// module2.js(有依赖的模块)
define(['module1'], function(module1){
  function showAge(){
    console.log('module2---showAge', module1.getAge)
  }
  return {
    showAge
  }
})

// main.js
requirejs.config({
  // baseUrl:'', // 基础路径
  paths:{
    module1: './module1', // key:define第一个参数的模块命名, 第二个参数是该模块对应的文件路径
    module2: './module2'
  }
})
requirejs(['module2'], function(module2){
  module2.showAge()
})

// index.html require.js是提前准备好的库
<script data-main="./main.js" src="./lib/require.js">

es6模块

  • es6模块 模块的导入是静态的,并且模块只有在被引用时才会执行,支持 Tree Shaking, 需要经过编译后运行于浏览器端
  • es6表现形式:export / export default,引入import {命名一致} from '' / import utils from ''
js 复制代码
// 导出变量、函数和类 
export const variable = 42; 
export function add(a, b) { return a + b; } 
export class Person { /* ... */ }

// 默认导出 
export default function() { 
  console.log('This is the default export.'); 
}

// 命名导入 
import { variable, add, Person } from './module.js';
// 默认导入 
import myFunction from './module.js';

es6模块的延伸(vite开发环境运行快也是基于现代浏览器对ESM的支持)

  • 本身es6模块需要经过编译,浏览器运行编译后的产物才不会报import等语法错误,但是基于现代浏览器对## <script type=module>的支持,使得浏览器以 ES Module 的方式加载脚本
  • 默认情况下 ES 脚本是 defer 的,无论内联还是外联,- 给 script 标签显式指定 async 属性,可以覆盖默认的 defer 行为
  • 安全策略更严格,非同域脚本的加载受 CORS 策略限制
相关推荐
吕彬-前端7 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱9 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai18 分钟前
uniapp
前端·javascript·vue.js·uni-app
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205872 小时前
web端手机录音
前端
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb