2024 年最新前端ES-Module模块化、webpack打包工具详细教程(更新中)

news2024/11/15 17:58:54

模块化概述

什么是模块?模块是一个封装了特定功能的代码块,可以独立开发、测试和维护。模块通过导出(export)和导入(import)与其他模块通信,保持内部细节的封装。

前端 JavaScript 模块化是指将代码拆分为独立的模块,每个模块负责特定的功能或逻辑。模块化的主要目的是提高代码的可维护性、可复用性和可扩展性。模块化让开发者能够组织代码,使之更加清晰、结构化,并且可以减少命名冲突和全局变量污染。

模块化优势

提高可维护性:模块的分离使代码更易于管理,修改或调试时只需专注于特定模块。
防止命名冲突:模块有自己的作用域,避免了全局作用域的污染。
重用性:可以将模块在不同的项目或文件中重复使用,提高开发效率。
依赖管理:模块化工具可以处理模块之间的依赖关系,确保按顺序加载。

模块化演变过程

前端 JavaScript 模块化从最早的无组织结构,到 IIFE、CommonJS、AMD,再到现代的 ES6 模块和打包工具,经历了不断演变。如今,ES6 模块已经成为标准,配合现代的打包工具,前端开发更加模块化和高效。

1. 没有模块化阶段 (ES3、ES3 之前)
在最早的 JavaScript 开发中,所有的代码都是通过 <script> 标签加载的。所有的脚本文件被直接插入 HTML 页面,并且依赖的加载顺序需要手动管理。这样容易导致命名冲突和全局变量污染。

2. 命名空间模式
前端开发者开始使用命名空间(Namespace)的方式组织代码,将相关功能模块封装在一个对象内,从而避免全局污染。

var MyModule = {
    foo: function() {
        console.log('foo');
    },
    bar: function() {
        console.log('bar');
    }
};

MyModule.foo();

3. 立即调用函数表达式(IIFE)
IIFE 是一个自执行的函数,它创建了一个局部作用域,从而避免了全局变量污染。IIFE 成为了一种非常流行的模块化模式。

var MyModule = (function() {
    var privateVar = 'I am private';
    
    function privateMethod() {
        console.log(privateVar);
    }
    
    return {
        publicMethod: function() {
            privateMethod();
        }
    };
})();

MyModule.publicMethod();

4. CommonJS (2009)
CommonJS 是 Node.js 中的模块化标准,也是服务器端 JavaScript 模块化的主要方式。它的特点是使用 require 导入模块,使用 module.exports 导出模块。

通过 module.exports 导出模块

module.exports = {
    foo: function() {
        console.log('foo');
    }
};
myModule.foo();

通过 require 导入模块

var myModule = require('./myModule');

5. AMD(Asynchronous Module Definition, 2010)
AMD 是一种用于浏览器的异步模块加载标准,最著名的实现是 RequireJS。AMD 的设计目标是解决浏览器环境中异步加载模块的问题。

定义模块

define('myModule', ['dependency'], function(dependency) {
    return {
        foo: function() {
            console.log('foo');
        }
    };
});

使用模块

require(['myModule'], function(myModule) {
    myModule.foo();
});

6.UMD(Universal Module Definition)

UMD 是为了兼容 CommonJS 和 AMD 而提出的一个模块化标准。UMD 模块可以同时运行在服务器端和浏览器端,解决了模块化标准不统一的问题。

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['dependency'], factory);
    } else if (typeof exports === 'object') {
        module.exports = factory(require('dependency'));
    } else {
        root.myModule = factory(root.dependency);
    }
}(this, function (dependency) {
    return {
        foo: function() {
            console.log('foo');
        }
    };
}));

7. ES6 模块(2015)
ECMAScript 2015 (ES6) 引入了官方的模块化系统,成为前端模块化的标准。它支持静态分析和编译时优化,模块以 importexport 进行导入和导出:

通过 export 导出模块

export function foo() {
    console.log('foo');
}

通过 import 导入模块

import { foo } from './myModule.js';
foo();

ES6 模块系统特点:

- 静态引入:模块依赖在编译时解析,能够优化打包体积和性能。
- 作用域独立:每个模块都有自己的作用域,防止命名冲突。
- 支持异步加载:通过 `import()` 动态导入模块。

8. 模块打包工具

随着 JavaScript 项目规模的扩大和模块化需求的增加,模块打包工具应运而生,它们允许开发者使用各种模块化标准,并将它们打包为浏览器兼容的文件。

- Browserify:最早的工具之一,允许在浏览器中使用 CommonJS 模块。
- Webpack:目前最流行的打包工具之一,支持 CommonJS、ES6 模块以及插件扩展。
- Rollup:专注于 ES6 模块的打包工具,生成的文件更为轻量。
- Parcel:零配置的打包工具,支持多种模块标准,且性能优异。

