引言:模块化开发的演进

在早期的前端开发中,JavaScript 缺乏原生的模块化支持,开发者不得不依赖 IIFE(立即调用函数表达式)或第三方库(如 RequireJS)来实现代码组织。随着 ES6(ES2015)的发布,JavaScript 终于迎来了官方的模块系统——ES Modules(ESM),这彻底改变了前端开发的方式。

一、<script type="module"> 的革命

1.1 什么是 ES Modules?

ES Modules 是 JavaScript 的官方模块标准,它通过 import 和 export 语法实现了模块化编程:

// 模块导出 (math.js)
export const add = (a, b) => a + b;// 模块导入 (app.js)
import { add } from './math.js';

1.2 type="module" 的特性

当我们在 HTML 中使用 <script type="module"> 时,浏览器会以特殊方式处理这个脚本:

  • 模块作用域:变量不会污染全局命名空间

  • 严格模式:代码自动在严格模式下运行

  • 延迟执行:默认具有 defer 行为

  • 跨域限制:必须遵守 CORS 策略(Cross-Origin Resource Sharing:跨源资源共享,是一种基于 HTTP 头的安全机制,用于控制网页应用在不同源“domain”之间访问资源的权限。)

<script type="module" src="app.js"></script>

1.3 与传统脚本的对比

特性type="module"传统脚本
作用域模块作用域全局作用域
严格模式默认启用需要手动声明
依赖解析静态分析(编译时)动态解析(运行时)
执行时机默认 defer立即执行(阻塞渲染)
文件扩展名推荐 .mjs(接受 .js).js

二、构建工具下的 TypeScript 模块

2.1 为什么能直接导入 .ts 文件?

在现代构建工具如 Vite、Webpack 或 Rollup 中,直接导入 .ts 文件成为可能:

<script type="module" src="/src/main.ts"></script>

这背后的魔法在于构建工具的处理流程:

  1. 开发环境

    • Vite 服务器拦截请求

    • 实时编译 TypeScript 为 JavaScript

    • 返回标准的 ES Module 给浏览器

  2. 生产环境

    • 构建时将 .ts 编译为 .js

    • 生成的文件名通常包含哈希值(如 main.a1b2c3.js

2.2 构建工具的工作流程(以 Vite 为例)

浏览器请求 main.ts → Vite 开发服务器 → 即时编译 → 返回 ESM JavaScript → 浏览器执行

这种设计带来了极佳的开发体验(HMR 热更新)和高效的生产构建。

三、defer 的深层意义

3.1 defer 的核心作用

defer 属性控制脚本的执行时机,其核心特点是:

  • 不阻塞 HTML 解析:浏览器会并行下载脚本

  • 保持执行顺序:多个 defer 脚本按声明顺序执行

  • 执行时机:在 DOM 解析完成后,DOMContentLoaded 事件前触发

3.2 type="module" 的隐式 defer

所有模块脚本自动获得 defer 行为:

<!-- 以下两种写法等效 -->
<script type="module" src="app.js"></script>
<script defer type="module" src="app.js"></script>

3.3 不同加载策略对比

策略执行时机阻塞解析顺序保证适用场景
无属性立即执行传统脚本
async下载完立即执行独立第三方库(如分析)
deferDOM 解析后执行主应用逻辑
type="module"同 defer现代模块化应用

四、现代前端开发最佳实践

4.1 项目结构建议

src/├── main.ts       # 应用入口├── components/   # 组件├── utils/        # 工具函数└── styles/       # 样式

4.2 构建配置示例(vite.config.ts)

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'export default defineConfig({plugins: [vue()],build: {target: 'esnext' // 生成现代 ESM 代码}
})

4.3 性能优化技巧

  1. 代码分割:利用动态 import() 实现按需加载

    const module = await import('./heavy-module.ts')

  2. 预加载:使用 <link rel="modulepreload"> 提前加载关键模块

  3. 共享依赖:将公共依赖提取为单独 chunk

五、未来展望

随着 ESM 导入映射(Import Maps) 的普及,未来可能实现:

<!-- 浏览器原生支持裸模块导入 -->
<script type="importmap">
{"imports": {"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"}
}
</script><script type="module">
import { createApp } from 'vue' // 直接使用
</script>

