如何利用Require.Js管理多页面站点文件(译)
英文版地址
最近使用 Require.Js 的时候我发现它确实是一个改善代码管理的一个好方法。我以前发表Backbone类的文章时曾提到过 Require,但此前,我从未在传统的多页面网站内使用到 Require。在多页面网站里面配置 Require 的过程相当繁琐,所以我想将教程整理出来帮助那些可能会遇到困惑的朋友们。
概述
注意,本文假设你已经熟悉 Require.Js 和基本的配置使用方法,如果不是,建议你先看看官网的手册。
创建一个单页应用 (single-page App) 时,许多人喜欢在发布之前把所有的js文件全部打包编译为一个文件,可以减少断断续续的 http 请求,操作体验简洁明快更像 app,同样的,这种做法增加了首次加载时页面的量级。
部署多页面站点的时候,编译合并所有文件并非一个好方案,因为你不能保证用户会访问到每一个页面,而且加载中的文件会有很多用不到的js,这拖慢了页面渲染速度,用户体验变差。比如说,用户只是访问了Contact页面,那么有必要把About页面要用到的js给加载一遍吗?
完美的情景是每一个页面都有自己的 main 文件用来存放特定页面的方法,外加一个独立文件(最好是缓存起来)用来存放公共 Javascript 库。
例如,你有一个About页面和一个 Contact 页面,于是你新建一个 mian-about.js 和一个 main-contact.js,而且假设 mian-about 和 main-contact 都需要 jQuery 和 underscore。这时,不建议把 jQuery 和 underscore 编译到每一个 main 文件里面,那样会造成不必要的重复和臃肿,我们只用新建一个包含 jQuery 和 underscore 的 common.js 并且保证它在 mian-*.js 文件之前加载就可以了。下表可以加深理解:
common.js
----------------
js/vendor/jquery.js
js/vendor/underscore.js
About
----------------
js/common.js
js/app/main-about.js
Contact
----------------
js/common.js
js/app/main-contact.js
将那些公用的 js 文件编译合并到 common.js 后减少了每个页面的 http 请求,而且,第一个页面加载完毕,common.js 就可以从浏览器缓存里直接读取了。下面我们再来看一个例子。
例子
RequireJS 的作者 James Burke,做了很多有效组织代码,利用 RequireJS Optimizer 压缩优化代码的努力,有些例子是我经常提到的:example-multipage-shim.,example-multipage。但我更喜欢用 shim 版本(它支持非 AMD 方式定义的模块载入)的 RequireJS,因为一个项目里面似乎总有几个非 AMD 的脚本文件。
如果你在用RequireJs创建一个单页站点,那么你可能会这样定义你的script标签:
<!--This sets the baseUrl to the "scripts" directory, and
loads a script that will have a module ID of 'main'-->
<script data-main="scripts/main.js" src="scripts/require.js"></script>
data-main 属性可以很方便的用来设置 RequireJs 的 baseUrl property,通常,你也可以在 main.js 里面加上一些配置,比如,你要加载一个第三方的js库,你要创建一个路径以便引用。因为模板里的每一个单页的 mian-* 文件都不同,所以,我们可以把配置信息放在 common.js 里:
//The build will inline common dependencies into this file.
requirejs.config({
baseUrl: './js',
paths: {
'jquery': 'vendor/jquery',
'bootstrap': 'vendor/bootstrap'
},
shim: {
'bootstrap': ['jquery']
}
});
除了 common.js,我还在 app/models 下创建了BasicModel文件以表明common.js是公用的,并把BasicModel放进common.js里。
编译
编译之前需要有一个 option.js 来指定哪些文件需要编译,哪些不需要:
module.exports = {
appDir: 'www',
baseUrl: 'js/',
mainConfigFile: 'www/js/common.js',
dir: 'www-release',
modules: [
{
name: 'common',
include: [
'app/models/basicModel',
'jquery',
'bootstrap'
]
},
{
name: 'app/main-about',
exclude: ['common']
},
{
name: 'app/main-contact',
exclude: ['common']
}
]
};
上面的代码中,首先把所有的文件用 include 方法包含进来,然后把不需要的文件用 exclude 方法排除出去。RequireJs 会根据 exclude 的参数配置理出嵌套依赖关系并把文件排除掉。因为 bootstrap 已经编译合并进 common.js 了,所以不需要单独为 main-about 或 main-contact 再 exclude 掉 bootstrap。
在执行这些操作之前,你需要执行一个 npm 安装。首先你要确保安装了 grunt 工具,安装完成后执行 grunt 命令压缩打包。如果打包顺利完成,会在www-release/build.txt 里看到如下被打包的文件清单:
css/bootstrap-responsive.css
----------------
css/bootstrap-responsive.css css/bootstrap.css
----------------
css/bootstrap.css css/style.css
----------------
css/style.css js/common.js
----------------
js/common.js
js/app/models/basicModel.js
js/vendor/bootstrap.js js/app/main-about.js
----------------
js/app/models/aboutModel.js
js/app/main-about.js js/app/main-contact.js
----------------
js/app/models/contactModel.js
js/app/main-contact.js
www-release/common.js 里面试一大块压缩后的代码,代码里就包含了 BasicModel, Bootstrap, jQuery, and 初始配置代码。要配置 about.html ,只需要按下面的顺序加载文件即可:
<script src="./js/vendor/require.js"></script>
<script type="text/javascript">
// Load common code that includes config,
// then load the app logic for this page.
require(['./js/common'], function (common) {
// ./js/common.js sets the baseUrl to be ./js/
// You can ask for 'app/main-about' here instead
// of './js/app/main-about'
require(['app/main-about']);
});
</script>
通过层层引入 RequireJs --> common.js --> main-about.js 实现了明晰简便的代码管理方式。
谢谢。
前端技术文章翻译QQ群:338353879
如何利用Require.Js管理多页面站点文件(译)的更多相关文章
- 利用require.js实现javascript模块化加载
这种引入很看到很想死吧! <script src="1.js"></script> <script src="2.js">& ...
- require.js使用baseUrl + paths导入文件配置的3种方法
//main.js requirejs.config({ baseUrl: 'lib/js',//参照于引入这个js文件的index.html页面的相对路径,因为此时mian.js文件已经导入到了in ...
- 利用zepto.js实现移动页面图片全屏滑动
HTML <%-- Created by IntelliJ IDEA. User: fanso2o Date: 2017/2/28 Time: 16:09 To change this temp ...
- javascript模块化编程库require.js的用法
随着javascript的兴起,越来越多的公司开始将JS模块化,以增加开发的效率和减少重复编写代码的.更是为了能更加容易的维护日后的代码,因为现在的随着人们对交互效果的越来越强烈的需求,我们的JS代码 ...
- 对require.js 的使用进行总结
一.为什么要使用require.js 首先一个页面如果在加载多个js文件的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长:其次,由于js文件之间存在依赖关系,因此必须严格保证加载 ...
- js模块化开发——require.js的用法详细介绍(含jsonp)
RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签脚本加载步骤.可以用它回事.优化代码,但其主要的目的还是为了代码的模块化.它鼓励在使用脚本以moudle ...
- 【前端】Require.js使用方法总结
一.为什么要使用require.js 首先一个页面如果在加载多个js文件的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长:其次,由于js文件之间存在依赖关系,因此必须严格保证加载 ...
- require.js 简洁入门
原文地址:http://blog.sae.sina.com.cn/archives/4382 前言 提到require.js大多数人会说提到模块化开发,AMD等等,其实require.js并没有这么多 ...
- 【实践】require.js + r.js 代码打包压缩初体验
第二个分享的是学校项目所接触到的新知识,代码压缩 + 代码打包 这次的项目用了require.js 这个插件做模块化管理的工具,所谓模块化就是在开发的过程中将功能划分成一个独立的模块,使代码可读性更强 ...
随机推荐
- linux下常用的日志分析命令【转】
形如下面这样的access.log日志内容: 211.123.23.133 – - [10/Dec/2010:09:31:17 +0800] “GET /query/trendxml/district ...
- javascript 实现 接口编程
// Constructor. var Interface = function (name, methods) { if (arguments.length != 2) { throw new Er ...
- Math.ceil()、floor()、round()
ceil():向上取整,>=某个小数的最小整数,即15.3取16.返回double类型 如果参数小于0且大于-1.0,结果为 -0. floor():向下取整,<=某个小数的最大整数,即1 ...
- LeetCode OJ-- Text Justification
https://oj.leetcode.com/problems/text-justification/ 细节题 class Solution { public: vector<string&g ...
- LeetCode OJ-- Container With Most Water
https://oj.leetcode.com/problems/container-with-most-water/ 不同高度的柱子排一列,两个柱子可以组成一个容器,求最大容积. 最直观的方法就是暴 ...
- 2017 ACM-ICPC EC-Final 记录
北京赛区结束后就以为自己的赛季结束了……但是还是保持着做题量 那天突然接到通知,去打EC-Final 但是这是一个临时组起来的队伍,另外两位队友原来一起组的比较熟,我就需要适应一下. 于是我们临时训练 ...
- Codeforces 371B Fox Dividing Cheese(简单数论)
题目链接 Fox Dividing Cheese 思路:求出两个数a和b的最大公约数g,然后求出a/g,b/g,分别记为c和d. 然后考虑c和d,若c或d中存在不为2,3,5的质因子,则直接输出-1( ...
- 搞懂ZooKeeper的Watcher之源码分析及特性总结
前言 本章讲ZooKeeper重要的机制,Watcher特性.ZooKeeper允许客户端向服务端注册Watcher监听,当服务端一些指定事件触发了这个Watcher,那么就会向指定客户端发送一个事件 ...
- 基于http的断点续传和多线程下载
HTTP协议的GET方法,支持只请求某个资源的某一部分: 206 Partial Content 部分内容响应: Range 请求的资源范围: Content-Range 响应的资源范围: 断点续传: ...
- “应用程序无法正常启动(oxc000007b)”解决方案