我对 Vue 和现代 Web 开发很陌生,所以我提前道歉。情况是这样的。
我正在尝试制作一个简单的 Flask 应用程序,它在前端使用 Vue 和 Vuetify。当我查找如何将 Flask 与 Vue 结合的教程时(就像这个),它依赖于 webpack,我可以让它正常工作。当我尝试根据他们的快速入门指南的说明将 Vuetify 添加到项目中时,我发现它要求您遵循Existing Applications
指南,因为该项目不是使用 vue-cli3 初始化的(请参阅此处的错误报告)。我尝试按照这些说明进行操作,但在混乱的几个小时后放弃了,没有结果。
在阅读了 webpack 之后,我决定对于我的特定应用程序,我可以负担得起不使用它。所以我回到了 Vuetify 快速入门指南并按照New Applications
说明,启动了 Flask,这就是我得到的:
127.0.0.1 - - [21/May/2019 18:31:20] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/May/2019 18:31:20] "GET /js/app.c12f4ec0.js HTTP/1.1" 404 -
127.0.0.1 - - [21/May/2019 18:31:20] "GET /css/chunk-vendors.b7bc2226.css HTTP/1.1" 404 -
127.0.0.1 - - [21/May/2019 18:31:20] "GET /js/chunk-vendors.2eb58769.js HTTP/1.1" 404 -
127.0.0.1 - - [21/May/2019 18:31:21] "GET /js/app.c12f4ec0.js HTTP/1.1" 404 -
127.0.0.1 - - [21/May/2019 18:38:22] "GET /index.html HTTP/1.1" 404 -
有问题的代码:
from flask import Flask, render_template
app = Flask(__name__,
static_folder="./test/dist",
template_folder="./test/dist")
@app.route('/')
def index():
return render_template("index.html")
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
在大多数情况下,Vue 代码只是一个安装了 Vuetify 的新项目。我所做的唯一更改是在main.js
中,我更改了分隔符的内容,以便它们不会与 Jinja2 冲突。
import Vue from 'vue'
import './plugins/vuetify'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
delimiters: ["[[", "]]"],
}).$mount('#app')
我的三个主要问题是:
- Flask 用于查找静态文件和模板文件的路径有什么问题?
- 是否可以在没有 webpack 的情况下将 Vue 与 Flask 一起使用?
- 如果不可能,有人会做一个关于如何将 Vuetify 集成到基于 webpack 的 Vue 项目中的 eli5 吗?
提前感谢!
好的,所以我找到了答案,结果证明它比我想象的要容易得多。为了更容易复制我的步骤,我将从顶部开始。
app.py
from flask import Flask, render_template
app = Flask(__name__,
static_folder="./test/dist", # place that webpack builds to
template_folder="./test/dist")
@app.route('/')
def index():
return render_template("index.html")
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
在与app.py
相同的目录中运行以下命令(假设您已经安装了 vue-cli):
$ vue init webpack vue-app-name
$ cd vue-app-name
$ yarn add vuetify # or use npm install vuetify --save
现在你基本上只需按照 Vuetify 快速入门页面的Existing Applications
部分的说明进行操作:
主顶部.js
import Vue from 'vue'
import App from './App'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
Vue.config.productionTip = false
Vue.use(Vuetify)
<head>
索引部分.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>frontend</title>
<link href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons' rel="stylesheet">
</head>
最后在索引的构建部分.js将 web pack 输出其构建的目录更改为:
// Template for index.html
index: path.resolve(__dirname, '../../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../../dist'),
此时,如果您运行
$ yarn build # or npm run build
$ cd ..
$ python app.py
并弹出打开你的网络浏览器,你应该看到默认的 Vue HelloWorld 页面,你有 Flask 与 Vue、Vuetify 和 webpack 一起工作。
这就是我感到困惑的地方。如果您按照新 Vuetify 项目的说明运行开发服务器,它们将拥有自己的自定义 Hello World 页面。但是,因为 Hello World 页面仍然是默认的 Vue 页面,我认为这意味着没有安装 Vuetify。真正发生的事情是他们有不同的App.vue和HelloWorld.vue文件。如果你用Vuetify文件替换常规的App.vue和HelloWorld.vue文件,将logo.svg
文件复制到assets文件夹中并重新运行开发服务器,你将获得Vuetify登陆页面。
无论如何,我觉得自己像个白痴,但希望这对另一个 Flask/Vue/Vuetify/Webpack 新手有所帮助。
这是使用 python 3.7.3和 vue-cli 3.7.0 完成
的。我有多个 Vue 和 Flask 项目,发现 webpack 是最好的方法。我不喜欢 Vue-CLI,因为在构建时指定本地文件和捆绑文件的路径太困难了。我知道一开始这是一个学习曲线,但如果你投入时间,值得一两天。
您应该使用 Flask-Webpack 来允许 flask 查找已散列和捆绑的资产。以及一个 webpack 插件来创建提供链接的清单 JSON。使用烧瓶 webpack 时,您还需要像以前一样直接指定文件夹路径。
我的 webpack 配置中有这个设置:
const ManifestPlugin = require('webpack-manifest-plugin')
...
plugins: [
new ManifestPlugin({
writeToFileEmit: true,
seed: {
publicPath: '/'
},
generate: (seed, files) => ({
...seed,
'assets': files.reduce((manifest, { name, path }) => ({ ...manifest,
[name]: path }), {})
})
})
]
这将创建一个如下所示的清单.json文件:
{"assets":{"base_css.css":"static/css/base_css.1bf3ff18.css",
"base_css.js":"static/js/base_css.1e6b291b.js",
"chunk-vendors.js":"static/js/chunkvendors.f92da40c.js",},
"publicPath":"/"}
设置好项目后,我设想在使用 npm 和导入添加到现有项目之后添加 Vuetify 是相当简单的。
请注意,使用 Vue-CLI 和/或 webpack 时,您无法更改 vue 分隔符。来自 API 文档中的分隔符:"限制:此选项仅在完整版本中可用,具有浏览器内编译。
但是最后一点应该不是问题,因为你的 html 模板和 vue 模板将分别解耦,所以 {{ }} 交叉无关紧要,它们是上下文相关的。
我遇到了类似的问题。@clayton-ramstedt 提供的答案提供了 200 个状态代码,但它加载的是空白页面而不是所需的静态 UI。原因是索引.html引用了其他各种JS和CSS文件,并且上面的答案对所有文件都返回了index.html
。
下面的代码对我有用。
from flask import Flask, send_from_directory
import os
app = Flask(__name__,
static_folder="./test/dist",
template_folder="./test/dist")
@app.route("/", defaults={"path": ""})
@app.route("/<path:path>")
def serve_frontend(path):
if path != "" and os.path.exists(app.static_folder + '/' + path):
return send_from_directory(app.static_folder, path)
return send_from_directory(app.static_folder, 'index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
这将正确呈现JS和CSS文件,当我们遇到其他一些路由(如/login或/dashboard)时,它们将由index相应地处理.html。
确保提供path
转换器类型,因为默认字符串类型不会呈现包含斜杠的 JS 和 CSS 文件。