2

在开发使用 Webpack 管理 JavaScript 依赖项的 Web 应用程序时,我偶然发现了我将要描述的问题。

加载传递字符串的依赖项require()可以很好地工作:

// main.js
var jQuery = require('jquery');

在这里,jquery安装了 Bower,并且正确配置了 Webpack 以自动解析 Bower 模块。

现在,我正在研究有条件地加载模块的问题,特别是关于必须从 CDN 下载模块的情况,或者如果 CDN 失败则从本地服务器下载模块的情况。顺便说一下,我scriptjs习惯从 CDN 异步加载。我正在编写的代码是这样的:

var jQuery = undefined;
try {
  jQuery = require('jquery-cdn');
} catch (e) {
  console.log('Unable to load jQuery from CDN. Loading local version...');
  require('script!jquery');
  jQuery = window.jQuery;
}

// jQuery available here

这段代码也很漂亮。

现在,由于我显然有很多依赖项(Handlebars、Ember 等)我想首先尝试从 CDN 加载,所以这段代码开始变得有点多余,所以我尝试做的最合乎逻辑的事情是将其重构为一个函数:

function loadModule(module, object) {
  var lib = undefined;
  try {
    lib = require(module + '-cdn');
  } catch (e) {
    console.log('Cannot load ' + object + ' from CDN. Loading local version...');
    require('script!' + module);
    lib = window[object];
  }
  return lib;
}

var jQuery = loadModule('jquery', 'jQuery');
var Handlebars = loadModule('handlebars', 'Handlebars');
// etc...

问题是 Webpack在处理语句中的表达式时有一种特殊的 行为require,这阻碍了我以上述方式加载模块的尝试。特别是,当在其中使用表达式require

尝试包含您的表达式可能的所有文件

当我尝试使用上面的代码运行 Webpack 时,最终结果是一堆错误消息。

虽然链接的资源建议明确声明要包含的 JavaScript 文件的路径,但我没有得到的是当我不能或不想传递精确路径时如何做同样的事情require,而是使用自动解析模块,如图所示。

谢谢大家

编辑:

我仍然不知道如何使用表达式来加载这些脚本,但是,我设计了一个解决方法。基本上,这个想法是在require('script')内部显式地编写一个回调函数,然后在适当的时候动态地调用该函数。更准确地说,我准备了一个这样的配置文件:

// config.js
'use strict';
module.exports = {
  'lib': {
    'jquery': {
      'object': 'jQuery',
      'dev': function() { require('script!jquery'); },
      'dist': function() { return require('jquery-cdn'); },
      'cdn': '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'
    },
    'handlebars': {
      // ...
    }
  }
};

然后,在我的主代码中,我定义了一个要加载的资源数组,例如:

var config = require('./config.js');
var resources = [ config.lib.jquery, config.lib.handlebars, ... ];

然后当我必须加载开发版本或分发版本时,我通常会调用:

// Inside some kind of cycle
// resource = resources[index]
try {
  window[resource.object] = resource.dist();
} catch (e) {
  console.log('Cannot load ' + resource.object + ' from CDN. Loading local version...');
  resource.dev();
}

这里有一个更完整的例子。

4

0 回答 0