LoginSignup
0
0

Flask + Webpack with VSCodeの開発環境

Last updated at Posted at 2023-10-31

概要

個人開発中のFlaskアプリでjavascriptが大きくなりすぎたため、jsファイルを分割して管理することにしました。

しかし分割しすぎるとパフォーマンスに問題がでるらしく、回避のためwebpackで数個のjsファイルにbundle(build)する形をとることにしました。

ここで困ってしまったのが、「FlaskとWebpackを併用する場合のフォルダ構造やデバッグ/ビルドの設定のあるべき姿」とは?という点です。

結局正解は分からないままなのですが、備忘録がてら自分がどうしたかを記載しておきます。

前提知識

Flaskとは

Webアプリのバックエンドをpythonで書くことができるフレームワークの1つです。他にはdjangoなどがあります。

Webpackとは

複数の JavaScript モジュールを一つ(またはいくつか)のファイルへバンドル(=bundle: 束にする、包む)してくれます。

モジュールを 1 つ(もしくは少数)にまとめることでブラウザからのリクエスト数を減らし、ファイル転送の効率が向上します。

採用した構造・設定

フォルダ構造

まずフォルダ構造については次のようにしました。
もともとFlaskアプリとして作っていたため、ちょっと歪な気がします。詳しい説明・今後修正したい点についてはコメントに記載の通りです。

root
├─.vscode
  ├─launch.json # webpackでbundle→front/distからstaticにコピー→run.pyを実行する設定を記載
  └─tasks.json # launch.jsonを構成する各タスクを定義
├─backend
  ├─routes #flaskのpyファイルを配置
  └─templates # front/back共用のため、rootに配置すべきだったかも。ここのhtmlファイルはstaticのjsをロードする。
├─env # venvの仮想環境 pythonに関わるもののためbackend下の方が適切かも
├─frontend
  ├─dist # ビルド(webpackのbundle)結果は一旦ここに配置
  ├─node_modules # node.jsのパッケージの実物
  ├─src # module毎にjsをbundleする(複数のbundleファイルを出力する)
     ├─moduleA
     └─moduleB
  ├─package.json # node.jsのパッケージのリストを記載
  └─webpack.config.js # webpackのbundle設定を記載
├─static # distからbundleしたjsをここにコピー。cssもここ
├─ run.py # app.run() flaskの実行処理を記載
├─ requests.txt # backend下の方が適切かも
├─ LICENSE.txt
└─ .gitignore

設定内容

launch.json, tasks.json, webpack.config.jsの設定内容は次の通り。
F5キーでwebpackのバンドルからFlaskの実行、ブラウザの起動を行います。

※jsonにコメントは本来書けないので、コピペの時はコメントを消してください。

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Flask with npm build",
            "type": "python",
            "request": "launch",
            "program": "./run.py",
            "console": "integratedTerminal",
            "justMyCode": true,
            "preLaunchTask": "build-and-copy-and-open-browser" //webpackのビルド,ビルド成果物のコピー,ブラウザ起動
        },
        {
            "name": "Flask Only",
            "type": "python",
            "request": "launch",
            "program": "./run.py",
            "console": "integratedTerminal",
            "justMyCode": true,
            "preLaunchTask": "open-browser", //ブラウザ起動
        }
    ]
}
tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      // ビルド
      "label": "build",
      "type": "shell",
      "command": "npm --prefix ./frontend run build", 
      "problemMatcher": []
    },
    {
      // ビルド成果物のコピー
      "label": "copy-js-files-from-dist-to-static",
      "type": "shell",
      "command": "cp ./frontend/dist/*.js ./static/", 
      "problemMatcher": []
    },
    {
      // ビルド&ビルド成果物のコピー
      "label": "build-and-copy",
      "dependsOn": ["build", "copy-js-files-from-dist-to-static"],
      "dependsOrder": "sequence",
      "problemMatcher": []
    },
    {
     // ブラウザ起動
      "label": "open-browser",
      "type": "shell",
      "command": "start http://localhost:5000",
      "problemMatcher": []
    },
    {
      // ビルド,ビルド成果物のコピー,ブラウザの起動
      "label": "build-and-copy-and-open-browser",
      "dependsOn": ["build-and-copy", "open-browser"],
      "dependsOrder": "sequence",
      "problemMatcher": []
    }    
  ]
}
webpack.config.js
const path = require('path');

module.exports = {

  devtool: 'source-map',
    devServer: {
        static: {
            directory: path.join(__dirname, 'dist'),  // 静的ファイルのディレクトリ
        },
        hot: true  // ホットモジュールリプレースメントを有効にする
    },
  mode: 'development',

  // エントリーポイント(主なJavaScriptファイル)
  entry: {
    'moduleA': './src/moduleA/main.js',
    'moduleB': './src/moduleB/main.js',
  },

  // 出力先は一旦dist
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname,'dist')
  },

};
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0