MarredCheese
MarredCheese

Reputation: 20881

Flask: How to use ES6 modules?

I have a working Flask app that I'm trying to refactor to use ES6 imports. I don't need it to run on old browsers, and ES6 imports work in modern browsers without transpilation, right?

I'm just running this via Flask's built-in server at the moment. The production app is served via gevent instead, but I'm obviously not at that point with these changes yet.

Below is what I've tried so far. Where have I gone wrong?

views.py

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

formatting.js

export function formatNumber(...) {
  ...
}

Attempt 1

home.html

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

main.js

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

Error (main.js, line 1)

Uncaught SyntaxError: Unexpected token {

Attempt 2

home.html

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

Error (main.js, line 1)

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.

Attempt 3

home.html

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

main.mjs

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

Error (main.mjs, line 1)

Failed to load module script: The server responded with a non-JavaScript MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.

Upvotes: 13

Views: 13205

Answers (4)

norbitheeviljester
norbitheeviljester

Reputation: 962

this worked for me:

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

added this code before launching flask

Upvotes: 5

Ryan de Kleer
Ryan de Kleer

Reputation: 1363

For those of you getting the error:

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

...you'll want to confirm python is returning the expected mimetype of your JS files.

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

For myself, using a Windows platform to host the web server from (eg. Flask's development server), I found I needed to update the registry to associate the file extension with text/javascript.

For example, in the registry editor:

  1. Under HKEY_CLASSES_ROOT, find .js (and .mjs if using that)
  2. Look at the value for "Content Type". It must say text/javascript, NOT text/plain, or application/octet-stream, etc.

Upvotes: 7

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38982

I don't need it to run on old browsers, and ES6 imports work in modern browsers without transpilation, right?

It depends on browser spectrum of your intended application users.

There is documented support for ES6 imports in modern web browsers.

See the list of supported browsers to be sure that you're viewing your application in a supported browser version.

The script extension ought to be .js and not .mjs as documented in the above link.

I noticed that the error reported is one that as to do with mimetype. Flask is returning an application/octet-stream for the mimetype of the static file where it is unable to guess the mimetype.

You can correct this using the url_for template function to build the url for the file pointing at a view that returns an appropriate mimetype.

<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'
    )

While text/javascript is a deprecated mime/type for JS resources, you may have better support for it in browsers.

I strongly suggest to use gunicorn or nginx to serve the static files as the above is only goes as far as helping with development.

Upvotes: 1

James Russo
James Russo

Reputation: 568

I'm pretty sure you will need to use webpack and babel to transpile your code.

There is a webpack plugin for Flask that might be of use https://pypi.org/project/Flask-Webpack/ https://github.com/nickjj/flask-webpack

You could also follow this https://itnext.io/a-template-for-creating-a-full-stack-web-application-with-flask-npm-webpack-and-reactjs-be2294b111bd or https://codeburst.io/creating-a-full-stack-web-application-with-python-npm-webpack-and-react-8925800503d9 tutorials. Just ignore the parts about react

This post ES6 build chain python backend (flask) not SPA seems to be a similar one to yours as well.

Upvotes: 2

Related Questions