requirejs:杏仁的优化(almond)

简介:

这里只是调侃一下,“杏仁”其实指的是almond,requirejs作者的另一个开源项目,它的定位是作为requirejs的一个替代品。

本文概要

1. 使用场景
2. 打包例子:未使用almond
3. 打包例子:使用almond
4. 如何暴露公共API
5. 限制 & 支持的特性
6. 写在后面 & demo下载

 

使用场景

什么情况下需要使用almond呢?假设你手头有个基于requirejs的小项目,所有业务代码加起来就几十K(压缩后可能更小).出于性能优化的考虑,你可能在想:如果能够去掉requirejs的依赖就好了,毕竟,gzip后的requirejs还有大概20k(2.1.6版本)。

almond就是为了这个目的而诞生的,开发过程,你可以照常使用requirejs来管理你的依赖,而到了打包上线阶段,替换成almond就行了。gzip后的almond只有大约1k,优化幅度相当大。

例子:未使用almond

这一小节主要举个requirejs+r.js打包的例子,下一小杰会在本小节的基础上,通过almond进行进一步的优化。代码很简单,扫一下就可以了
目录结构如下:

demo.html
build.js
js/
js/main.js
js/cookie.js
js/util.js

demo.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo</title>
</head>
<body>
<h1>简单的requirejs例子 - almond</h1>
<script type="text/javascript" src="js/require.js" data-main="js/main-built.js"></script>
<!-- <script type="text/javascript" src="js/main-almond-built.js"></script> -->
</body>
</html>

js/main.js

requirejs.config({
    baseUrl: 'js'
});
require(['cookie', 'util'], function(Cookie, Util){
    Cookie.say('hello');
    Util.say('hello');
});

js/cookie.js

define([], function(){
    return {
        say: function(msg){
            alert('cookie: '+msg);
        }
    };
});

js/util.js

define([], function(){
    return {
        say: function(msg){
            alert('util: '+msg);
        }
    };
});

用r.js打包

首先,在build.js里声明打包的配置

({
    baseUrl: "js", name: "main", optimize: "none", out: "js/main-built.js" })

然后,下载打包工具r.js

npm install -g requirejs

最后,通过r.js打包

r.js -o build.js

恭喜!可以看到js目录下生成了打包后的文件main-built.js

js/main-built.js


define('cookie',[], function(){
    return {
        say: function(msg){
            alert('cookie: '+msg);
        }
    };
});
define('util',[], function(){
    return {
        say: function(msg){
            alert('util: '+msg);
        }
    };
});
requirejs.config({
    baseUrl: 'js'
});
require(['cookie', 'util'], function(Cookie, Util){
    Cookie.say('hello');
    Util.say('hello');
});

define("main", function(){});

运行demo

为了检验打包后的结果是运行的,我们需要到浏览器里验证一下。首先我们要把demo.html里的资源引用修改下

<script type="text/javascript" src="js/require.js" data-main="js/main-built.js"></script>

在浏览器里打开demo.html,看到下面的弹窗,搞定

Alt text

例子:使用了almond

我们看到,上面的例子打包后生成了main-built.js,gzip后看下文件多大

gzip main-built.js

可以看到只有174B,这种情况下,在页面中引用requirejs有点不划算,这个时候我们就要引入almond了

-rw-r--r-- 1 user staff 174B 4 20 22:03 main-built.js.gz

很简单,首先下载almond,并放置到js目录下

然后,运行下面命令,通过r.js + almond生成打包后的文件main-almond-built.js

r.js -o baseUrl=js name=almond include=main out=js/main-almond-built.js wrap=true optimize=none

js/main-almond-built.js

/**
 * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/jrburke/almond for details
 */
// almond的代码篇幅略长,这里略过...

define("cookie",[],function(){return{say:function(e){alert("cookie: "+e)}}}),define("util",[],function(){return{say:function(e){alert("util: "+e)}}}),requirejs.config({baseUrl:"js"}),require(["cookie","util"],function(e,t){e.say("hello"),t.say("hello")}),define("main",function(){});

同样,在修改修改main.js的链接后,在浏览器里访问demo.html,done!

<script type="text/javascript" src="js/main-almond-built.js"></script>

Alt text

看下gzip后的main-almond-built.js多大,只有1.6k!

-rw-r--r--  1 user  staff   1.6K  4 20 22:34 main-almond-built.js.gz

通过配置文件打包

上面打包的命令行有点长,对于楼主这样对命令行有恐惧症的人来说,还是比较习惯写个配置文件,命令行则越简短越好

build-almond.js

({
    baseUrl: "js", name: "almond", include: "main", out: "js/main-almond-built.js", wrap: true })

接下来就很简单了,很短的一行命令

r.js -o build-almond.js

暴露公共API

上面的例子,如果没有加上wrap: true这个选项,打包后生成的文件,你是可以访问到之前的定义的模块的,比截图所

Alt text

但加上wrap: true后就完全不一样了,因为所有的代码都会被包在一个匿名的闭包里,大致如下

(function () {
    //almond will be here
    //main and its nested dependencies will be here
}());

此时就访问不到之前定义的模块了,包括require都成了匿名函数里的一个局部变量
Alt text