9. ES Module 在浏览器中的原生支持

现代浏览器现在已经支持原生的 ES6 模块化系统,开发者可以直接在浏览器中使用 type="module"<script> 标签。这让开发者可以直接在浏览器环境中使用 ES6 模块,而无需通过打包工具进行预处理。

<script type="module">
  import { foo } from './myModule.js';
  foo();
</script>

ES6 Module 特性

ES Module(ESM)是 ECMAScript 2015(ES6)引入的官方 JavaScript 模块系统,专门用于解决现代开发中模块化需求。它的特性包括静态分析、作用域隔离、支持异步加载等。它提高了代码的可维护性、性能和开发效率,并得到了浏览器和服务器环境的广泛支持。

1. 静态加载(静态分析)

ESM 的依赖关系在编译时就能确定,因此可以进行静态分析。这意味着模块依赖在代码执行前已被解析,编译器和打包工具可以在构建时进行优化和错误检查。

import { foo } from './myModule.js';

由于导入语句是静态的,工具可以提前检测哪些模块被使用,未使用的代码可以在构建过程中进行“树摇”(tree-shaking)优化,从而减小打包体积。

2. 作用域隔离

每个 ES 模块都有自己的独立作用域,模块内部的变量和函数不会泄露到全局作用域。这种封装避免了不同模块之间的命名冲突,确保代码安全。模块内部的 secret 变量是私有的,外部无法访问,只有 publicVar 通过 export 导出,供其他模块使用。

module.js

let secret = "I'm private";
export const publicVar = 'I am public';

3. import 和 export

ESM 使用 exportimport 关键字进行模块的导出和导入,有两种导出方式:命名导出默认导出

命名导出(Named Export):可以导出多个变量、函数或类,并且在导入时需要按名字导入。

module.js

export const foo = () => console.log('foo');
export const bar = () => console.log('bar');

main.js

import { foo, bar } from './module.js';
foo();
bar();

默认导出(Default Export):每个模块只能有一个默认导出,导入时可以自定义导入的名称。

module.js

export default function() {
  console.log('default export');
}

main.js

import myFunction from './module.js';
myFunction(); // 输出 'default export'

4. 模块是单例的

ES 模块是单例的,意味着每个模块只会被加载和执行一次,后续的导入都引用相同的模块实例。这保证了模块的状态在多个导入中是共享的。

module.js

let count = 0;
export const increment = () => count++;
export const getCount = () => count;

main.js

import { increment, getCount } from './module.js';
increment();
console.log(getCount()); // 1
increment();
console.log(getCount()); // 2

5. 严格模式

所有的 ES 模块默认处于严格模式(use strict),这意味着无法使用一些松散的 JavaScript 语法(如隐式全局变量、删除未定义属性等),从而提高代码的安全性和性能。

模块中自动使用严格模式

x = 10; // ReferenceError: x is not defined

6. 支持异步动态导入

除了静态导入,ES 模块还支持动态导入。通过 import() 函数,可以在代码执行时按需加载模块,动态导入返回一个 Promise。这个特性非常适合代码拆分和按需加载,尤其是在大型应用中提高性能。

main.js

document.getElementById('loadModule').addEventListener('click', async () => {
  const module = await import('./module.js');
  module.foo(); // 动态加载模块后调用
});

7. 浏览器原生支持

现代浏览器支持原生 ES 模块,开发者可以直接在浏览器中使用模块功能,无需额外的打包工具。通过 <script type="module"> 标签,浏览器可以异步加载模块,并自动管理模块的依赖关系。

<script type="module">
  import { foo } from './module.js';
  foo();
</script>

8. 文件路径和后缀

在使用 import 时,模块的文件路径必须是相对路径或绝对路径,并且需要指定 .js 后缀。这与 Node.js 的 CommonJS 模块系统不同,后者可以省略文件扩展名。

import { foo } from './module.js'; // 必须加 .js 扩展名

9. 兼容性 与 Polyfill

为了支持旧版浏览器和环境,开发者通常使用 Babel 等工具将 ES 模块转换为 CommonJS 或其他模块格式,同时结合 Webpack 等打包工具来处理依赖关系。

Polyfill 是一种用于在旧版本浏览器或不支持某些新特性环境中实现现代 JavaScript 功能的技术。它通常是指一个库或代码片段,用来提供尚未被原生支持的功能,让开发者能够使用最新的语言特性,同时保证在较旧环境中的兼容性。