结语

从 <script type="module"> 到构建工具对 TypeScript 的原生支持,现代前端开发已经实现了质的飞跃。理解这些技术背后的原理,能帮助我们构建更高效、更可维护的 Web 应用。随着浏览器能力的不断增强和工具链的持续优化,模块化开发的体验将会越来越好。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yolo--qt可视化开发

qt5可能不支持我们的cuda版本&#xff0c;改用qt6 YOLO11QT6OpencvC训练加载模型全过程讲解_yolov11 模型转换成opencv c模型-CSDN博客 下面是qt5版本的案例&#xff0c;和yolo及cuda有冲突 安装qt 切换到虚拟环境&#xff0c;例如pyqt&#xff0c;conda activate pyqt pip …

SQL性能优化

show [session|global] status : 查看服务器状态 show global status like Com_ : 查看各种语句的执行次数 开启慢查询: 在 MySQL 配置文件&#xff08;/etc/my.cnf&#xff09;配置: #开启MySQL慢日志查询开关 slow_query_log1 #设置慢日志的时间为2秒&#xff0c;SQL语句执…

ctfshow pwn40

目录 1. 分析程序 2. 漏洞编写 3. 漏洞验证 1. 分析程序 首先检查程序相关保护&#xff0c;发现程序为32位且只开启了一个NX保护 checksec pwn 使用IDA进行逆向分析代码&#xff0c;查看漏洞触发点&#xff1a; 在main函数中&#xff0c;有一个ctfshow函数&#xff0c;这里…

SQL173 店铺901国庆期间的7日动销率和滞销率

SQL173 店铺901国庆期间的7日动销率和滞销率 SQL题解&#xff1a;店铺动销率与滞销率计算 关键&#xff1a;只要当天任一店铺有任何商品的销量就输出该天的结果&#xff0c;即使店铺901当天的动销率为0。 潜台词&#xff1a;​输出逻辑与店铺901的销售情况无关&#xff0c;只取…

PytorchLightning最佳实践基础篇

PyTorch Lightning&#xff08;简称 PL&#xff09;是一个建立在 PyTorch 之上的高层框架&#xff0c;核心目标是剥离工程代码与研究逻辑&#xff0c;让研究者专注于模型设计和实验思路&#xff0c;而非训练循环、分布式配置、日志管理等重复性工程工作。本文从基础到进阶&…

Apache Flink 实时流处理性能优化实践指南

Apache Flink 实时流处理性能优化实践指南 随着大数据和实时计算需求不断增长&#xff0c;Apache Flink 已经成为主流的流处理引擎。然而&#xff0c;在生产环境中&#xff0c;高并发、大吞吐量和低延迟的业务场景对 Flink 作业的性能提出了更高要求。本文将从原理层面深入解析…

ubuntu上将TempMonitor加入开机自动运行的方法

1.新建一个TempMonitor.sh文件&#xff0c;内容如下&#xff1a;#!/bin/bashcd /fjrobot/ ./TempMonitor &2.执行以下命令chmod x TempMonitor chmod x TempMonitor.sh rm -rf /etc/rc2.d/S56TempMonitor rm -rf /etc/init.d/TempMonitor cp /fjrobot/TempMonitor.sh /etc/…

速卖通自养号测评技术解析:IP、浏览器与风控规避的实战方案

一、速卖通的“春天”来了&#xff0c;卖家如何抓住机会&#xff1f;2025年的夏天&#xff0c;速卖通的风头正劲。从沙特市场跃升为第二大电商平台&#xff0c;到8月大促返佣力度升级&#xff0c;平台对优质商家的扶持政策越来越清晰。但与此同时&#xff0c;竞争也愈发激烈——…

adb: CreateProcessW failed: 系统找不到指定的文件

具体错误 adb devices * daemon not running; starting now at tcp:5037 adb: CreateProcessW failed: 系统找不到指定的文件。 (2) * failed to start daemon adb.exe: failed to check server version: cannot connect to daemon 下载最新的platform-tools-windows 下载最新…

Centos安装HAProxy搭建Mysql高可用集群负载均衡

