Flask:如何使用 ES6 模块?

Posted

技术标签:

【中文标题】Flask:如何使用 ES6 模块?【英文标题】:Flask: How to use ES6 modules? 【发布时间】:2019-10-28 10:30:59 【问题描述】:

我有一个正在工作的 Flask 应用程序,我正在尝试重构它以使用 ES6 导入。我不需要它在旧浏览器上运行,而 ES6 导入在现代浏览器中也能正常工作,对吧?

我现在只是通过 Flask 的内置服务器运行它。生产应用程序是通过 gevent 提供的,但我显然还没有进行这些更改。

以下是我迄今为止尝试过的。我哪里出错了?

views.py

@app.route('/home')
def serve_home():
    return render_template('home.html')

格式化.js

export function formatNumber(...) 
  ...

尝试 1

home.html

<script type="text/javascript" src="/static/js/main.js"></script>

main.js

import formatNumber from "/static/js/formatting.js";

错误(main.js,第 1 行)

Uncaught SyntaxError: Unexpected token

尝试 2

将脚本类型更改为“模块”

home.html

<script type="module" src="/static/js/main.js"></script>

错误(main.js,第 1 行)

加载模块脚本失败:服务器以“text/plain”的非 JavaScript MIME 类型响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。

尝试 3

将两个 Javascript 文件的扩展名从“js”更改为“mjs”

home.html

<script type="module" src="/static/js/main.mjs"></script>

main.mjs

import formatNumber from "/static/js/formatting.mjs";

错误(main.mjs,第 1 行)

加载模块脚本失败:服务器以“application/octet-stream”的非 JavaScript MIME 类型响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。

【问题讨论】:

【参考方案1】:

我很确定你需要使用 webpack 和 babel 来转译你的代码。

有一个 Flask 的 webpack 插件可能有用https://pypi.org/project/Flask-Webpack/https://github.com/nickjj/flask-webpack

您也可以按照此https://itnext.io/a-template-for-creating-a-full-stack-web-application-with-flask-npm-webpack-and-reactjs-be2294b111bd 或https://codeburst.io/creating-a-full-stack-web-application-with-python-npm-webpack-and-react-8925800503d9 教程进行操作。忽略关于 react 的部分

这篇ES6 build chain python backend (flask) not SPA 的帖子似乎也与您的相似。

【讨论】:

【参考方案2】:

我不需要它在旧浏览器上运行,而 ES6 导入可以在现代浏览器中运行而无需转译,对吧?

这取决于您的预期应用程序用户的浏览器范围。

在现代网络浏览器中支持 ES6 导入。

请参阅list of supported browsers 以确保您在受支持的浏览器版本中查看您的应用程序。

脚本扩展名应该是.js,而不是上面链接中记录的.mjs

我注意到报告的错误与 mimetype 有关。 Flask 是 returning an application/octet-stream 用于静态文件的 mimetype,它无法猜测 mimetype。

您可以使用url_for 模板函数更正此问题,为指向返回适当mimetype 的视图的文件构建URL。

<script type="module" src=" url_for('es6-static', filename='/js/main.js') "></script>
@app.route('/es6-static/<path:filename>')
def es6_static(filename):
    return send_from_directory(app.config['ES6_MODULES'],
                               filename, as_attachment=True,
                               mimetype='text/javascript'
    )

虽然text/javascript 是 JS 资源的已弃用 mime/type,但您可能在浏览器中对它有更好的支持。

我强烈建议使用 gunicorn 或 nginx 来提供静态文件,因为以上只是有助于开发。

【讨论】:

【参考方案3】:

对于那些遇到错误的人:

The server responded with a non-JavaScript MIME type [...]

...您需要确认 python 正在返回您的 JS 文件的预期 mimetype。

>>> import mimetypes
>>> mimetypes.guess_type("notExists.js")
('text/javascript', None)

我自己使用 Windows 平台从(例如 Flask 的开发服务器)托管 Web 服务器,我发现我需要更新注册表以将文件扩展名与 text/javascript 关联。

例如,在注册表编辑器中:

    在 HKEY_CLASSES_ROOT 下,找到 .js(如果使用,则找到 .mjs) 查看“内容类型”的值。它必须text/javascript,而不是text/plain,或application/octet-stream等。

【讨论】:

【参考方案4】:

这对我有用:

import mimetypes
mimetypes.add_type('application/javascript', '.mjs')

在启动烧瓶之前添加此代码

【讨论】:

以上是关于Flask:如何使用 ES6 模块?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 ES6 模块使用 Socket.IO 客户端?

如何使用 ES6 模块导入来导入路径

如何判断一个特定模块是 CommonJS 模块还是 ES6 模块?

如何将 ES6、AMD 和 CJS 模块与 JSPM 和系统 js 一起使用?

如何使用 ES6 模块模拟单元测试的依赖关系

如何将 ES6 导入与“请求”npm 模块一起使用