随着 JavaScript 语言和浏览器技术的发展,新功能和 API 被不断引入,而这些功能可能不会立即在所有浏览器或环境中得到支持。Polyfill 使开发者可以在旧环境中使用这些新功能,而不必等待所有用户的浏览器升级。

早期浏览器不支持 Promise、fetch、Array.prototype.includes 等功能,但通过 Polyfill,开发者仍可以在这些浏览器中使用这些特性。
在 IE 浏览器中,许多 ES6(如 Map、Set)或 HTML5 API 都不被支持,Polyfill 可以帮助实现这些功能。

webpack 打包工具

Webpack 是一个非常流行的 JavaScript 模块打包工具,主要用于将前端项目中的各种资源(包括 JavaScript、CSS、图片等)打包成浏览器可以直接加载的文件。它支持模块化开发,并通过配置文件允许高度定制打包过程。

在这里插入图片描述

Webpack 工作原理

读取入口文件:Webpack 从配置文件中指定的入口文件开始,递归地读取文件中的依赖(如 import 和 require)。
构建依赖图:通过解析每个模块的依赖,Webpack 构建出一个完整的依赖图。
应用 Loaders:根据配置,Webpack 使用不同的 Loader 处理非 JavaScript 文件(如 CSS、图片、SASS 等)。
应用 Plugins:Webpack 在打包的不同阶段执行插件进行优化或特定的处理,如压缩代码、生成 HTML 文件等。
输出文件:Webpack 根据依赖图,生成打包后的文件,通常是一个或多个 JavaScript 文件,以及其他的静态资源(CSS、图片等)。

Webpack 优点

高度可配置:Webpack 提供了灵活的配置方式,可以根据项目需求进行高度定制。
强大的社区支持:Webpack 拥有丰富的插件和 loader 生态,几乎能满足所有类型的前端打包需求。
优化性能:通过代码拆分、Tree Shaking 等技术,Webpack 能够有效优化前端代码的加载速度和性能。

更新中······

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156485.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Pytorch】一文快速教你高效使用torch.no_grad()

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 博主简介 博主致力于嵌入式、Python、人工智能、C/C领域和各种前沿技术的优质博客分享&#xff0c;用最优质的内容带来最舒适的…

2024年中国研究生数学建模竞赛A/C/D/E题全析全解

问题一&#xff1a; 针对问题一&#xff0c;可以采用以下低复杂度模型&#xff0c;来计算风机主轴及塔架的疲劳损伤累积程度。 建模思路&#xff1a; 累积疲劳损伤计算&#xff1a; 根据Palmgren-Miner线性累积损伤理论&#xff0c;元件的疲劳损伤可以累积。因此&#xff0c;…

基于SpringBoot+Vue的商城积分系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目源码、Python精…

手机在网状态查询接口如何用C#进行调用?

一、什么是手机在网状态查询接口&#xff1f; 手机在网状态查询接口是利用实时数据来对手机号码在运营商网络中的状态进行查询的工具&#xff0c;包括正常使用状态、停机状态、不在网状态、预销户状态等。 二、手机在网状态查询适用哪些场景&#xff1f; 例如&#xff1a;商…

【线程池】ThreadPoolExecutor应用

ThreadPoolExecutor应用 每一步的坚持与积累,都是铸就高薪和大牛的必经的修炼 哈哈,不吹牛逼了,今天来分享最近在提升中的学习总结,无论是对在职场还是求职,看完,我相信都会有些许的收获和成长 也难得过了一个悠闲点的周末,哈哈哈,一起奥利给!! 本文总纲: 1.为什么要自定义线程…

联合体的用法和用联合体判断大小端存储

像结构体⼀样&#xff0c;联合体也是由⼀个或者多个成员构成&#xff0c;这些成员可以不同的类型。但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所 以联合体也叫&#xff1a;共⽤体。 给联合体其中⼀个成员赋值&#xff0c;其他成…

Linux 文件系统(下)

目录 一.文件系统 1.文件在磁盘上的存储方式 a.盘面、磁道和扇区 b.分区和分组 2.有关Block group相关字段详解 a.inode编号 b.inode Table&#xff08;节点表&#xff09; c.Data blocks&#xff08;数据区&#xff09; d.小结 二.软硬链接 1.软链接 a.软链接的创建…

SystemExit: 系统退出异常的完美解决方法⚙️

&#x1f6aa;SystemExit: 系统退出异常的完美解决方法⚙️ &#x1f6aa;SystemExit: 系统退出异常的完美解决方法⚙️摘要引言正文1. 什么是SystemExit异常&#xff1f;&#x1f4dc;2. 捕获SystemExit&#xff1a;是否应该这样做&#xff1f;⚠️3. 正确处理SystemExit的最…

javase复习day30综合练习

