Skip to content
loading...

Vue+Flask on DigitalOcean: how to proceed?

twitter logo github logo ・1 min read  

Hi!

Following my earlier post, I am now trying to have my app running on a single Digital Ocean droplet.

But how should I approach it?

Is it correct to have my Vue app being served to the outside world and the Flask API being served locally in the droplet, and have my Vue app access it via localhost:port?

Or do I need two server blocks, one for the Vue app and one for the Flask API?

(the API is for internal use only, I do not intend to have a public endpoint to it)

Thanks for the help!
Daniel

twitter logo DISCUSS (6)
markdown guide
 

I don't know specifically about Digital Ocean but you should probably just serve the VueJS app from Flask's static app. Treat it as just a JS dependency that's served by the server.

How to do it (I'm using blueprints but you can do it with the regular app)

# Used to find the Vue.js frontend app
TEMPLATE_FOLDER = os.path.abspath(
    os.path.join(os.path.dirname(app.__file__), '../..', 'frontend/dist')
)
STATIC_FOLDER = os.path.join(TEMPLATE_FOLDER, 'static')

# look for the frontend index.html page, it's a Vue.js SPA
app = Blueprint(
    'frontend',
    'app.frontend',
    url_prefix='/',
    template_folder=TEMPLATE_FOLDER,
    static_folder=STATIC_FOLDER,
    static_url_path='/static'
)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    'Frontend application'
    return render_template('index.html')

This tells Flask to serve the result of yarn build (the static app) as regular js and css dependencies. The frontend in my case sits in the same repository, that's why this works.

These two lines:

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')

make sure that all paths get redirected to the SPA so that it's going to be Vue's router responsibility to handle them.

On the Vue part this is the configuration (I'm using vue cli 3 but it worked with the old vue template in a similar way):

module.exports = {
  assetsDir: 'static'
}

so that the build command will put the static files in a static subdirectory to make Flask happy :-)

 

Wow, would never have thought about doing it this way.
Sounds great. And that makes all my API calls quite simple.
Will give it a try.

Thanks!

 

I deployed a side project using Flask/React last week on digital ocean. I just installed nginx and configured a block to serve a static build of the react app and one to serve the flask API via gunicorn. I also setup gitlab CI to build/deploy, which seems to be working pretty good so far.

If your API is being used by the Vue app, it'll need to be public because of the nature of SPAs. You could probably enforce domain referral requirements, but usually you just secure the API with the knowledge that it's publicly available.

 

If your API is being used by the Vue app, it'll need to be public because of the nature of SPAs.

But that only in this solution or also in @rhymes solution described above?

 

@danroc mine is behind basic authentication. The SPA talks to the API and they both are behind basic authentication (TLS only)

 

It'll be public in his solution, as well. The only difference is that the initial index.html file will be served via the flask app, instead of just through nginx.

Classic DEV Post from Mar 24

Netlify CMS or Forestry.io?

As I'm self-documenting and making choices for my new projet's JAMStack, I struggle deciding between these two (awesome-looking) Git-based CMS tools.

Daniel da Rocha profile image
architect turned dev

DEV hosts thousands of valuable blog posts and discussions.

And it's free