RequireJS优化成多个模块 [英] RequireJS optimization into multiple modules
问题描述
我正在尝试使用RequireJS将我们的JS模块化为一些更大的JS文件,以便可以按需加载依赖项,但是在加载页面时不会花费大量的单个JS下载.
例如,JS文件为:
- js/main.js
- js/views/category1/js1.js
- js/views/category1/js2.js
- js/views/category2/js1.js
- js/views/category2/js2.js
应用程序的某些部分(例如,类别1中的所有内容)仅由某些类型的用户使用,并且与类别2类似,因此没有必要为每个用户加载所有内容.
我正在尝试为r.js构建配置,以创建两个动态加载的模块(category1.js和category2.js),其中包含各自js1.js和js2.js文件中的所有代码.
({
appDir: './',
baseUrl: './js',
dir: './dist',
modules: [
{
name: 'main',
exclude: [
"category1",
"category2"
]
},
{
name: "category1",
include: [
"views/category1/js1",
"views/category1/js2"
],
create: true
},
{
name: "category2",
include: [
"views/category2/js1",
"views/category2/js2"
],
create: true
}
],
fileExclusionRegExp: /^(r|build)\.js$/,
writeBuildTxt: false,
optimizeCss: 'standard',
removeCombined: true,
paths: {
jquery: 'lib/jquery',
underscore: 'lib/underscore',
backbone: 'lib/backbone/backbone'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
}
}
})
但是,在加载编译后的输出时,浏览器抱怨无法找到views/category1/js1,views/category1/js2等.
我什至不确定是否可以从RequireJS中的多个较小的JS文件中创建一些高级模块.有没有人对此有任何经验?
编辑
main.js:
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
}
},
paths: {
jquery: 'lib/jquery',
underscore: 'lib/underscore',
backbone: 'lib/backbone/backbone'
}
});
require([
'views/app',
'router'
], function(AppView, Router) {
new Router();
Backbone.history.start();
});
index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script data-main="js/main" src="js/lib/require/require.js"></script>
</head>
<body></body>
</html>
正在从router.js引用JS1,JS2等文件.
执行require(['A'], ...)
或拥有define(['A'], ...
时,RequireJS会检查其配置以解析名称A
,并构建其使用的URL.加载模块A
.它可能会尝试加载类似的内容:
http://localhost/js/A.js
如果优化模块以使A
,B
,C
被包含在名为category1
的捆绑软件中,则可能会发生以下情况:
-
装入捆绑包
category1
,然后发出对A
的请求.这很好,因为在加载category1
时发现了A
. -
该捆绑包尚未加载,但已请求
A
.这是一个问题,因为它将以与不进行优化相同的方式来解析A
.但是这里有一个问题,因为如果您已经优化了模块,那么A
在category1
外部将不再可用(因为removeCombined
是true
).
解决方案是在运行时配置中告诉RequireJS该捆绑包包含您要加载的模块.为此,您可以使用 bundles
选项.例如:
bundles: {
category1: ['A', 'B', 'C']
}
这告诉RequireJS,当您想加载模块A
时,加载category1
并在其中找到它".
请注意,您不必列出捆绑软件中的每个模块.例如,如果您有一个模块X
,并且知道唯一要加载该模块的模块是同一捆绑包的一部分,那么您就无需在bundles
中将其列为模块.>
I am trying to use RequireJS to modularize our JS into a few larger JS files so that dependencies can be loaded on-demand but without the heft of a large single-JS download when loading the page.
As an example, with the JS files as:
- js/main.js
- js/views/category1/js1.js
- js/views/category1/js2.js
- js/views/category2/js1.js
- js/views/category2/js2.js
Some parts of the application (e.g. everything in category1) are only used by certain types of users, and similarly with category2, so it doesn't make sense loading it all for every user.
I'm trying a build config for r.js to create two dynamically loaded modules (category1.js & category2.js) which contain all the code from their respective js1.js and js2.js files.
({
appDir: './',
baseUrl: './js',
dir: './dist',
modules: [
{
name: 'main',
exclude: [
"category1",
"category2"
]
},
{
name: "category1",
include: [
"views/category1/js1",
"views/category1/js2"
],
create: true
},
{
name: "category2",
include: [
"views/category2/js1",
"views/category2/js2"
],
create: true
}
],
fileExclusionRegExp: /^(r|build)\.js$/,
writeBuildTxt: false,
optimizeCss: 'standard',
removeCombined: true,
paths: {
jquery: 'lib/jquery',
underscore: 'lib/underscore',
backbone: 'lib/backbone/backbone'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
}
}
})
However, when loading the compiled output, the browser is complaining that it can't find views/category1/js1, views/category1/js2 and so on.
I'm not even sure it's possible to create a few high-level modules from multiple smaller JS files in RequireJS. Has anyone had any experience with this?
EDIT
main.js:
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
}
},
paths: {
jquery: 'lib/jquery',
underscore: 'lib/underscore',
backbone: 'lib/backbone/backbone'
}
});
require([
'views/app',
'router'
], function(AppView, Router) {
new Router();
Backbone.history.start();
});
index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script data-main="js/main" src="js/lib/require/require.js"></script>
</head>
<body></body>
</html>
The JS1, JS2, etc files are being referenced from router.js.
When you do require(['A'], ...)
or you have a define(['A'], ...
, RequireJS inspects its configuration to resolve the name A
, and builds a URL that it uses to load the module A
. It may try to load something like:
http://localhost/js/A.js
If you optimize your modules so that A
, B
, C
are included in a bundle named category1
, you have the following possibilities:
The bundle
category1
is loaded, and then a request is made forA
. This is fine becauseA
was found whencategory1
was loadded.The bundle is not yet loaded but a request is made for
A
. This is a problem because it will resolveA
in the same way as without optimization. But you've got a problem here because if you've optimized your modules, thenA
is no longer available outsidecategory1
(becauseremoveCombined
istrue
).
The solution is to tell RequireJS in your run time configuration that the bundle contains the modules you want to load. You use the bundles
option for this. For instance:
bundles: {
category1: ['A', 'B', 'C']
}
This tells RequireJS, "when you want to load module A
, load category1
and you'll find it in there".
Note that you don't have to list every single module in the bundle. If you have a module X
for instance, and you know that the only modules that will want to load it are part of the same bundle, then you don't need to list it as a module in bundles
.
这篇关于RequireJS优化成多个模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!