RequireJS优化成多个模块 [英] RequireJS optimization into multiple modules

查看:153
本文介绍了RequireJS优化成多个模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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

如果优化模块以使ABC被包含在名为category1的捆绑软件中,则可能会发生以下情况:

  1. 装入捆绑包category1,然后发出对A的请求.这很好,因为在加载category1时发现了A.

  2. 该捆绑包尚未加载,但已请求A.这是一个问题,因为它将以与不进行优化相同的方式来解析A.但是这里有一个问题,因为如果您已经优化了模块,那么Acategory1外部将不再可用(因为removeCombinedtrue).

解决方案是在运行时配置中告诉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:

  1. The bundle category1 is loaded, and then a request is made for A. This is fine because A was found when category1 was loadded.

  2. The bundle is not yet loaded but a request is made for A. This is a problem because it will resolve A in the same way as without optimization. But you've got a problem here because if you've optimized your modules, then A is no longer available outside category1 (because removeCombined is true).

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