如何将 angular2 与 jinja2 模板和烧瓶结合起来
how to combine angular2 with jinja2 templates and flask
在 Angular 1 取得巨大成功后,我开始使用 Angular 2。我遵循了 Quickstart and the Tour of Heroes 教程,一切都很顺利。
精简版服务器启动,我看到 tsc
运行 处于监视模式,我什至看到 BrowserSync 已连接。太棒了!
但是,我需要开始让事情变得更加真实。
如何使用 flask dev 或 gunicorn 服务器而不是使用精简版服务器,将初始 index.html 文件作为呈现的 jinja 模板来实现所有这些工作?
给 flask 开发服务器一个非常天真的尝试,我基本上将示例 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`
查看罪魁祸首转译 main.js 文件,我看到:
(function(System, SystemJS, require) {<!doctype html>
<html>
<head lang='en'>
所以,是的,那是行不通的...显然我的线路是乱七八糟的。
垫片、polyfill、反应式扩展、systemjs、angular2 本身有很多黑魔法,然后加入 tsc 和 lite 服务器。诚然,我还没有完成所有这些工作,这需要时间,但我希望我的项目能很快恢复正常。
(我不介意在开发中使用精简版服务器(BrowserSync 是一个很好的特权),只要我可以将其配置为代理真正的烧瓶服务器,该服务器将 return 呈现 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>
在寻找同一个问题的答案时,我被提醒要更改 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/ 环境选项)
我遇到了同样的问题,这是我如何解决的;
步骤 1
目录结构如下:
+- MyAppName
+-- 服务器应用
+--- //...这里是烧瓶文件
+-- 客户端应用
+--- 节点模块
+--- 应用程序
+--- //...更多节点+angular 应用程序文件
我使用以下代码在 URL .../client-app/...
处公开了我的 Flask 应用程序中的 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)
步骤 2
转到你的 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' 是我选择在
公开我的 client_app_folder()
函数的路径
步骤 3
将您的客户端应用程序的包查找器配置为使用设置的路由(在本例中为 '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
变量
祝一切顺利!
在 Angular 1 取得巨大成功后,我开始使用 Angular 2。我遵循了 Quickstart and the Tour of Heroes 教程,一切都很顺利。
精简版服务器启动,我看到 tsc
运行 处于监视模式,我什至看到 BrowserSync 已连接。太棒了!
但是,我需要开始让事情变得更加真实。
如何使用 flask dev 或 gunicorn 服务器而不是使用精简版服务器,将初始 index.html 文件作为呈现的 jinja 模板来实现所有这些工作?
给 flask 开发服务器一个非常天真的尝试,我基本上将示例 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`
查看罪魁祸首转译 main.js 文件,我看到:
(function(System, SystemJS, require) {<!doctype html>
<html>
<head lang='en'>
所以,是的,那是行不通的...显然我的线路是乱七八糟的。
垫片、polyfill、反应式扩展、systemjs、angular2 本身有很多黑魔法,然后加入 tsc 和 lite 服务器。诚然,我还没有完成所有这些工作,这需要时间,但我希望我的项目能很快恢复正常。
(我不介意在开发中使用精简版服务器(BrowserSync 是一个很好的特权),只要我可以将其配置为代理真正的烧瓶服务器,该服务器将 return 呈现 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>
在寻找同一个问题的答案时,我被提醒要更改 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/ 环境选项)
我遇到了同样的问题,这是我如何解决的;
步骤 1
目录结构如下:
+- MyAppName
+-- 服务器应用
+--- //...这里是烧瓶文件
+-- 客户端应用
+--- 节点模块
+--- 应用程序
+--- //...更多节点+angular 应用程序文件
我使用以下代码在 URL .../client-app/...
处公开了我的 Flask 应用程序中的 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)
步骤 2
转到你的 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' 是我选择在
公开我的client_app_folder()
函数的路径
步骤 3
将您的客户端应用程序的包查找器配置为使用设置的路由(在本例中为 '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
变量
祝一切顺利!