游乐游手机版
首页/前端开发/文章详情

全面浅析SeaJS模块定义与加载机制和原理教程

时间:2026-06-10 06:56
SeaJS是遵循CommonJS规范的模块加载器,核心功能包括模块定义(define)与模块加载(use)及依赖管理。通过define定义模块、exports暴露接口,use加载模块,require建立依赖关系。该工具仅4K大小,能有效解决大量脚本引用带来的维护和HTTP请求问题。

SeaJS 是由玉伯开发的一款严格遵循 CommonJS 规范的模块加载器,主要用于高效、干净地加载 JavaScript 模块和 CSS 样式文件。这个工具体积极小——压缩并经过 gzip 处理后仅 4KB,提供的接口和方法也极为精简:核心功能只有模块定义、模块加载以及依赖管理。然而,它功能强大,能够确保在使用某个模块时,所有依赖模块已经稳定加载到环境中。玉伯曾非常务实地说过:SeaJS 能让你真正享受编码的乐趣,再也不用为脚本加载顺序而烦恼。

说实话,你现在还在一个页面里一口气引用几十个 JS 和 CSS 文件吗?我统计过自己公司网站的个人主页首页,竟然引用了多达 39 个 CSS 和 JS 文件。这带来的问题显而易见:

seaJs的模块定义和模块加载浅析

  1. 维护成本急剧上升,前端和后端都感到头疼。
  2. HTTP 请求数量过多——虽然可以用合并工具解决,但如果没有后端支持,人工成本很高;即使后端帮助合并,那么长的路径字符串也让人眼花缭乱。

SeaJS 正是解决这些痛点的理想工具。

模块的定义 define

定义一个模块非常简单。例如,创建一个 sayHello.js 文件:

复制代码 代码如下:

define(function(require, exports, module) {
  exports.sayHello = function(eleID, text) {
    document.getElementById(eleID).innerHTML = text;
  };
});

这里需要重点关注 exports 参数,它是模块对外暴露 API 的通道。其他模块通过 exports.sayHello 即可调用到该方法。

模块的加载 use

如果页面上有一个 id 为 out 的元素,想要输出 "Hello SeaJS!",操作步骤如下:

  1. 先引入 sea.js
  2. 使用 seajs.use 加载 sayHello 模块:

复制代码 代码如下:

seajs.use("sayHello/sayHello", function(say) {
  say.sayHello("out", "Hello SeaJS!");
});

seajs.use 是加载模块的核心方法:

  • 第一个参数是模块标识,路径相对于 sea.js 所在位置,.js 后缀可以省略。当然,模块标识还有多种写法,具体可参考官方文档(https://seajs.com/docs/zh-cn/module-identifier.html)。
  • 第二个参数为回调函数,参数 say 即加载进来的 sayHello 模块。通过 say.sayHello() 调用模块暴露的方法。

模块的依赖关系

模块之间的依赖关系应该在定义时就规划清楚。比如将上面的 sayHello 模块改造一下——假设我们已经有一个通用的 DOM 工具模块(包含获取元素、设置样式等常用方法),例如这样的 DOM.js

复制代码 代码如下:

define(function(require, exports, module) {
    var DOM = {
        /**
         * 通过元素的id属性获取DOM对象,参数为字符串,或多个字符串
         * @id getById
         * @method getById
         * @param {String} id the id attribute
         * @return {HTMLElement | Object} The HTMLElement with the id, or null if none found.
         */
        getById: function() {
            var els = [];
            for (var i = 0; i < arguments.length; i++) {
                var el = arguments[i];
                if (typeof el == "string") {
                    el = document.getElementById(el);
                }
                if (arguments.length == 1) {
                    return el;
                }
                els.push(el);
            }
            return els;
        },
        /**
         * get 获取对象,可以传入对象或字符串,如果传入字符串则以document.getElementById()的方式获取对象
         * @id get
         * @param {String} el html element
         * @return {Object} HTMLElement object.
         */
        get: function(el) {
            if (el & (el.tagName || el.item)) {
                return el;
            }
            return this.getById(el);
        }
    };
    return DOM;
});

那么 sayHelloA 模块可以这样编写(新建 sayHelloA.js):

复制代码 代码如下:

define(function(require, exports, module) {
    var DOM = require("DOM/DOM");
    require("sayHelloA/sayHello.css");
    exports.sayHello = function(eleID, text) {
        DOM.get(eleID).innerHTML = text;
    };
});

require 函数的作用就是建立模块之间的依赖关系。上面的 sayHelloA 依赖于 DOM 模块(因为用到了 DOM.get),通过 var DOM = require("DOM/DOM") 加载并赋值;require("sayHelloA/sayHello.css") 则直接引入了 CSS 文件——这样页面就会自动加载该样式。

最近我一直在深入研究 SeaJS,越是深入了解就越喜欢它。感谢玉伯!当然,你可能会觉得这些简单的示例没必要大费周章。确实,项目规模小、JS 文件少的时候,模块化的优势不那么明显;但一旦文件数量增加,或者项目达到中型以上规模,模块化带来的清晰结构与良好的可维护性就会充分体现出来。

来源:https://www.jb51.net/article/50750.htm
上一篇详解SeaJS模块解析规则与使用总结 下一篇深入解析Seajs模块化与加载机制
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
HTML文档版权声明结构与基础脚手架代码质量解析
前端开发 · 2026-07-07

HTML文档版权声明结构与基础脚手架代码质量解析

版权声明需用语义化``标签,©符号使用`©`实体;年份通过服务端、构建或JS分层兜底;`rel= "license "`仅指向真实许可证文件才有效。

基于HTML模板的组件化全栈交互方案
前端开发 · 2026-07-07

基于HTML模板的组件化全栈交互方案

纯HTML模板仅作静态结构,全栈交互需后端注入数据、前端JS激活模板及用户事件触发双向链路。``标签惰性,不执行脚本或加载资源,需通过克隆填充数据并手动绑定事件实现交互,父子传值依赖JS对象与自定义事件。

Bootstrap修改Badge徽章边框为圆点样式的方法
前端开发 · 2026-07-07

Bootstrap修改Badge徽章边框为圆点样式的方法

将BootstrapBadge改为圆点:自定义类设置等宽高、border-radius:50%、padding:0、font-size:0;Bootstrap5 2+需加display:inline-block;注意垂直对齐,避免min-width干扰,背景色用background-color更可控。

Bootstrap响应式多栏Footer社交图标排版实现
前端开发 · 2026-07-07

Bootstrap响应式多栏Footer社交图标排版实现

使用Bootstrap5的grid系统实现响应式多栏Footer,按断点设置列宽;以FontAwesome处理社交图标,避免使用img;利用list-unstyled组织链接列表;借助flex-column容器配合mt-auto使版权行自动贴底,避免fixed-bottom固定定位的弊端。

如何用Shadow DOM隔离组件内外事件分发
前端开发 · 2026-07-07

如何用Shadow DOM隔离组件内外事件分发

ShadowDOM内部事件默认不穿透影子边界,需显式设置composed:true才能被外部监听。此时event target指向宿主元素,真实触发源需通过event composedPath()[0]获取。原生事件手动派发时也必须声明composed:true。应避免在宿主上依赖event target做逻辑分支,建议在shadowroot内绑定事件或使用