前端模块化

这篇具有很好参考价值的文章主要介绍了前端模块化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 

1.为什么需要模块化

随着前端应用的日益复杂,我们的项目代码已经逐渐膨胀到了不得不花大量时间去管理的程度了。而模块化就是一种最主流的代码组织方式,它通过把复杂的代码按照功能的不同划分为不同的模块单独维护,从而提高开发效率、降低维护成本。模块化可以使你能够更容易地重用代码。你可以创建一个模块来完成一个特定的功能,然后在多个地方重用这个模块,而不是复制和粘贴代码。

2.没有工具和规范时模块化的演进历史

2.1文件划分

最早期的模块化是通过文件划分的方式,将不同的文件划分为不同的模块,一个文件就对应一个模块,如下图就有2个模块a和b。

想要使用模块的时候就用script标签引入该模块

<script src="module-a.js"></script>
<script src="module-b.js"></script>

前端模块化

这种方式存在的问题

  1. 难以管理模块之间的依赖关系
  2. 多个模块的变量名会出现冲突
  3. 外部可以修改模块的内容

2.2命名空间

为了解决以上出现的问题,又有了一种新的模块化方式,便是命名空间,通过将每个模块包裹成一个全局对象来实现,这样的确解决了命名冲突问题,但是仍然存在外部可以修改模块内部内容的问题

前端模块化

使用模块

<script src="module-a.js"></script>
<script src="module-b.js"></script>
<script>
moduleA.method1()
moduleB.method1()
//模块成员可以被修改
moduleA.name = 'foo‘
</script>

2.3立即执行函数

用立即执行函数实现了私有成员的方式,外部无法修改内部的变量,通过挂载到window对象上来完成模块化的暴露

前端模块化

 

3.模块化规范

前面所提到的几种早期模块化方式都有一个问题,就是必须通过script脚本标签来使用模块,但是如果随着项目规模的增大,忘记加入script标签或者引入了已经删除的模块,就会出现一些问题。也就是说,最好要把引入模块化这个工作放到js代码中去完成,而不只是在html中引入

3.1 CommonJS

NodeJS里的CommonJS规范是一个很好的模块化方式,CommonJS包含以下几个特征

  1. 一个文件就是一个模块
  2. 每个模块都有单独的作用域
  3. 通过 module.exports 导出成员
  4. 通过 require 函数载入模块

特征中的第4个,require是同步的加载,在Node中只会在启动的时候加载,执行的时候只是去使用,而到了浏览器端,每一次刷新页面都会导致大量的同步模式请求出现,这就无法使用了。

3.2 AMD(Asynchronous Module Definition)

AMD(Asynchronous Module Definition)是 RequireJS 在推广过程中对模块定义的规范化产出,。由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是require.js。

AMD这个规范约定每一个模块都必须通过 define 这个函数定义,默认可以接收两个参数,也可以传递三个参数:

  1. 第一个参数是模块的名字;
  2. 第二个参数是一个数组,用于声明模块依赖项;
  3. 第三个参数是一个函数,函数的参数与前面的依赖项一一对应,每一项分别为依赖项这个模块导出的成员,这个函数的作用可以以理解为为当前的这个模块提供一个私有的空间。如果需要在这个模块当中向外部导出一些成员,可以通过 return 实现

前端模块化

 AMD也可以通过require方法来加载对应的模块,require与define的区别是,require只是用来加载,而define是定义一个模块

前端模块化

 

 

 案例

src
├── index.html
├── index.js
├── lib
│   └── require.js // 使用require.js 库
└── modules
    ├── dataServe.js
    └── example.js
  • dataServe
// 导入example
define(['example'], function (example) {
    let msg = "data"
    function showMsg () {
        console.log(msg, example.getName());
    }
    return { showMsg }
})
  • example.js
define(function () {
    let name = "w"
    function getName () { return name }
    return { getName }
})
  • index.js