制造假数据 制造数据 练习一 package Demo1;import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; im…

上海数科(北京)律师事务所开业庆典圆满举行

金秋送爽&#xff0c;丹桂飘香。2024年9月22日&#xff0c;数智科技焕新启航主题论坛暨上海数科&#xff08;北京&#xff09;律师事务所&#xff08;以下简称“数科北京”&#xff09;开业庆典在北京中海广场中楼隆重举行。 庆典现场星光熠熠&#xff0c;汇聚了来自法律界、科…

程序员的AI时代:拥抱变革,塑造未来

你们有没有想过&#xff0c;如果有一天&#xff0c;你的编程工作被一个AI助手取代了&#xff0c;你会怎么办&#xff1f;这不是危言耸听&#xff0c;随着AIGC技术的飞速发展&#xff0c;这样的场景可能真的会出现。但是&#xff0c;别担心&#xff0c;今天我们就来聊聊&#xf…

云栖通道看AI产业应用,打开大模型的无限可能

9月19日-21日&#xff0c;2024云栖大会在杭州西湖区云栖小镇举行。20日&#xff0c;云栖通道如约开放。 这是一个为广大AI产业从业者、创业者以及大模型开发者提供的专属交流平台。来自教育、智能体应用、智能驾驶、人形机器人等多个AI应用领域的科学家、开发者、技术代表等现…

AI客服对决:智能客服PK赛揭示企业级AI应用未来

如今的AI对抗场景&#xff0c;简直成了颇具娱乐性的“观赏项目”。围观群众们不仅看得津津有味&#xff0c;时不时还会发出阵阵笑声。 最近&#xff0c;一场别开生面的AI客服挑战赛引发了热议&#xff1a;一位使用“花开富贵”阿姨人设的Agent甩出一条链接&#xff0c;结果对面…

WPF DataGrid 单元格居中,头部居中,点击行改变背景色。

我得全局样式都写在了App.XAML文件下的ResourceDictionary里&#xff0c;方便全局引用 DataGrid样式和点击改变行背景色的触发器(BasedOn继承的是UI框架的样式&#xff0c;若无则删除&#xff0c;触发器还有鼠标移动事件等&#xff0c;按需自行修改添加) <Style x:Key&quo…

Docker_基础初识

文章目录 初识Docker什么是虚拟化、容器化为什么要虚拟化、容器化&#xff1f;虚拟化实现方式应用程序执行环境分层虚拟化常见类别 常见虚拟化实现主机虚拟化(虚拟机)实现Hypervisor 容器虚拟化实现 namespace隔离实操基础知识dd命令语法参数 mkfs 命令语法参数 df 命令语法参数…

视觉距离与轴距离的转换方法

1.找一个明显的参照物&#xff0c;用上方固定的相机拍一下。保存好图片 2.轴用定长距离如1mm移动一下。 3.再用上相机再取一张图。 4.最后用halcon 将两图叠加 显示 效果如下 从图上可以明显的看出有两个图&#xff0c;红色标识的地方。 这时可以用halcon的工具画一个长方形…

深度学习-卷积神经网络(CNN)

文章目录 一、网络构造1. 卷积层&#xff08;Convolutional Layer&#xff09;&#xff08;1&#xff09;卷积&#xff08;2&#xff09;特征图计算公式&#xff08;3&#xff09;三通道卷积 2. 激活函数&#xff08;Activation Function&#xff09;3. 池化层&#xff08;Pool…

Elasticsearch不停机切换(上云)方案

如何给飞行中的飞机换引擎? 背景 业务背景 略 技术背景 线下集群40个索引左右&#xff0c;总数据量不大,不到100G因为ES承担的业务鉴权业务&#xff0c;所以不能接受停机割接 还有就是ES中数据来自各个业务方&#xff0c;推送的时机不定&#xff0c;也没有完备的重推机制&…

漏洞复现_永恒之蓝

1.概述 永恒之蓝&#xff08;EternalBlue&#xff09;是一个影响Windows操作系统的远程代码执行漏洞&#xff0c;编号为CVE-2017-0144&#xff0c;最初由美国国家安全局&#xff08;NSA&#xff09;开发并利用&#xff0c;后来被黑客组织Shadow Brokers泄露。该漏洞存在于SMBv…

『功能项目』QFrameWork制作背包界面UGUI【72】

本章项目成果展示 我们打开上一篇71QFrameWork更新道具图片UGUI的项目&#xff0c; 本章要做的事情是制作背包UI界面&#xff0c;实现道具栏与背包道具的互通 首先将以下资源图片放进Art文件夹 将UICanvas的UISlot对象复制一份放在Image下 创建Scrollbar View 设置Scrollbar V…