Backbone + RequireJS:使用RequireJS加载的HTML文件被解释为JS文件

时间:2013-02-17 17:00:16

标签: php javascript apache backbone.js requirejs

我想推出Backbone.js + Require.js。我可以加载模块就好了。但是当我尝试使用文本加载我的.html文件时!插件(text.js),我收到这些错误:

资源解释为脚本,但使用MIME类型text / html传输:“https://host.net/templates/login.html”。 require.js:1843

未捕获的SyntaxError:意外的令牌<的login.html:1

未捕获的TypeError:无法调用undefined underscore.js的方法'replace':1130

以下是我正在使用的规范:

浏览器 :Chrome

服务器端 :PHP w / Slim

计算机 :带有bitnami AMI的AWS微实体//这些东西附带生产默认设置,因此有可能Apache配置不对,或者php.ini不正确。我只是不知道是什么。

目录结构:

/
   dev/    // Webroot: Behind basic_auth for dev reasons
       web/
           index.php    // Starts up the Slim router and PHP backend 
               app/
                   app.html    // The entry point for our SPA, data-main defined here
       js/   // At root for module accessibility in case of reuse
           apps/
           app/
               main.js  // Here we do require.config and bootstrapping
           app.js   
           router.js
           text.js
           modules/
               models/
                   login.js
               views/
                   login.js
           lib/
                   backbone/
                   backbone.js
               jquery/
                   jquery.js
               require/
               require.js
               underscore/
               underscore.js
       templates/   // Also at root for access to reuseable markup, such as login.html
        login.html

以下是我认为相关的一些代码:

/js/apps/app/main.js

requirejs.config({
 baseUrl: '/js/apps/app',

  shim: {
    'backbone' : {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
    },
    'underscore' : {
      exports: '_'
    },
    'jquery' : {
      exports: '$'
    },
    'backbone.ajaxcommands' : {
      deps : ['backbone', 'underscore', 'jquery'],
    }
  },

  paths: {
    jquery:     'lib/jquery/jquery-1.9.1.min',
    underscore: 'lib/underscore/underscore',
    backbone:   'lib/backbone/backbone-min'
  },

  config: {
    text: {
      useXhr: function (url, protocol, hostname, port)
      {
        protocol = 'https';
  //      return true; 
      }
    }
  }
});
require(['app'],function(App){
    App.initialize(); 
    App.start(); 
  }
); 

/js/apps/app/modules/views/login.js

define([
  'backbone',
  'underscore',
  'modules/views/login',
  'text!/templates/login.html'
], function(Backbone, _, Login, loginTemplate){
  var LoginView = Backbone.View.extend({
    el: $("#login-form"),

    events: {
      "click #login": "login"
    },

    template: _.template(loginTemplate),

    initialize: function(){
      var self = this; 

      this.username = $("#username"); 
      this.password = $("#password"); 

      this.username.change(function(e){
        self.model.set({username: $(e.currentTarget).val()});
      }); 

      this.password.change(function(e){
        self.model.set({password: $(e.currentTarget).val()}); 
      });

    },

    login: function(){
      var user= this.model.get('username'); 
      var pword= this.model.get('password'); 
      if(this.model.save() == false)
      {
        console.log("We got issues loggin' in"); 
      }
      else
      {
        console.log("We should have cookies now"); 
      }
    }

    //render: function(){
    //  this.$el.append(this.template); 
    //}
  });
  return LoginView; 
}); 

/templates/login.html

`<div>hi</div>`

努力寻找解决方案: 当我查看Chrome调试器时,在“网络”标签下,我看到确实检索到了login.html,但Chrome认为它是一个JS文件。

我使用断点遍历代码,发现在Require.js 1843中,该行上的节点对象有一个名为“outerHtml”的属性,等于带有一堆属性的“'标签。那么也许它将我的html包装在标签中?当我查看调试器的网络选项卡中的预览选项卡时,我确实看到了标记。如果login.html具有有效的js代码,那么我没有得到语法错误。我仍然得到underscore.js错误,因为它的格式错误的html。

我尝试过这些解决方案: Chrome says "Resource interpreted as script but transferred with MIME type text/plain.", what gives?

在项目下移动js /模板代码(使路径相对而不是绝对)。一切似乎都有效,但text.js会将.js附加到login.html的末尾,所以我找不到404。这是因为跨域访问是偶然的?

使用require.config的各种配置选项,包括设置baseURL

不幸的是,我遗忘了许多其他的调整。这真是令人沮丧。

感谢您的时间。

修改 我把一个独立的东西展现出我在drive上看到的相同的行为。文件结构应为:

/
    index.html //This can actually be anywhere visible on the web
    so-js/
        ...
    so-templates/
        ...

注意so-js /和so-templates是在webroot上,索引文件可以在任何地方。

2 个答案:

答案 0 :(得分:6)

问题是由这一行引起的:

   config: {
    text: {
      useXhr: function (url, protocol, hostname, port)
      {
        protocol = 'https';
      //  return true; 
      }
    }
  }

它覆盖了文本!的useXhr方法,它意味着返回一个布尔值来确定文本文件的Javascript版本是否可用。如果是,它将返回false,否则为true。

因为你没有返回任何内容并且undefined是假的,所以它需要意味着它应该在&lt; script&gt;中加载它。标记,这就是为什么你得到MIME类型警告和后续错误。

如果删除整个配置属性,则错误消失,loginCMmplate将填入login.html。

答案 1 :(得分:0)

您也可以使用grunt从html模板生成模块

像这样:

模板/ hello.html的

<div>hello world!</div>

JS /模板/ hello.js

define('templates/hello', '<div>hello world!</div>')

grunt任务配置:

function converTemplate(srcDir){
    return function(){
        grunt.file.recurse(srcDir, function(abspath, rootdir, subdir, filename){
            if(/^.*\.html$/.test(filename)){
                if(subdir){
                    subdir = subdir.replace(/\\/g, '/');
                }

                var content = grunt.file.read(abspath),
                    targetPath = 'js/templates' + '/' + (subdir ? subdir + '/': '') + filename.replace('.html', '.js'),
                    moduleName = 'templates/' + (subdir ? subdir + '/': '') + filename.replace('.html', '');
                content = content.replace(/[ \t]*\r?\n[ \t]*/g, '');
                content = content.replace(/'/g, '\\\'');
                content = "define('"+moduleName+"', [], '"+content+"');";
                subdir && grunt.file.mkdir('js/templates/' + (subdir ? subdir + '/': ''));
                grunt.file.write(targetPath, content);
            }
        });
    };
}

grunt.registerTask('template', 'conver template', converTemplate('templates'));

目录结构:

templates/
    hello.html
js/
    templates/
        hello.js