接上文MYSQL高可用集群搭建–docker https://blog.csdn.net/weixin_43914685/article/details/149647589?spm1001.2014.3001.5501 连接到你搭建的 Percona XtraDB Cluster (PXC) 数据库集群&#xff0c;实现高可用性和负载均衡&#xff0c;建议使用一个中间件来管理这些连接。…

Sql server开挂的OPENJSON

以前一直用sql server2008&#xff0c;自从升级成sql server2019后&#xff0c;用OPENJSON的感觉像开挂&#xff0c;想想以前表作为参数传输时的痛苦&#xff0c;不堪回首。一》不堪回首 为了执行效率&#xff0c;很多时候希望将表作为参数传给数据库的存储过程。存储过程支持自…

【数据结构】队列和栈练习

1.用队列实现栈 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; typedef int QDatatype; typedef struct QueueNode {struct QueueNode *next;QDatatype data; }QNode;typedef struct Queue {QNode* head;QNode* tail;QDatatype size; }Que;typedef struct {Que…

LabVIEW二维码实时识别

​LabVIEW通过机器视觉技术&#xff0c;集成适配硬件构建二维码实时识别系统。通过图像采集、预处理、定位及识别全流程自动化&#xff0c;解决复杂环境下二维码识别效率低、准确率不足问题&#xff0c;满足工业产线追溯、物流分拣等实时识别需求。应用场景适用于工业产线追溯&…

微服务-springcloud-springboot-Skywalking详解(下载安装)

一、SkyWalking核心介绍 1. 什么是SkyWalking&#xff1f; Apache SkyWalking是一款国人主导开发的开源APM&#xff08;应用性能管理&#xff09;系统&#xff0c;2015年由吴晟创建&#xff0c;2017年进入Apache孵化器&#xff0c;2019年毕业成为Apache顶级项目。它通过分布式…

Elasticsearch 字段值过长导致索引报错问题排查与解决经验总结

在最近使用 Elasticsearch 的过程中&#xff0c;我遇到了一个 字段值过长导致索引失败 的问题。经过排查和多次尝试&#xff0c;最终通过设置字段 "index": false 方式解决。本文将从问题现象、排查过程、问题分析、解决方案和建议等方面&#xff0c;详细记录这次踩坑…

使用idea 将一个git分支的部分记录合并到git另一个分支

场景&#xff1a; 有多个版本分支&#xff0c;需要将其中一个分支的某一两次提交合并到指定分支上 eg&#xff1a; 将v1.0.0分支中指定提交记录 合并到 v1.0.1分支中 操作&#xff1a; 步骤一 idea切换项目分支到v1.0.1(需要合并到哪个分支就先站到哪个分支上) 步骤二 在ide…

基于深度学习的图像分类:使用ShuffleNet实现高效分类

前言 图像分类是计算机视觉领域中的一个基础任务&#xff0c;其目标是将输入的图像分配到预定义的类别中。近年来&#xff0c;深度学习技术&#xff0c;尤其是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;在图像分类任务中取得了显著的进展。ShuffleNet是一种轻量级的…

OpenGL里相机的运动控制

相机的核心构造一个是glm::lookAt函数&#xff0c;一个是glm::perspective函数&#xff0c;本文相机的一切运动都在于如何构建相应的参数传入上述两个函数里。glm::mat4 glm::lookAt(glm::vec3 const &eye,//相机所在位置glm::vec3 const &center,//要凝视的点glm::vec…

java设计模式 -【策略模式】

策略模式定义 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为设计模式&#xff0c;允许在运行时选择算法的行为。它将算法封装成独立的类&#xff0c;使得它们可以相互替换&#xff0c;而不影响客户端代码。 核心组成 Context&#xff08;上下文&#xff09;&…

项目重新发布更新缓存问题,Nginx清除缓存更新网页

server {listen 80;server_name your.domain.com; # 替换为你的域名root /usr/share/nginx/html; # 替换为你的项目根目录# 规则1&#xff1a;HTML 文件 - 永不缓存# 这是最关键的一步&#xff0c;确保浏览器总是获取最新的入口文件。location /index.html {add_header Cache-…