为什么我的 angular 2 应用程序不会 bootstrap?

Why won't my angular 2 application bootstrap?

我正在尝试使用 express、angular 2、typescript、gulp 和 systemjs 为 bootstrap angular 2 个应用程序构建样板模板。出于某种原因,我的 index.html 文件无法识别我的 bootstrap.js 文件。我所有的 jadetypescript 都位于 src。我正在使用 gulp 将打字稿从 src 转换为 dist,并在 express 中提供来自 node_modulesjspm_packages 的静态资产。但是当终于到了调用 System.import 的时候,就像这样: System.import('app').catch(console.error.bind(console)), 我得到:

Error: SyntaxError: Unexpected token < Evaluating http://localhost:3000/app/bootstrap.js Error loading http://localhost:3000/app/bootstrap.js

错误似乎是在 angular2-polyfills.min.js 中引起的。

这是我的基本 express 后端,可让您了解我的资产和文件是如何提供的(我怀疑我有一个临时的脑残并且我的路径已关闭):

const app = express();
app.use('/jspm_packages', express.static('jspm_packages'));
app.use('/node_modules', express.static('node_modules'));

app.get('*', function(req, res) {
  const file = fs.readFileSync('src/index.jade').toString();
  const html = jade.render(file);
  return res.send(html);
});

app.listen(process.env.PORT || 3000);

我的 index.html 文件位于 dist 中,该目录包含所有转译文件 javascript。这是我的 System.config:

上的 packages 属性
packages: {
          "dist": {
            "main": "bootstrap",
            "format": "system",
            "defaultExtension": "js"
          }
        },

我的印象是 dist 标识了相对于 BASE_URL 的文件夹(在我的例子中就是 /),而 main 属性 标识文件名。所以我认为通过调用 System.import('app'),它会在 dist 内的 app 文件夹中查找 bootstrap.js 文件到 bootstrap 我的 angular 2 应用程序,但情况似乎并非如此。当我打开 chrome 控制台时,bootstrap.js 没有出现在我的源代码中,所以我猜某处存在路径错误,但我已经尝试了所有变体,但似乎无法理解上班。

非常感谢任何帮助,谢谢。

更新:

这是我的index.htmlhttps://jsfiddle.net/r02r3jk3/ 这是提供内容的文件夹结构和服务器端代码:https://jsfiddle.net/cejk0jw3/

当我检查网络选项卡以获取对 angular2/platformbrowser.js 文件请求的响应时,我得到以下信息:

请求URL是http://localhost:3000/jspm_packages/npm/angular2@2.0.0-beta.9/platform/browser.js

响应的内容类型为 Content-Type:text/html; charset=utf-8,但响应是我的 index.html 文件 :(

而不是 System.import('app') 中的 app 它应该是 dist 这样的: System.import('dist') 并且您的包定义应该是:

packages: {
    "dist": {
      "main": "app/bootstrap",
      "format": "system",
      "defaultExtension": "js"
    }
}

更新

因为您的 index.html 位于 appdist 相同的文件夹中。那么你的包定义中不需要 dist

您的定义应该是:

packages: {
    "app": {
      "main": "bootstrap",
      "format": "system",
      "defaultExtension": "js"
    }
}

并像这样导入:

System.import('app')

更新

我试图复制您的设置,以下是我发现的问题:

在您的后端代码中:

您没有提供 dist 中的文件。该行已被注释掉。这样,由于您的 app.get('*', ...)

,对 app/* 的任何请求都将转发给 index.html

您可以取消对原始行的注释:
app.use('/dist', express.static('dist'));

app.use('/app',express.static('dist/app'))

取决于你做的是哪一个,packages对象会有所不同。

我会选择后者,app.use('/app',express.static('dist/app'))。从请求中隐藏 dist 对我来说更有意义。

此外,检查 SystemJS module formats

包定义为:

  packages: {
    "app": {
      "main": "bootstrap",
      //"format": "system",  // this was causing the main issue 
      format:"register",
      "defaultExtension": "js"
    }
  },

最后:

System.import('app')

更新

最后一个问题是关于行 "angular2": "npm:angular2@2.0.0-beta.9":

server/index.js中的以下两行引起:

app.use(express.static('jspm_packages'));
app.use(express.static('node_modules'));

问题是 jspm_packagesnode_modules 中的所有内容将直接从服务器提供。因此,如果您尝试访问:http://localhost:3000/angular2,它将从 node_modules.
提供服务 如果您尝试访问:http://localhost:3000/npm/angular2@2.0.0-beta.9,它将从 jspm_packages 提供服务。所以,当你有这些行时:

paths: {
  ...
  "npm:*": "jspm_packages/npm/*"
},
map:{
  `"angular2": "npm:angular2@2.0.0-beta.9"`
}

angular2 的每个请求都将转换为:jspm_packages/npm/angular2@2.0.0-beta.9。但它应该只是 /npm/angular2@2.0.0-beta.9.

当您删除 "angular2": "npm:angular2@2.0.0-beta.9" 时它起作用了,因为 angular2 现在将从 node_modules.

内部提供

所以解决方案是将您的 server/index.js 更改为:

app.use('jspm_packages',express.static('jspm_packages'));
app.use('node_modules',express.static('node_modules'));

此外,index.html 中的脚本标签现在应该是:

<script src="jspm_packages/npm/angular2@2.0.0-beta.9/bundles/angular2-polyfills.min.js"></script>
<script src="jspm_packages/system.js"></script>

事实上,这取决于在构建应用程序时如何转换 TypeScript 文件:

  • 如果您为每个 TypeScript 获取一个 JS 文件,则会在相应文件中创建一个匿名模块 ("System.register([ 'import1' ], ...")。在这种情况下,模块由其名称和路径标识。
  • 如果您只为所有 TypeScript 文件获取一个 JS 文件(使用 outFile 选项),则在使用 System.register 函数时明确定义模块名称 (("System.register('module name', [ 'import1' ], ...").

你的情况好像属于第一种情况,你可以试试这个:

System.import('path/to/boot');

请注意,如果您的 index.html 文件位于 dist 文件夹下,您需要在该级别为您的 JS 编译文件创建一个子文件夹。此子文件夹需要在 "packages" 条目中配置到您的 SystemJS 中。

有关详细信息,请参阅此问题:

  • How do I actually deploy an Angular 2 + Typescript + systemjs app?