Flask + Webpack + Vue.js
Я очень привык к Django, питаю симпатию к Flask, время от времени играю с aiohttp. Короче говоря - я люблю использовать python для бэкенда.
И как всякий современный веб-разработчик, я увлеченно наблюдаю за той вакханалией, что творится в мире javascript. Конечно же, я тоже хочу в ней принять участие. Это желание стало особо острым после того, как пришлось по работе создать несколько проектов на Laravel (да простят меня питонщики), с интегрированным из коробки Vue.js. Ощущения были непередаваемые.
Но статей "Как перестать рефлексировать и наконец начать использовать современный javascript вместе с Flask" я нашел немного. О чем это я - да их почти нет! В итоге, пришлось протаптывать дорожку самому. И вот, когда поставленная цель была достигнута и был написан полноценный работающий проект, я решил написать эту статью, чтобы поделится своим опытом. Я покажу как организовал разработку Flask + Webpack + Vue.js на деле.
Предполагается, что читатель достаточно хорошо владеет разработкой под python и сможет настроить себе виртуальное окружение. Также, я уверен, что у вас уже установлен npm, а если нет, то можно ознакомиться со статьей.
Работать будем в 4 этапа:
-
Создадим простое Flask приложение.
-
Установим vue-cli и сгенерируем основу для vue приложения.
-
Настроим webpack для удобной работы с flask.
-
Соединим фронт с бэком с помощью ajax запросов.
Пишем бэкенд
Ставим себе Flask:
pip install Flask
создаем файл app.py со следующим кодом:
from flask import Flask, jsonify, send_from_directory
app = Flask(__name__, static_folder='static/dist')
@app.route('/')
def index():
# тут просто пробрасываем файлик, без всякого препроцессинга
return app.send_static_file("index.html")
@app.route('/dist/<path:path>')
def static_dist(path):
# тут пробрасываем статику
return send_from_directory("static/dist", path)
@app.route('/api/languages')
def languages():
# а это простой метод, который будет возвращать список языков программирования
# который мы потом с помощью vue.js будем отображать
return jsonify({
'languages': [
'assembly',
'c#',
'c',
'c++',
'go',
'java',
'javascript',
'object c',
'pascal',
'perl',
'php',
'python',
'R',
'ruby',
'SQL',
'swift',
'visual basic',
]
})
if __name__ == '__main__':
app.run()
Можно проверить работоспособность сервера, запустив его:
python app.py
и убедившись, что 127.0.0.1:5000/api/languages возвращает список языков в виде json объекта. Пока нет смысла обращаться к 127.0.0.1:5000/, так как этот url предполагает наличие файла index.html в папке static. А у нас пока такого файла нет.
Интегрируем vue.js в проект
Создаем папку static и переходим в нее:
mkdir static
cd static
Далее, устанавливаем vue-cli, желательно глобально (подробнее можно почитать тут):
npm install -g vue-cli
теперь инициализируем проект (я использую webpack-simple - шаблон инициализаци vue.js, потому что его очень удобно кастомизировать, в отличие от шаблона webpack, который заточен под nodejs разработку):
vue init webpack-simple .
отвечаем на вопросы, например, так:
и запускаем установку пакетов:
npm install
Ждем установки всех зависимостей. Когда все установится, открываем файл package.json и смотрим содержимое. Нас интересует группа scripts, которая определяет пользовательские команды, вызываемые через:
npm run action_name
По умолчанию нам предлагается две команды:
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
}
-
dev - запускает встроенный nodejs сервер для разработки с отслеживанием изменений в коде и автоматической перезагрузкой кода.
-
build - предназначена для сборки приложения для продакшена, то есть все, что можно будет минимизировать - будет минимизиованно, а вместо версии vue (для разработчиков), будет использованна "ужатая" версия.
Запустим сервер для разработки фронта:
npm run dev
Так как стоит флаг --open, то должен будет открыться браузер по адресу 127.0.0.1:8080/
А теперь в отдельном терминале запустим наш бэк:
python app.py
Попробуем открыть список языков 127.0.0.1:8080/api/languages/. Как и ожидалось, никакого списка языков нам не пришло. Нас все время выбрасывает на страницу с Vue приветствием. Как вы наверное догадались это потому что бэк у нас на одном порту, а сервер для фронта на другом. Чтобы решить эту проблему мы настроим прокси у фронт-сервера.
Открываем файлик webpack.config.js, находим строчки
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true,
},
и добавляем настройки прокси сервера, чтобы все запросы начинающиеся на api обрабатывались flask-сервером, которые у нас на 5000 порту:
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true,
proxy: {
"/api": "http://localhost:5000"
}
},
Теперь перезапустим сервер для фронт-разработки:
npm run dev
Если открыть http://localhost:8080/ то окажемся на странице vue приветствия, а если открыть http://localhost:8080/api/languages то увидем список языков в json формате.
Красота! Теперь можно убрать страницу по умолчанию и что-нибудь стянуть с сервера.
Соединяем фронт с бэком.
В vue из коробки не встроен пакет для работы с ajax запросами. Поэтому, нужно установить какой-нибудь (я предпочитаю axios):
npm install -S axios
Флаг -S я добавил, чтобы модуль зафиксировался в качестве зависимости проекта в package.json.
Теперь нам нужно очистить файл static/src/App.vue от лишнего кода:
<template>
<div id="app">
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
}
}
}
</script>
<style>
</style>
добавить переменную для хранения списка языков:
...
data () {
return {
languages: []
}
}
...
и отредактировать шаблон:
<template>
<div id="app">
<ul>
<li v-for="l in languages">{{ l }}</li>
</ul>
</div>
</template>
Если перезагрузить страницу, то мы ничего не увидим. Это потому, что список языков пустой. Воспользуемся библиотекой axios, чтобы получить список языков:
<script>
import axios from 'axios'
export default {
name: 'app',
data() {
return {
languages: []
}
},
created() {
axios.get("/api/languages").then(r => {
this.languages = r.data.languages
})
}
}
</script>
Так как мы используем фронт-сервер, он автоматически обновит код по мере его изменения, и сразу запросит список языков с сервера. Получим такую картинку:
Подведем итоги
Интегрировать vue с любым приложением, будь то flask, django или любой другой фреймворк, очень просто. Главный секрет заключается в настройки прокси для фронт-сервера и разработке при параллельной работе двух команд:
python app.py
и:
npm run dev
Одна отслеживает бэк, другая - фронт. Вот так все просто.