Python 将react应用程序的构建包含到Flask中的正确方法
我有一个网站开发完全使用烧瓶。它使用一个名为Python 将react应用程序的构建包含到Flask中的正确方法,python,python-3.x,reactjs,flask,Python,Python 3.x,Reactjs,Flask,我有一个网站开发完全使用烧瓶。它使用一个名为仪表板的蓝图,它承载一些视图以访问不同的可视化效果,即仪表板/ 我使用id、名称和它所属的组来存储仪表板,因此用户只能从他们所属的组访问可视化效果 (这是我解决这个问题的经验不足的方法,因此我也愿意接受更好的设计模式来实现这一点的建议。) 我的项目有点像这样 app ├── dashboards │ ├── __init__.py │ └── views.py ├── __init__.py ├── models │ ├── dashboa
仪表板
的蓝图,它承载一些视图以访问不同的可视化效果,即仪表板/
我使用id
、名称和它所属的组来存储仪表板,因此用户只能从他们所属的组访问可视化效果
(这是我解决这个问题的经验不足的方法,因此我也愿意接受更好的设计模式来实现这一点的建议。)
我的项目有点像这样
app
├── dashboards
│ ├── __init__.py
│ └── views.py
├── __init__.py
├── models
│ ├── dashboard.py
│ └── __init__.p
├── static
│ ├── css
│ │ ├── styles.css
│ └── js
│ └── scripts.js
└── templates
├── base.html
└── dashboards
├── cat.html
├── clock.html
├── index.html
├── private.html
└── public.html
仪表板蓝图的我的视图
# app/dashboards/views.py
from ..models.dashboard import Dashboard
@dashboards.route('/<string:name>')
def view_dashboard(name):
# a dictionary with dashboards available to current_user
dashboards = get_dashboards()
for dashboard in dashboards.values():
for d in dashboard:
if name == d.name:
route = 'dashboards/{dashboard}.html'.format(dashboard = d.name)
return render_template(route, dashboard=d)
else:
return render_template('404.html'), 404
# app/dashboards/__init__.py
from flask import Blueprint
dashboards = Blueprint('dashboards', __name__)
from . import views
bp = Blueprint(name='myblueprint',
import_name=__name__,
static_folder='static/myblueprint',
template_folder='templates',
static_url_path='/static', # this is what myblueprint.static will point to
url_prefix='/myblueprint',
subdomain=None,
url_defaults=None,
root_path=None)
最后,我使用create_应用程序模式
# app/__init__.py
# some imports happening here
def create_app(config_name):
app = Flask(__name__)
from .dashboards import dashboards as dashboards_blueprint
app.register_blueprint(dashboards_blueprint, url_prefix='/dashboards')
return app
在app
之上的一个级别,有一个manage.py
调用create\u app
方法,传递一些配置属性。我相信这是烧瓶中常见的图案。我也认为这与我的问题无关
特别是,如果使用create react app包部署react app,即使用npm run build
,则输出是一个文件夹/build
,其中包含运行该app所需的静态文件。例如,此文件夹具有以下结构
├── build
│ ├── asset-manifest.json
│ ├── favicon.ico
│ ├── index.html
│ ├── manifest.json
│ ├── service-worker.js
│ └── static
│ ├── css
│ │ ├── main.<some-hash-1>.css
│ │ └── main.<some-hash-1>.css.map
│ └── js
│ ├── main.<some-hash-2>.js
│ └── main.<some-hash-2>.js.map
other files here
├── 建造
│ ├── asset-manifest.json
│ ├── 图标文件
│ ├── index.html
│ ├── manifest.json
│ ├── service-worker.js
│ └── 静止的
│ ├── css
│ │ ├── main..css
│ │ └── main..css.map
│ └── js
│ ├── main..js
│ └── main..js.map
这里还有其他文件吗
现在,如果想使用Flask插入react应用程序,我现在要做的是将/css
和/js
中的/build
文件移动到/app
中的/static
文件夹中,然后将index.html
从/build
重命名为“react dashboard.html”,并将其移动到模板/仪表板
这是一种让基本应用程序正常工作的非常愚蠢的方法,但我不知道从/build
将其他文件放在哪里,也不知道如何使用更好的设计模式
由此我可以调整蓝图定义,并将模板和静态文件夹移动到app/dashboards
,但我仍然不知道其他文件(如service worker.js
)和清单等)的位置
在Flask应用程序上“装载”部署的react应用程序的正确方法是什么?我知道从/build
重新组织文件是不可取的。我通过调整蓝图解决了这个问题
# app/dashboards/views.py
from ..models.dashboard import Dashboard
@dashboards.route('/<string:name>')
def view_dashboard(name):
# a dictionary with dashboards available to current_user
dashboards = get_dashboards()
for dashboard in dashboards.values():
for d in dashboard:
if name == d.name:
route = 'dashboards/{dashboard}.html'.format(dashboard = d.name)
return render_template(route, dashboard=d)
else:
return render_template('404.html'), 404
# app/dashboards/__init__.py
from flask import Blueprint
dashboards = Blueprint('dashboards', __name__)
from . import views
bp = Blueprint(name='myblueprint',
import_name=__name__,
static_folder='static/myblueprint',
template_folder='templates',
static_url_path='/static', # this is what myblueprint.static will point to
url_prefix='/myblueprint',
subdomain=None,
url_defaults=None,
root_path=None)
这样,蓝图中的静态路径将指向/myblueprint/static
,我需要修改创建react app
构建文件夹
- 将
/build
中每个*.css、*.js和.html中对static
的调用替换为/myblueprint/static
- 重新排列
/build
中的文件夹,以匹配我的blueprint静态文件夹。
- 将
/build/static
移动到/blueprint/static
- 在调用这些文件的
/blueprint/templates/index.html
中设置我自己的jinja模板。确保此文件指向/myblueprint/static
中的静态资产,而不是/build/static
李>
我已经创建了一个gulpfile
,它将自动化这个过程
var gulp = require('gulp');
var replace = require('gulp-replace');
var rename = require('gulp-rename');
// script to deploy react build into flask blueprint directory
// it replaces values and folder names
// README
// how to use this:
// in the react app, run npm run build
// copy the resulting /build folder in /myblueprint
// create a template of a template in /templates/base as index.default.html
// install gulp, gulp-replace, gulp-rename
// run gulp from /myblueprint
// replace routes inside css files
gulp.task('othertemplates', function(){
gulp.src(['./build/static/css/main.*.css'])
.pipe(replace('url(/static/media/', 'url(/myblueprint/static/media/'))
.pipe(gulp.dest('static/myblueprint/css/'));
});
// replace routes inside js files
gulp.task('jsthingtemplates', function(){
gulp.src(['./build/static/js/main.*.js'])
.pipe(replace('static/media/', 'myblueprint/static/media/'))
.pipe(gulp.dest('static/myblueprint/js/'));
});
// move other files
gulp.task('mediastuff', function(){
gulp.src(['./build/static/media/*'])
.pipe(gulp.dest('static/myblueprint/media/'));
gulp.src(['./build/asset-manifest.json'])
.pipe(gulp.dest('static/myblueprint/'));
});
// replace hashes in assets in the jinja template
gulp.task('jinjareplace', function(){
var fs = require('fs');
var assets = JSON.parse(fs.readFileSync('./build/asset-manifest.json'));
// extract hashes
let jsHashNew = assets['main.js'].match('[a-z0-9]{8}')
let cssHashNew = assets['main.css'].match('[a-z0-9]{8}')
gulp.src(['./templates/myblueprint/base/index.default.html'])
.pipe(replace('css/main.cssHash.css', `css/main.${cssHashNew}.css`))
.pipe(replace('js/main.jsHash.js', `js/main.${jsHashNew}.js`))
.pipe(rename('index.html'))
.pipe(gulp.dest('templates/myblueprint/'));
});
gulp.task('default', ['othertemplates', 'jsthingtemplates', 'mediastuff', 'jinjareplace'])
有了它,您可以从与gulpfile.js
相同的路径运行gulp
,并且应该涵盖所有内容