(function () {
    requirejs.config({
        paths: {
            example: './modules/example',
            dataServe: './modules/dataServe'
        }
    })

    requirejs(['dataServe'], function (d) {
        d.showMsg()
    })

})()
  • index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <script data-main="./index.js" src="lib/require.js"></script>
    </body>
</html>

问题:

  1. 使代码复杂度提高
  2. 如果模块划分的过于细致,同一个页面的请求会过多,页面效率低下

3.3 CMD+Sea.js

与CommonJS基本保持一致,但是后来也被require.js兼容了

前端模块化

3.4 ES Module

ES Module是现在最常用的模块化解决方案,仍然采用了与CommonJS相似的import和export来完成模块的导入和导出

在html中,只需要在script标签里加入type="module"就可以导入模块

<script type="module"> console.log('this is es module') </script>

与普通script标签不同的地方是:

  1. es模块会自动开启严格模式,忽略掉use strict。
  2. es模块都有单独的作用域
  3. es模块通过CORS方式请求,如果请求的资源不支持CORS会报跨域错误
  4. es模块等于在脚本上加入defer属性,让脚本等同步内容加载完后异步按顺序执行
<script type="module">
    //es模块会自动开启严格模式
    console.log(this); //undefined
</script>
<script type="module">
    //es模块都有单独的作用域
    let a = 1
    console.log(a); //1
</script>
<script type="module">
    //es模块都有单独的作用域
    let a = 2
    console.log(a); //2
</script>

 

导出:使用export关键词来完成导出

普通导出:

方式一 用{}包裹需要导出的变量,函数或者类,如果想要改名,可以在导出时用as来改

const name = "why";
const age = 18;

function sum(a, b) {
  return a + b;
}

class Person {
  constructor(name) {
    this.name = name;
  }
}

//3.统一导出时使用as关键字给变量起别名
export { name as bName, age, sum as bSum, Person };

方式二 export直接放在变量,函数,类声明之前

export const name = "why";
export const age = 18;

export function sum(a, b) {
  return a + b;
}

export class Person {
  constructor(name) {
    this.name = name;
  }
}

默认导出

方式一:不使用{}包裹变量,函数,类

 

const height = 1.88;

export default height;

 

方式二:使用{}包裹变量,函数,类,但必须通过as改变名字为default

 

const height = 1.88;

export {
  height as default
};

 

 

导入:使用import关键词来完成导入

方式一:分别导入,可以通过as来起别名

import {
  name as barName,
  age,
  sum,
  Person as BarPerson,
} from "./bar.js";

方式二:整体导入,通过as来起别名,然后分别使用

import * as baz from "./baz.js";
console.log(baz.name, baz.age);

baz.sum(1, 2);

const person2 = new baz.Person("lily");
console.log(person2);

方式三:导入默认导出的变量,不加{}包裹

import height from "./demo.js";
console.log(height);

 

导入导出注意点:

  1. ES Module导出的变量并非变量的值本身,而是一个引用,所以导入的变量的值会受原模块的影响
  2. 导入的变量是只读的,不能进行赋值更改
  3. import异步实现,会有一个独立的模块依赖的解析阶段
  4. 不能与CommonJS相似地在导入路径中省略.js(可通过打包配置改善)

举例:导入的变量的值会受原模块的影响

前端模块化

 在导入中使用导出:把import from改成export from

常用于集中导出,方便后续导入资源

 

前端模块化

 

与CommonJS的互动 

在node环境下,虽说一般都是CommonJS规范的模块化,但是node也做了兼容可以让ES Module正常使用,只要把原来的.js文件改为.mjs就可以正常使用import语法了。import导入的时候还可以导入CommonJS的模块,只是所有CommonJS模块都会被当作默认导出的方式来导入。但是在CommonJS里面,无法使用require去导入ES Module导出的内容,也就是在下面的b.js里面会报错

  • a.mjs
import b from './b.js'

console.log(b.name); // 1234

export let a = 4

 

  • b.js 

 

 

const a = require('./a.mjs') // 报错
module.exports = {
    name: '1234'
}

 文章来源地址https://www.toymoban.com/news/detail-709876.html