这种情况下,如果我们想要访问模块里的方法,该怎么做呢?可以修改下配置文件

build-almond-frag.js

({
    baseUrl: "js", name: "almond", include: "main", out: 'js/main-built-almond-public.js', wrap: { startFile: 'js/start.frag.js', endFile: 'js/end.frag.js' }
})

js/start.frag.js

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define([], factory);
    } else {
        root.Main = factory();
    }
}(this, function () {
    //almond, and your modules will be inlined here

js/end.frag.js

    return {
        cookie: require('cookie'), util: require('util') };
}));

打包

r.js -o build-almond-frag.js

生成的文件结构如下

start.frag
almond.js
modules for your lib, including 'main'
end.frag

现在,可以在浏览器里继访问我们暴露的API了
Alt text

一些限制 & 支持的特性

毫无意外,almond只是支持了requirejs功能的子集,所以,在使用前需要了解下它的支持哪些特性,有哪些限制。

限制:

  • 需要将所有的模块打包成一个文件
  • 不支持模块动态加载
  • 只能调用一次requirejs.config()(原来可以调用两次??)
  • 不能通过var require = {};传递配置参数
  • 不支持多版本/上下文
  • 不要使用require.toUrl()require.nameToUrl()
  • (不了解packages,直接附上原文了)

    do not use packages/packagePaths config. If you need to use packages that have a main property, volo can create an adapter module so that it can work without this config. Use the amdify add command to add the dependency to your project.

支持的特性

  • 使用相对路径的依赖(dependencies with relative IDs.)
  • define('id', {}) definitions.(不知道肿么翻译)
  • define(), require() and requirejs() 调用。
  • 符合这样特性的插件:能够将资源内联进打包优化后的文件,并通过同步的方式访问内联后的资源。比如text插件CoffeeScript插件

写在后面

本文简单介绍了下如何通过almond对依赖requirejs的项目进行进一步的优化。当然,almond也存在着一些限制,比如无法动态加载模块、只能将模块打包成一个文件等,具体的可以参考这里。是否在打包阶段使用almond替代requirejs,得看具体场景,这里就不展开,后面有时间再简单介绍下。

相关文章
|
6月前
|
数据采集 前端开发 JavaScript
我是如何使用 Next.js14 + Tailwindcss 重构个人项目的
这篇文章介绍了作者在学习React和Nest时受到大佬imsyy项目DailyHot的启发,基于React开发了一个项目,并因为这个项目获得了少量流量而进行了优化。作者随后因为想要优化SEO和深入学习Next.js14,决定重构这个项目。文章详细介绍了项目的信息、特性、演示图、运行环境、Vercel本地部署步骤以及责任声明。作者还感谢了为本项目提供支持与灵感的项目,并承诺会记录下开发过程中遇到的问题及解决方法以帮助他人。
我是如何使用 Next.js14 + Tailwindcss 重构个人项目的
|
4月前
|
前端开发 JavaScript 开发工具
使用RequireJS和Bower优化前端资源管理和模块化开发
【7月更文挑战第7天】随着Web应用的复杂度日益增长,前端资源管理和模块化开发变得尤为重要。RequireJS和Bower是两个流行的前端开发工具,它们分别解决了JavaScript模块化加载和前端包依赖管理的问题,极大地提升了开发效率和代码质量。
64 3
|
4月前
|
缓存 监控 JavaScript
常见的JS优化方案都有那些
【7月更文挑战第7天】 JavaScript优化包括代码优化(箭头函数、解构赋值、模板字面量、展开运算符、高阶函数)、DOM操作优化(减少操作、事件委托、节流防抖)、异步优化(Promise、Web Workers)、缓存策略(结果缓存、HTTP缓存)、压缩合并以及性能分析和监控。通过这些方法,提升网页性能和用户体验。
29 1
|
4月前
|
JavaScript 前端开发
前端 JS 经典:Vite 打包优化
前端 JS 经典:Vite 打包优化
229 0
|
6月前
|
缓存 JavaScript 前端开发
前端工程化:优化JS加载速度
在现代Web应用中,JavaScript已成为必不可少的一部分,但是随着业务复杂度的增加,JS文件的体积也越来越大,导致网页加载速度变慢,影响用户体验。本文将介绍前端工程化的优化策略,以提高JS文件的加载速度。
81 2
|
Web App开发 前端开发 JavaScript
UMD 被淘汰了吗?不考虑的 UMD 的库如何在纯 UMD 前端项目中运行?
UMD 被淘汰了吗?不考虑的 UMD 的库如何在纯 UMD 前端项目中运行?
225 0
|
JavaScript 前端开发 Java
服从AMD规范的require.js库的学习
服从AMD规范的require.js库的学习
141 0
|
资源调度 前端开发 JavaScript
前端编译速度优化——ESbuild
本文旨在说明使用ESbuild提升前端编译构建的速度,降低前端编译的CPU开销
700 0
前端编译速度优化——ESbuild
|
JavaScript 前端开发
前端优化系列 - JS混淆引入性能天坑
现在前端渲染变得越来越普遍。前端渲染主要依赖JS去完成核心逻辑,JS正变得越来越重要。本文详细谈谈JS混淆对性能的影响。
4204 0
|
JavaScript 前端开发 应用服务中间件