RrequireJS 优化器和优化后加载动态路径
RrequireJS optimizer and loading dynamic paths after optimization
我有一个带有 requirejs 的 g运行t 任务并且正在 运行 优化器。
我在 运行 时加载了很多并不总是需要的外部文件,通常我只需要少量核心文件。然后根据用户决定,我在 运行 时间内加载某些文件。
例如:
define(["backbone", 'text!data/filePaths.json'],
function(Backbone, filePaths) {
'use strict';
return Backbone.Model.extend({
initialize: function(){
// parse the file paths, there could be a hundred here
this.filePaths = JSON.parse(filePaths);
},
// dynamically add a file via this function call
addFile: function(id){
var self = this;
return new Promise(function(resolve, reject){
// load files dynamically based on the id passed in
require([self.filePaths[id].path], function(View){
resolve(new View());
});
});
}
});
}
);
文件路径 json 可能如下所示:
"ONE": {
"name": "BlueBox",
"path": "views/box/Blue"
},
"TWO": {
"name": "RedBox",
"path": "views/box/Red"
},
etc...
问题是这不适用于我的优化器。
当我 运行 我的应用程序使用优化文件时,我得到:
Uncaught Error: undefined missing views/box/Red
更新:
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
requirejs: {
desktopJS: {
options: {
baseUrl: "public/js/app",
wrap: true,
// Cannot use almond since it does not currently appear to support requireJS's config-map
name: "../libs/almond",
preserveLicenseComments: false,
optimize: "uglify2",
uglify2: {
// mangle: false,
// no_mangle: true,
// stats: true,
// "mangle-props": false,
"max-line-len": 1000,
max_line_length: 1000
},
uglify: {
mangle: false,
no_mangle: true,
stats: true,
"mangle-props": false,
max_line_length: 1000,
beautify: true
},
mainConfigFile: "public/js/app/config/config.js",
include: ["init/DesktopInit"],
out: "public/js/app/init/DesktopInit.min.js"
}
},
desktopCSS: {
options: {
optimizeCss: "standard",
cssIn: "./public/css/desktop.css",
out: "./public/css/desktop.min.css"
}
}
},
注意:如果我使用未优化的版本,一切正常。
这并不是真正的答案,只是一种方式"around"我的应用程序无法正常工作。
我相信唯一可以避免这种情况的方法是使用 include 配置
例如:
requirejs: {
desktopJS: {
options: {
baseUrl: "public/js/app",
wrap: true,
name: "../libs/almond",
optimize: "uglify2",
uglify2: {
"max-line-len": 1000,
max_line_length: 1000
},
mainConfigFile: "public/js/app/config/config.js",
include: ["init/DesktopInit", "views/box/Blue"], // include the file here, all of a sudden the error goes away for that file.
虽然当我有一百个文件时这变得很麻烦。我不想用我所有的文件来构建整个东西,我想要一组优化的文件,以及一堆可以动态需要的其他文件。
优化器无法跟踪 require
调用的依赖关系,这些调用不具有作为字符串文字数组的依赖关系。您的调用是优化器无法处理的 require
调用的示例,因为依赖项列表是在 运行 时间计算的:
require([self.filePaths[id].path], function(View){
原因很简单:优化器在优化模块时不会评估它们。无论如何,self.filePaths[id].path
的可能值的数量可能是无限的,因此优化器无法处理所有情况。因此,当优化器优化您的代码时,应由此 require
调用加载的模块不包含在包中。您在 中提到的一种解决方案是使用 include
来 包括所有可能由该 require
调用加载的模块。
正如您所指出的,如果您可以拥有数百个模块,这意味着将它们全部包含在优化器生成的包中。有其他选择吗?是的,有。
您可以生成一个仅包含应用程序其他模块的包,并将由上面的 require
调用加载的模块单独加载,而不是作为一部分加载 嗯,但是你在问题中显示的具体配置有问题。您有一条评论说您不能使用 Almond。然而,实际上您确实在下一行使用它。 (你的答案中也有。)问题是 Almond 的限制之一是它不进行动态加载。这是 list of restrictions 中的第一个限制。 你必须为此使用全功能的 AMD 加载器,比如 RequireJS 本身。
我有一个带有 requirejs 的 g运行t 任务并且正在 运行 优化器。
我在 运行 时加载了很多并不总是需要的外部文件,通常我只需要少量核心文件。然后根据用户决定,我在 运行 时间内加载某些文件。
例如:
define(["backbone", 'text!data/filePaths.json'],
function(Backbone, filePaths) {
'use strict';
return Backbone.Model.extend({
initialize: function(){
// parse the file paths, there could be a hundred here
this.filePaths = JSON.parse(filePaths);
},
// dynamically add a file via this function call
addFile: function(id){
var self = this;
return new Promise(function(resolve, reject){
// load files dynamically based on the id passed in
require([self.filePaths[id].path], function(View){
resolve(new View());
});
});
}
});
}
);
文件路径 json 可能如下所示:
"ONE": {
"name": "BlueBox",
"path": "views/box/Blue"
},
"TWO": {
"name": "RedBox",
"path": "views/box/Red"
},
etc...
问题是这不适用于我的优化器。
当我 运行 我的应用程序使用优化文件时,我得到:
Uncaught Error: undefined missing views/box/Red
更新:
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
requirejs: {
desktopJS: {
options: {
baseUrl: "public/js/app",
wrap: true,
// Cannot use almond since it does not currently appear to support requireJS's config-map
name: "../libs/almond",
preserveLicenseComments: false,
optimize: "uglify2",
uglify2: {
// mangle: false,
// no_mangle: true,
// stats: true,
// "mangle-props": false,
"max-line-len": 1000,
max_line_length: 1000
},
uglify: {
mangle: false,
no_mangle: true,
stats: true,
"mangle-props": false,
max_line_length: 1000,
beautify: true
},
mainConfigFile: "public/js/app/config/config.js",
include: ["init/DesktopInit"],
out: "public/js/app/init/DesktopInit.min.js"
}
},
desktopCSS: {
options: {
optimizeCss: "standard",
cssIn: "./public/css/desktop.css",
out: "./public/css/desktop.min.css"
}
}
},
注意:如果我使用未优化的版本,一切正常。
这并不是真正的答案,只是一种方式"around"我的应用程序无法正常工作。
我相信唯一可以避免这种情况的方法是使用 include 配置
例如:
requirejs: {
desktopJS: {
options: {
baseUrl: "public/js/app",
wrap: true,
name: "../libs/almond",
optimize: "uglify2",
uglify2: {
"max-line-len": 1000,
max_line_length: 1000
},
mainConfigFile: "public/js/app/config/config.js",
include: ["init/DesktopInit", "views/box/Blue"], // include the file here, all of a sudden the error goes away for that file.
虽然当我有一百个文件时这变得很麻烦。我不想用我所有的文件来构建整个东西,我想要一组优化的文件,以及一堆可以动态需要的其他文件。
优化器无法跟踪 require
调用的依赖关系,这些调用不具有作为字符串文字数组的依赖关系。您的调用是优化器无法处理的 require
调用的示例,因为依赖项列表是在 运行 时间计算的:
require([self.filePaths[id].path], function(View){
原因很简单:优化器在优化模块时不会评估它们。无论如何,self.filePaths[id].path
的可能值的数量可能是无限的,因此优化器无法处理所有情况。因此,当优化器优化您的代码时,应由此 require
调用加载的模块不包含在包中。您在 include
来 包括所有可能由该 require
调用加载的模块。
正如您所指出的,如果您可以拥有数百个模块,这意味着将它们全部包含在优化器生成的包中。有其他选择吗?是的,有。
您可以生成一个仅包含应用程序其他模块的包,并将由上面的 require
调用加载的模块单独加载,而不是作为一部分加载 嗯,但是你在问题中显示的具体配置有问题。您有一条评论说您不能使用 Almond。然而,实际上您确实在下一行使用它。 (你的答案中也有。)问题是 Almond 的限制之一是它不进行动态加载。这是 list of restrictions 中的第一个限制。 你必须为此使用全功能的 AMD 加载器,比如 RequireJS 本身。