RequireJS路径配置

6

我在“index.html”文件中编写了RequireJS的开发配置:

<script src="require-2.1.5.min.js"></script>
<script>
    require.config({
        baseUrl: 'js',
        paths: {
            angular: 'libraries/angular-1.1.5.min',
            jquery: 'libraries/jquery-2.0.0.min',
            underscore: 'libraries/underscore-1.4.4.min',
            ...
            zeroclipboard: 'plugins/zeroclipboard-1.0.7.min',
            tablesorter: 'plugins/jquery.tablesorter-2.9.1.min',
            ...
        },
        shim: {
            'angular': {
                exports: 'angular'
            },
            'underscore': {
                exports: '_'
            }
        },
        packages: [
            {
                name: 'index',
                location: 'app/index',
                main: 'main'
            }
        ]
    });

    require(['index']);
</script>

但是在生产环境中,我只有两个已经合并的文件用于库和插件:
js/libraries.js // all jQuery, AngularJS, RequireJS, Underscore and other libraries concatenated
js/plugins.js // all plugins (already an AMD modules, no need for "shim" config) concatenated

那么,我现在该如何编写我的配置“路径”呢?我没有任何'libraries/angular-1.1.5.min.js'和其他路径。

我的解决方案是编写:

    paths: {
        angular: 'libraries',
        underscore: 'libraries'
    }

我将AngularJS和Underscore库与'libraries.js'文件关联起来,一切运作良好(无需jQuery及其所有插件;它们已经是AMD模块)。
但是这种方式是否正确?我的解决方案似乎有点不够优雅,不是最佳实践的解决方案。
我的r.js构建过程:
({
baseUrl: 'scripts',
paths: {
    jquery: 'jquery-2.0.0.min',
    ...
    tablesorter: 'jquery.tablesorter-2.0.5.min',
    zeroclipboard: 'zeroclipboard-1.0.7.min'
},
name: 'foo/main',
exclude: [
    'angular',
    'jquery',
    ...
    'tablesorter',
    'zeroclipboard'
],
optimize: 'uglify',
out: 'production/js/foo.js'
})

更新1:

我想要的是:

www.mysite.com/about.html:

<script src="js/libraries.js"></script><-- jQuery (already AMD), AngularJS (not AMD), RequireJS, Underscore (not AMD) and other libraries already here, only 1 http request needed //-->
<script src="js/plugins.js"></script><-- all AMD //-->
<script>
    require.config({
        baseUrl: 'js',
        paths: {
            angular: WHAT I NEED TO WRITE HERE?,
            underscore: WHAT I NEED TO WRITE HERE?
        },
        shim: {
            'angular': {
                exports: 'angular'
            },
            'underscore': {
                exports: '_'
            }
        },
        packages: [
            {
                name: 'about',
                location: 'js',
                main: 'about'
            }
        ]
    });

    require(['about']); // will load "js/about.js"
</script>

更新2:

好的,现在“优先级”已经清楚了,所以我不需要第一个和第二个“script”标签(但我需要将“Require.js”与“libraries.js”分开)。RequireJS会自动加载它们。但是对于“libraries.js”文件中的非AMD库应该怎么办呢?

AngularJS和UnderscoreJS都是非AMD模块,这就是为什么我必须使用“shim”的原因,对吧?但是为了让“shim”起作用,我还需要使用“paths”,这样“shim”才能找到被shimmed的模块,对吧?但是我只有一个文件——“libraries.js”,我无法将其写入“path”选项中……真的很困惑……


你不应该添加那些额外的脚本标签,require.js 可以并且应该为你加载它们。我的下面关于优先级选项的回答是否不清楚? - Willem D'Haeseleer
你的回答很好,只是在看到你的更新之前我已经进行了一次更新 :) - artuska
2个回答

5
为了预加载通用库代码,您应该使用优先级配置选项。 您可以在foo/main.js文件中放置类似以下内容的代码。
require.config({
    priority: ["libraries", "plugins"]
});

然后你的构建文件可能会像这样。 libraries和plugins文件应该包含一个定义语句,定义所有被视为常规/下载一次的依赖项。

({
    baseUrl: 'scripts',
    paths: {
        jquery: 'jquery-2.0.0.min',
        ...
        tablesorter: 'jquery.tablesorter-2.0.5.min',
        zeroclipboard: 'zeroclipboard-1.0.7.min'
    },
    modules: [
        {
            name: 'foo/main'
            excludes: ...
        },
        {
            name: 'libraries'
        },
        {
            name: 'plugins'
        }
    ],
    optimize: 'uglify',
    out: 'production/js/foo.js'
})

“这个想法是通过一个文件加载所有必需的引导代码。”例如,我的网站上有3个页面:关于、作品集、联系方式。我用我的模块制作了3个不同的文件(许多“define”模块连接成1个文件):“about.js”,“portfolio.js”,“contacts.js”。第4个文件是“libraries+plugins.js”——因为我希望浏览器缓存此文件并永远不再下载它。我无法将“libraries+plugins.js”代码放入每个“about.js”,“portfolio.js”,“contacts.js”文件中。 - artuska
啊,是的,这很有道理。我认为你需要查看priority配置选项以允许多层输出。http://requirejs.org/docs/1.0/docs/faq-optimization.html#priority - Willem D'Haeseleer
@artuska,我已经编辑了我的问题,以更好地反映在RequireJS中的优先级选项。 - Willem D'Haeseleer

2
你应该在两个环境中使用相同的配置。而且你所拥有的这个配置应该在外部文件中。当你使用r.j进行优化时,所有模块都已经在单个文件中了,因此RequireJS会直接使用它们而不需要加载它们。看起来你需要调整你的构建过程。
请查看我最近关于此的博客文章: Understanding AMD RequireJS

已添加我的r.js构建脚本。即使在您的博客文章之后,我仍然不明白如何在“index.html”文件中保持开发和生产的配置相同。正如您所看到的,我从最终构建中排除了一些文件,将它们放入单独的文件(libraries.js)中,以便浏览器可以缓存它,并且不必为网站上的其他页面再次下载它。“libraries.js”包含AMD模块库(例如jQuery,在其核心中已经是一个AMD模块)和非AMD库(例如AngularJS)。因此,“libraries.js”文件中没有“define”用于AngularJS。 - artuska
也许我应该手动将所有库制作成AMD模块?我的意思是,只需编辑Angular.js文件并将其代码包装在“define('angular',[],function(){...})”函数中? - artuska
我猜这些大模块从构建中排除是有意义的。您可以查看 https://github.com/tnajdek/angular-requirejs-seed 项目,其中将 AngularJS 与 RequireJS 一起使用。 - Tomas Kirda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接