惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
Recorded Future
Recorded Future
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
GbyAI
GbyAI
IT之家
IT之家
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
S
SegmentFault 最新的问题
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
罗磊的独立博客
MongoDB | Blog
MongoDB | Blog
The Cloudflare Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
腾讯CDC
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
aimingoo的专栏
aimingoo的专栏
博客园 - Franky
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
月光博客
月光博客
博客园_首页
C
Check Point Blog
宝玉的分享
宝玉的分享
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Tenable Blog
Vercel News
Vercel News
SecWiki News
SecWiki News
Security Latest
Security Latest
Microsoft Security Blog
Microsoft Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
阮一峰的网络日志
阮一峰的网络日志
Hacker News - Newest:
Hacker News - Newest: "LLM"
Google Online Security Blog
Google Online Security Blog
N
News and Events Feed by Topic
Y
Y Combinator Blog
U
Unit 42
The Register - Security
The Register - Security
云风的 BLOG
云风的 BLOG
K
Kaspersky official blog
WordPress大学
WordPress大学
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
Jina AI
Jina AI

囧克斯

奔四了,写给40岁的自己 有序退网 我和 Vue.js 的十年 我参与《代码之外 Beyond Code》的故事 博客站迁移至 VitePress 的备忘 写给我的奶奶 中文格式化小工具 zhlint 及其开发心得 vue-mark-display:用 markdown 语法轻松撰写幻灯片 我对技术会议的一些看法 VueConf Hangzhou 见闻 第四届 CSSConf CN 见闻 [译]Web 表单的未来 [译]苹果正在做一些他们的程序员明摆着不想要的东西 [译]为什么我不会无偿加班且你也不应该 [译]如果管理是唯一可走的路,那就完蛋了 [译]如何撰写 Git 提交信息 [译]C 程序的原则 Vue 2.0 来了! Weex 近 4 个月的开源之路 Weex 在 JS Runtime 内的多实例管理 我理解的 SPA 我理解的 Flux 架构 【整理】Vue 2.0 自 beta 1 到 beta 4 以来的主要更新 通过一张图走进 Vue 2.0 Code Review for Vue 2.0 Preview Vue 2.0 发布啦! 务实的小而美 Vue.js 1.0.0 发布了! [译]如何成为一名卓越的前端工程师 手机淘宝前端的图片相关工作流程梳理 [译]如何让办公室政治最小化 Vue.js 源码学习笔记 从原型到发布——“团队时间线” 1.0 开发心得 Vue + webpack 项目实践 用 Koa 写服务体验 webcomponents 笔记 之 配置管理 小秀个人的13~14年摄影作品 (共19张) 由今年D2前端论坛想到的 [译]CSS命名神马的真心难 [译]Git 分支的最佳实践 [译]撰写可测试的 JavaScript [译]语义化版本管理 [译]通过HTML5 Canvas API调节图像的亮度和颜色 [译]JavaScript V8性能小贴士 [译]视觉差,走起! [译]Chrome开发者工具中评估性能的五大新特性 精气神儿 细节无微不至,彩屏让人又爱又恨——新老“神机”大对决:Nokia 1050 vs Nokia 1202 秦升拿到红牌之后…… 用Sass重新整理自己的博客主题样式 Connect中间件使用手册 编辑器小调查结果 [译]JSLint 文档 烟火——写给蛇年的傲游和我 小秀个人的全年摄影作品 (共15张) 2012年终毫无正能量的总结 标签?ID?还是CLASS? 微创新=伪创新 HTML5峰会归来 分享bookmarklet一则:随意阅读 国际羽联和中国队之间的恶性循环 ZeroClipboard 学习笔记 “思考人生” 听杨东杰弹吉他 学习精髓 网站装修笔记20120426 网站装修笔记20120414 网站装修笔记20120406 分享Typecho插件:百度统计助手 我的得奖感言 网站装修笔记20120331 用CSS3制作尖角标签按钮样式 分享Typecho插件:Markdown 解析器 + 编辑器 分享Typecho皮肤:我的字很大 汇总自己过去的一些HTML5科普文章 html5中的消息通信简介 + 我的新网站开张 网站装修计划 Typed Arrays 是神马? 文明看球 HTML5中的文件处理 之 File Writer API HTML5中的文件处理 之 File API 独生子女、互相等和不耐烦 IndexedDB技术简介(四) IndexedDB技术简介(三) IndexedDB技术简介(二) IndexedDB技术简介(一) 把博客的字体进一步调大,同时去掉了侧边栏 “模仿别人是为了找到自己” 写给我未婚妻的2011年 写给自己的2011年 手把手教你入门EaselJS做HTML5动画 “吃了吧,不吃就浪费了” 写给傲游的2011年 所谓专业 写给HTML5的2011年 对HTML5中LocalStorage的一些使用建议 回味一下我2011年看到的最过瘾的5场足球比赛 浅浅浅谈开饭店被顾客吃出“异物”的用户体验 前端的本职 继续对Mac穷追猛打 之 修改原生按钮文字大小的技巧
巧用 RequireJS Optimizer 给传统的前端项目打包
勾三股四 · 2013-03-30 · via 囧克斯

r.js 本是 RequireJS 的一个附属产品,支持在 NodeJS、Rhino 等环境下运行 AMD 程序,并且其包含了一个名为 RequireJS Optimizer 的工具,可以为项目完成合并脚本等优化操作。