到了这里,关于前端模块化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端工程化之模块化

    前端模块化是一种标准,不是实现 理解模块化是理解前端工程化的前提 前端模块化是前端项目规模化的必然结果 前端模块化就是将复杂程序根据规范拆分成若干模块,一个模块包括输入和输出。而且模块的内部实现是私有的,它通过对外暴露接口与其他模块通信,而不是直

    2024年02月11日
    浏览(137)
  • 前端基础(ES6 模块化)

    前言:前面学习了js,引入方式使用的是script s\\\"XXX.js\\\",今天来学习引入文件的其他方式,使用ES6 模块化编程,学习组件化编程中的全局注册和局部注册的方法。 目录 复习 ES6 模块化导出导入 解构赋值 导入js文件 export default 全局注册 局部注册 回顾前面学习内容,用script s\\\"

    2024年02月11日
    浏览(30)
  • 前端面试题---模块化和性能优化

    模块化是一种将程序代码划分为独立、可复用的模块的开发方法。它能够提高代码的可维护性、可复用性和可扩展性,使得代码更易于组织、调试和协作。 常见的模块化方案包括: AMD(Asynchronous Module Definition):AMD是一种异步加载模块的规范,主要用于浏览器环境。它使用

    2024年02月10日
    浏览(31)
  • 前端基础(Vue的模块化开发)

      前言 :前面学习了前端HTML、CSS样式、JavaScript以及Vue框架的简单适用,接下来运用前端模块化编程的思想,继续学习Vue框架,完成自己项目项目的搭建。 目录 响应式基础 ref reactive 学习成果展示 Vue项目搭建 搭建自己的vue项目 总结  关于ref和reactive,官方解释如下,另外一

    2024年02月12日
    浏览(34)
  • 04_前端包管理工具&模块化

    注意事项: ​ 改模块代码不用重启服务器,修改config文件的时候需要重启服务器 ​ nvm的安装路径和node的安装路径不能在同一路径下面 ​ 有乱码问题使用管理员权限进行使用use方法 下载安装node ​ 使用命令进行安装 1.nvm list 查看已下载所有的node版本 2.nvm install 版本号 下载指

    2024年02月12日
    浏览(34)
  • 简单聊两句前端模块化

    在前端开发中,模块化是一种将代码拆分为独立模块的开发方法。它通过将功能相似或相关的代码组织成可复用、可维护的模块,以提高开发效率和代码质量。 模块化的主要目的是解决传统的JS开发存在的问题,例如全局命名冲突、代码复用困难、依赖管理混乱等。通过模块

    2024年02月05日
    浏览(27)
  • 前端node.js入门-前端工程化与模块化

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 Node.js 入门  什么是 Node.js? 什么是前端工程化?   Node.js 为何能执行 JS?  fs 模块 - 读写文件  path 模块 - 路径处理 URL 中的端口号  常见的服务程序  Node.js 模块化 什

    2024年02月14日
    浏览(51)
  • 为什么WebSocket需要前端心跳检测,有没有原生的检测机制?

    本文代码 github、gitee、npm 在web应用中,WebSocket是很常用的技术。通过浏览器的WebSocket构造函数就可以建立一个WebSocket连接。但当需要应用在具体项目中时,几乎都会进行心跳检测。 设置心跳检测,一是让通讯双方确认对方依旧活跃,二是浏览器端及时检测当前网络线路可用

    2024年02月03日
    浏览(41)
  • 前端框架的CSS模块化(CSS Modules)

    创作纪念日之际,来给大家分享一篇文章吧 聚沙成塔·每天进步一点点 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些

    2024年03月27日
    浏览(31)
  • 【FPGA/IC】什么是模块化设计?

    FPGA/IC设计中根据模块层次的不同有两种基本的设计方法: 自下而上 方法对设计进行逐次划分的过程是从基本单元出发的,设计树最末枝上的单元是已经设计好的基本单元,或者其他项目开发好的单元或者IP。该方法先对底层的功能块进行分析,然后使用这些模块来搭建规模

    2024年03月19日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包