试图理解 pathMappings

Trying to understand pathMappings

我有一个 Polymer 项目,我正在使用

的(部分)结构
app/
app/elements/my-element/my-element.html
bower_components/

编写 my-element.html 代码时,我希望它的 html 导入引用 url 形式的 ../polymer/polymer.html。这意味着我需要将 app/elements 和 bower_components 映射到相同的 url (如果它们存在,则优先映射到 app/elements ,否则它应该回退到寻找在 bower_components 目录中为他们提供。

我已尝试设置我的 wct-conf.js 文件来执行此操作。经过大量调试调试后,我想到了这一点,我认为可以做到,

var ret = {
  'suites': ['app/elements/**/test'],
  'plugins': ['local'],
  'webserver': {

    'pathMappings': [
      {'/components/<basename>/components': 'app/elements'},
      {'/components/<basename>/components': 'bower_components'},
      {'/components/<basename>/api': 'server/mock/fake.js'},
      {'/components/<basename>':'app'}
    ]
  }
};

module.exports = ret;

但是一旦我 运行 gulp test:local 到 运行 他们,我就会收到一大堆奇怪的 url 报告 404。他们是这样的

404 GET /components/pasv5/app/elements/bower_components/webcomponentsjs/webcomponents.min.js
404 GET /components/pasv5/app/elements/bower_components/test-fixture/test-fixture-mocha.js
404 GET /components/pasv5/app/elements/bower_components/test-fixture/test-fixture-mocha.js

它以某种奇怪的方式成功地合并了 app/elementsbower_components

我做错了什么,我应该怎么做?

我现在找到了答案。有两种可能的方法,但首先让我解释一下我对 pathMappings 的发现。

首先,虽然是url到文件偏移量的映射数组,但不是简单的数组。每个数组元素实际上是一个对象,我有很多键,每个键都是一个可能的 url 前缀,并且该键的每个值都是一个路径,相对于该键代表的项目根目录。 Web 组件测试器使用一个名为 serve-waterfall 的节点模块,它实际上定义了一些自己的条目,特别是:-

  WEB_COMPONENT: [
    {'/components/<basename>': '.'},
    {'/components': 'bower_components'},
    {'/components': '..'},
    {'/': '.'},
  ],

在配置阶段,您通过 wct-conf.js 中的模块导出提供的任何数组(您可以在主目录或项目根目录或两者中找到此文件)与上面的列表合并使用您提供的键扩充同一数组索引中的对象。

最后,Web Component Tester 添加了自己的路径:-

{'/components': path.join(WCT_ROOT, 'bower_components')},

其中 WCT_ROOT 是 WCT 在您的 node_modules 目录中的位置,尽管它在末尾被推入数组。这确保了 mocha、chai 和 sinon 可用于测试。

一旦构建了 pathMappings,它们就会被展平成一个 "waterfall" 数组,因此数组每个索引中的每个键都变成一个具有两个键的对象,prefixtarget,这个瀑布数组很重要,因为它是有序的。因此,如何将 pathMappings 的各种来源合并在一起也很重要,这可能比判断更幸运。

Web 组件测试启动一个 Express Web 服务器,服务器根目录位于项目根目录。

当 Web 服务器是 运行 时,并且当有一个 url 时,web-component-tester 单独负责(例如 web runner 组件),这由app.get() 调用。如果它没有被捕获,那么 serve-waterfall 组件将作为中间件启动,使用 app.use()。以一种相当复杂的方式,这通过 "waterfall" 数组尝试每个匹配的前缀,并根据 Express 服务器根目录和目标文件组成 url正在尝试检索。如果此尝试生成“404”错误,它会捕获它,并尝试下一个匹配的瀑布数组条目。

好的,背景介绍到此为止,现在是解决方案。 如果你想做一些复杂的事情,你可以在wct-conf.js文件中定义一个registerHook函数,并在其中完全重新定义pathMappings。

类似于以下内容:-

var ret = {
  'suites': ['app/elements/**/test'],
  'plugins': ['local'],
  'registerHooks' : function(context) {
    var existingMapping = context.options.webserver.pathMappings;
    var pathMappings = [
      {'/components/<basename>/bower_components': 'app/elements'},
      {'/components/<basename>/app/elements': 'bower_components'},
    ]
    pathMappings = pathMappings.concat(existingMapping);
    context.options.webserver.pathMappings = pathMappings;
  }

};

module.exports = ret;

但是对于我上面提出的问题,下面的方法也能解决问题...

var ret = {
  'suites': ['app/elements/**/test'],
  'plugins': ['local'],
  'webserver': {
    'pathMappings': [
      {'/components/<basename>/bower_components': 'app/elements'},
      {'/components/<basename>/app/elements': 'bower_components'},
    ]

  }
};

module.exports = ret;

下面是对其功能的简要说明。 suites 参数定义查找测试的文件列表,并请求 url /components/<basename>/app/elements/xxx/test/xxx-test.html(或类似)。从瀑布数组的第一个元素开始成功。

毫无疑问,测试工具会尝试导入 ../xxx.html,这会变成对 /component/<basename>/app/elements/xxx.html 的请求,并再次从数组的第一个元素开始成功。

接下来被测元素将尝试 html 导入 ..\polymer\polymer.html

wct 再次将其转换为对 /components/<basename>/app/elements/polymer/polymer.html 的请求,但失败了,因此检查了瀑布数组中的下一项。唯一匹配的是前缀为 /components/<basename>/app/elements 的请求,它被转换为 /components/<basename>/bower_components/polymer/polymer.html 的请求。并且有效。

使用我提供的配置,您也可以用另一种方式映射,瀑布数组中的第一项将因 /components/<basename>/bower_components/xxx/xxx.html 而失败,之后唯一匹配的前缀是 /components/<basename>/app/elements。我实际上看不到需要这个。