r.js 的介绍中明确写道它是 RequireJS 项目的一部分,和 RequireJS 协同工作。但我发现,RequireJS Optimizer 提供了丰富的配置参数,可以让我们完全跳出 AMD 和 RequireJS 程序的束缚,为我们的前端程序服务。


RequireJS Optimizer 常规用法 ​

首先,简单介绍一下 RequireJS Optimizer 的“正派”用法 (以 NodeJS 环境为例):

事先写好一个配置文件,比如 config.js,它是 JSON 格式的,常用属性有:

{
    // 程序的根路径
    appDir: "some/path/trunk",
    // 脚本的根路径
    // 相对于程序的根路径
    baseUrl: "./js",
    // 打包输出到的路径
    dir: "../some/path/release",
    // 需要打包合并的js模块,数组形式,可以有多个
    // name 以 baseUrl 为相对路径,无需写 .js 后缀
    // 比如 main 依赖 a 和 b,a 又依赖 c,则 {name: 'main'} 会把 c.js a.js b.js main.js 合并成一个 main.js
    modules: [
        {name: 'main'}
        ...
    ]
    // 通过正则以文件名排除文件/文件夹
    // 比如当前的正则表示排除 .svn、.git 这类的隐藏文件
    fileExclusionRegExp: /^\./
}

然后运行:

node r.js -o config.js

这时 RequireJS Optimizer 就会:

  1. 把配置信息的 modules 下的所有模块建立好完整的依赖关系,再把相应的文件打包合并到 dir 目录
  2. 把所有的 css 文件中,使用 @import 语法的文件自动打包合并到 dir 目录
  3. 把其它文件复制到 dir 目录,比如图片、附件等等

我已经把 RequireJS 和 r.js 整套东西用到了 H5Slides 上。觉得蛮方便的。

不过工作中的前端开发工作并不是绝对理想化的,有些旧的项目,并不是 AMD 的模块化开发方式,而是传统的 js 程序,开发一个页面时可能需要一口气引入三到五个 css 文件、十来个 js 文件…… 上线的时候为了减少流量及 HTTP 请求数又需要把代码尽可能重用和合并。这个时候就需要一个方便快捷的打包工具帮助我们了,下面就介绍一下 RequireJS Optimizer 是如何完成这项工作的。

用到的几个关键参数 ​

说到这里,必须要额外介绍几个 RequireJS Optimizer 的参数了:

modules[i].include ​

modules: [
    {
        name: "main",
        include: ["d", "e"]
    }
]

这里的 include 字段提供了“强制建立依赖关系”的功能,也就是说,即使在 main.js 的代码里没有依赖 d.js 和 e.js,它们也会在合并代码的时候插入到 main.js 的前面

skipModuleInsertion ​

在介绍这个参数之前需要说明的是,RequireJS Optimizer 有一个很智能的功能,就是为没有写明 define(...) 函数的模块代码自动将其放入 define(...) 之中。如果我们写明:

skipModuleInsertion: true

则这种处理将会被取消。

onBuildRead ​

这个参数可以定义一个函数,在处理每个 js 文件之前,会先对文件的文本内容进行预处理。比如下面这个例子里,我会把 main.js 里的代码全部清除:

onBuildRead: function (moduleName, path, contents) {
    if (moduleName === 'main') {
        contents = '/* empty code */';
    }
    return contents;
}

巧妙应用到传统项目 ​

这时,我们的资源已经足够了。比如我现在的项目有:

1 个 html

  • index.html

代码:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Index</title>
        <link rel="stylesheet" href="css/a.css">
        <link rel="stylesheet" href="css/b.css">
    </head>
    <body>

        ...

        <script src="js/a.js"></script>
        <script src="js/b.js"></script>
        <script src="js/c.js"></script>
    </body>
</html>

2 个 css

  • css/a.css
  • css/b.css

3 个 js

  • js/a.js
  • js/b.js
  • js/c.js

1 个图片文件夹

  • images

合并 css 文件 ​

新建一个 css 文件,叫 css/main.css,内容为:

@import url(a.css);
@import url(b.css);

然后把 index.html 中的 2 个 <link> 标签改成一个

<link rel="stylesheet" href="css/main.css">

合并 js 文件 ​

合并 js 文件的步骤略复杂些。首先也是新建一个 js 文件,叫 js/main.js:

document.write('<script src="js/a.js"></script>');
document.write('<script src="js/b.js"></script>');
document.write('<script src="js/c.js"></script>');

然后把 index.html 中的 3 个 <script> 标签改成一个

<script src="js/main.js"></script>

接下来就是配置打包工具的时间了。

禁止自动补齐 define(...) 的头尾 ​

skipModuleInsertion: true

强制建立依赖 ​

modules: [{name: 'main', include: ['a', 'b', 'c']}]

这样打包出来的 main.js 是这样的:

// code from a.js
// code from b.js
// code from c.js
document.write('<script src="js/a.js"></script>');
document.write('<script src="js/b.js"></script>');
document.write('<script src="js/c.js"></script>');

打包时去掉多余的 js/main.js 的代码 ​

onBuildRead: function (moduleName, path, contents) {
    if (moduleName === 'main') {
        contents = '/* empty code */';
    }
    return contents;
}

这样的话,打包工具就会把 document.write(...) 的代码去掉,得到干净的

// code from a.js
// code from b.js
// code from c.js
/* empty code */

运行 node r.js -o config.js 就可以得到一个打包成功的项目了,并且打包前后的代码都可以正常运行

附件是这个项目例子的源代码:project.zip