【问题标题】:how to combine angular2 with jinja2 templates and flask如何将 angular2 与 jinja2 模板和烧瓶结合起来
【发布时间】:2016-04-04 07:26:47
【问题描述】:

在 Angular 1 取得巨大成功后,我开始使用 Angular 2。我遵循了 QuickstartTour of Heroes 教程,一切都像魅力一样。

lite 服务器启动,我看到tsc 在监视模式下运行,我什至看到 BrowserSync 已连接。太好了!

但是,我需要开始让事情变得更加真实。

我如何使用烧瓶开发或 gunicorn 服务器而不是使用 lite 服务器来完成所有这些工作,将初始 index.html 文件作为渲染的 jinja 模板提供服务?

给烧瓶开发服务器一个非常幼稚的尝试,我基本上将教程中示例 index.html 的内容复制到我的 jinja 模板中,然后运行npm run tsc:w,最后启动我的烧瓶开发服务器并希望最好.事情编译得很好。但是在浏览器中我看到了问题:

angular2-polyfills.js:332 Error: SyntaxError: Unexpected token <
    at ZoneDelegate.invoke (http://127.0.0.1:5000/static/node_modules/angular2/bundles/angular2-polyfills.js:332:29)
    at Zone.run (http://127.0.0.1:5000/static/node_modules/angular2/bundles/angular2-polyfills.js:227:44)
    at http://127.0.0.1:5000/static/node_modules/angular2/bundles/angular2-polyfills.js:576:58
Evaluating http://127.0.0.1:5000/app/main.js
Error loading http://127.0.0.1:5000/app/main.js`

查看我看到的罪魁祸首 transpile main.js 文件:

(function(System, SystemJS, require) {<!doctype html>
<html>
<head lang='en'>

所以,是的,那是行不通的......显然我的接线是混乱的。

在 shims、polyfills、响应式扩展、systemjs、angular2 本身以及 tsc 和 lite 服务器中都有很多黑魔法。诚然,我还没有完成这一切,这需要时间,但我希望能很快让我的项目进入理智状态。

(我不介意在开发中使用 lite 服务器(BrowserSync 是一个不错的优势),只要我可以将其配置为代理将返回渲染 jinja 模板的真正的烧瓶服务器。)

更新

这是实际的模板索引文件,我做了一些小改动:

<!doctype html>
<html>
  <head lang="en">
    {% block head %}

    <meta charset="utf-8">

    <title>Angular 2 QuickStart</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">    
    <link rel="stylesheet" href="styles.css">
    <!-- 1. Load libraries -->
    <!-- IE required polyfills, in this exact order -->
    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>   
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>

    {% endblock %}
  </head>
  <!-- 3. Display the application -->
  <body>
    {% block content %}{% endblock %}

    <my-app>Loading...</my-app>

    <script>
      (function(globals) {
        this.MyConfig = {
          staticDir: '{{ config["STATIC_DIR"] }}'
        };
      }(this));
    </script>
  </body>
</html>

【问题讨论】:

  • 您最好提供模板的来源。
  • 确定。好点...我在问题中添加了模板代码。
  • 我很奇怪你在 main.js 中有 HTML。它应该在“localhost:NNN”的输出中或您用于提供文档的任何内容中。我猜它可以与响应式扩展相关联(它是 RreactiveJS 吗?)。尝试禁用它们?
  • 对,这很奇怪。如果我只是注释掉 System.config() 和 System.import() 代码,那么 html 就会像你期望的那样得到服务,当然什么也不会发生。包含 HTML 的 main.js 文件——我真的不知道为什么,也不知道如何调试它。这个文件只是一些在文件系统上并不真正存在的虚无缥缈的文件,所以我不确定如何调试它是如何生成的。

标签: python node.js flask angular jinja2


【解决方案1】:

我遇到了同样的问题,我是这样解决的;

第一步

目录结构如下:

+- 我的应用程序名称
+-- 服务器应用程序
+--- //...这里的烧瓶文件
+-- 客户端应用程序
+--- 节点模块
+--- 应用程序
+--- //...更多节点+角度应用程序文件

我使用以下代码在 URL .../client-app/... 处公开了我的烧瓶应用程序中的 ClientApp 文件夹:

from flask import Flask, send_from_directory
import os

BASE_URL = os.path.abspath(os.path.dirname(__file__))
CLIENT_APP_FOLDER = os.path.join(BASE_URL, "ClientApp")

# This is required by zone.js as it need to access the
# "main.js" file in the "ClientApp\app" folder which it
# does by accessing "<your-site-path>/app/main.js"
@app.route('/app/<path:filename>')
def client_app_app_folder(filename):
    return send_from_directory(os.path.join(CLIENT_APP_FOLDER, "app"), filename)

# Custom static data
@app.route('/client-app/<path:filename>')
def client_app_folder(filename):
    return send_from_directory(CLIENT_APP_FOLDER, filename)

第二步

转到您的index.html 文件(我将我的文件放在ServerApp\templates\index.html 以便我可以简单地执行render_template('index.html'))并使其看起来像这样:

<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="client-app/assets/css/style.css">

    <!-- 1. Load libraries -->
     <!-- Polyfill(s) for older browsers -->
    <script src="client-app/node_modules/es6-shim/es6-shim.min.js"></script>

    <script src="client-app/node_modules/zone.js/dist/zone.js"></script>
    <script src="client-app/node_modules/reflect-metadata/Reflect.js"></script>
    <script src="client-app/node_modules/systemjs/dist/system.src.js"></script>

    <!-- 2. Configure SystemJS -->
    <script src="client-app/systemjs.config.js"></script>
    <script src=""></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

路径前面的“客户端应用程序”是我选择在以下位置公开client_app_folder() 函数的路径

第三步

将您的客户端应用程序的包查找器配置为使用设置的路由(在本例中为“client-app/...”)。我使用 system.js,因此我使我的 systemjs.config.js 文件看起来像这样:

(function(global) {

  // map tells the System loader where to look for things
  var map = {
    'app':                        'client-app/app', // 'dist',
    'rxjs':                       'client-app/node_modules/rxjs',
    'angular2-in-memory-web-api': 'client-app/node_modules/angular2-in-memory-web-api',
    '@angular':                   'client-app/node_modules/@angular'
  };

  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' },
  };

  var packageNames = [
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router',
    '@angular/router-deprecated',
    '@angular/testing',
    '@angular/upgrade',
  ];

  // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
  packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
  });

  var config = {
    map: map,
    packages: packages
  }

  // filterSystemConfig - index.html's chance to modify config before we register it.
  if (global.filterSystemConfig) { global.filterSystemConfig(config); }

  System.config(config);

})(this);

我只修改了map变量

神速!

【讨论】:

  • 感谢您的详细解答!为 zone.js 设置路由 '/app/...' 对我来说是一个大关键。现在我只需要找时间回去并迷上它,并把我最喜欢的第 3 方 Angular 1 指令也连接进去。
【解决方案2】:

在寻找同一个问题的答案时,我被提醒要更改 angular 1 中的插值字符。可以找到两个为 angular 2 执行此操作的位置,但在 jinja2 端进行更改非常简单。用这个设置 jinja2 环境选项字符,但是你想要:

JINJA_ENV = jinja2.Environment(
  loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
  extensions=['jinja2.ext.autoescape'],
  block_start_string= '{[%',
  block_end_string='%]}',
  variable_start_string='{[',
  variable_end_string=']}',
  comment_start_string='{#',
  comment_end_string='#}',
  autoescape=True
)

希望我在这里使用兼容的字符串,我想我会发现的! (参见http://jinja.pocoo.org/docs/dev/api/ 环境选项)

【讨论】:

  • 如果您愿意,您也可以通过插值提供程序在角度方面进行更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 2019-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多