JS 模块化

一、JS 中的模块化规范

要明白我们的打包工具究竟做了什么,首先必须明白的一点就是 JS 中的模块化。

在 ES6 规范之前,我们有 CommonJS、AMD 等主流的模块化规范。

1、CommonJS(node.js 原生 & 同步加载 & 多次加载一次执行)

Node.js 是一个基于 V8 引擎,事件驱动 I/O 的服务端 JS 运行环境。

在 2009 年刚推出时,它就实现了一套名为 CommonJS 的模块化规范。

在 CommonJS 规范里:

  • 每个 JS 文件都是一个模块(module),每个模块内部都可以使用 require 函数和 module.exports 对象,来对模块进行导入和导出。

示例代码:

javascript 复制代码
// index.js
require('./moduleA');
const str = require('./moduleB');
console.log('index', str);

// moduleA.js
const timestamp = require('./moduleB');
setTimeout(() => console.log('moduleA', timestamp), 1000);

// moduleB.js
module.exports = new Date().getTime();

执行说明:

  • index.js 代表的模块通过执行 require 函数,分别加载了相对路径为 ./moduleA 和 ./moduleB 的两个模块,同时输出 moduleB 模块的结果。
  • moduleA.js 文件内也通过 require 函数加载了 moduleB.js 模块,在 1s 后也输出了加载进来的结果。
  • moduleB.js 文件内部定义了一个时间戳,使用 module.exports 对象导出。

运行结果(执行 node index.js):

diff 复制代码
index 1738743973675
moduleA 1738743973675

模块特性:

  • 每个模块都是单例的,当一个模块被多次加载的时候,最终执行实际上只会被执行一次。

2、AMD(浏览器端 & 异步 & 多次加载一次执行)

另一个为 WEB 开发者所熟知的 JS 运行环境就是浏览器了。浏览器并没有提供像 Node.js 里一样的 require 方法。

不过,受到 CommonJS 模块化规范的启发,WEB 端还是逐渐发展起来了 AMD、SystemJS 规范等适合浏览器端运行的 JS 模块化开发规范。

AMD 全称 Asynchronous module definition,意为异步的模块定义,不同于 CommonJS 规范的同步加载,AMD 正如其名所有模块默认都是异步加载,这也是早期为了满足 web 开发的需要,因为如果在 web 端也使用同步加载,那么页面在解析脚本文件的过程中可能使页面暂停响应。

示例代码:

javascript 复制代码
// index.js
require(['moduleA', 'moduleB'], function(moduleA, moduleB) {
    console.log('index', moduleB);
});

// moduleA.js
define(function(require) {
    const timestamp = require('moduleB');
    setTimeout(() => console.log('moduleA', timestamp), 1000);
});

// moduleB.js
define(function(require) {
    return new Date().getTime();
});

使用说明 :

如果想要使用 AMD 规范,我们还需要添加一个符合 AMD 规范的加载器脚本在页面中,符合 AMD 规范实现的库很多,比较有名的就是 require.js。

3、ESModule

前面我们说到的 CommonJS 规范和 AMD 规范有这么几个特点:

  1. 语言上层的运行环境实现的模块化规范,模块化规范由环境自己定义。
  2. 相互之间不能兼容使用。例如不能在 Node.js 运行 AMD 模块,不能直接在浏览器运行 CommonJS 模块。

在 EcmaScript 2015(也就是我们常说的 ES6)之后,JS 有了语言层面的模块化导入导出语法以及与之匹配的 ESModule 规范。

使用 ESModule 规范,我们可以通过 import 和 export 两个关键词来对模块进行导入与导出。

示例代码(基于 ESModule 规范改写之前的例子):

javascript 复制代码
// index.js
import './moduleA';
import str from './moduleB';
console.log(str);

// moduleA.js
import timestamp from './moduleB';
setTimeout(() => console.log('moduleA', timestamp), 1000);

// moduleB.js
export default new Date().getTime();

Webpack 配置(webpack.config.js):

javascript 复制代码
const path = require('path');

module.exports = {
    mode: 'none',
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.bundle.js', // 注意 filename 是小写不是 fileNane
        publicPath: 'dist/'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader', // 所有的 js 文件进 webpack 处理的过程中都使用 babel 进行编译
                    options: {
                        presets: ['@babel/preset-env'] // 支持使用环境参数来处理不同的内容
                    }
                }
            }
        ]
    }
};

依赖安装与运行:

bash 复制代码
# 安装依赖
yarn add webpack webpack-cli @babel/core babel-loader @babel/preset-env 

# 编译打包
./node_modules/.bin/webpack 

# 启动静态服务器(可使用 Python 简单启动)
python3 -m http.server 

关于 JS 运行环境与解析器

每个 JS 的运行环境都有一个解析器,否则这个环境也不会认识 JS 语法。

它的作用就是用 ECMAScript 的规范去解释 JS 语法,也就是处理和执行语言本身的内容。

例如按照逻辑正确执行 var a = "123"; function func() { console.log("hahaha"); } 之类的内容。

在解析器的上层,每个运行环境都会在解释器的基础上封装一些环境相关的 API。

例如 Node.js 中的 global 对象、process 对象,浏览器中的 window 对象、document 对象等等。

这些运行环境的 API 规范各自规范的影响,例如浏览器端的 W3C 规范,它们规定了 window 对象和 document 对象上的 API 内容,以使得我们能让 document.getElementById 这样的 API 在所有浏览器上运行正常。

以上就是对 JS 模块化相关规范(CommonJS、AMD、ESModule )以及 JS 运行环境、解析器等相关内容的梳理 ,通过不同规范的对比,能更清晰理解在不同场景(Node.js 服务端、浏览器端等 )下模块化的实现与应用 。

相关推荐
kyriewen1 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒1 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫2 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus2 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude
孟陬3 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端
Zhao-Jichao3 小时前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端
Highcharts.js4 小时前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化
Dream-Y.ocean4 小时前
鸿蒙PC平台星图遥感适配实战:基于 Electron 壳方案的纯 JavaScript 遥感图像处理引擎开发
javascript·electron·harmonyos
螺丝钉tina5 小时前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
小天源5 小时前
智叟云集系统 · 架构与职责分层
服务器·前端·数据库