vue.jsフロントエンドを使用したDjango-静的ファイルパス

Aug 19 2020

vueフロントエンドでdjangoアプリを提供しようとしていますが、静的ファイルの構成についてサポートが必要です。

質問TLDR:

Djangoにこのビルドされたパスを静的ファイルに到達する試みとして認識させるにはどうすればよいですか?あるいは、現在のDjango静的ファイルの設定に一致するようにVue側のビルド後のインジェクションパスを変更するにはどうすればよいですか?

Djangoはvueからビルドされたindex.htmlを提供しますが、パスが「絶対」であるため、ビルドプロセスから自動挿入された静的ファイル(scripts / css)を見つけることができません。スクリプトを自動挿入しないようにvue.config.jsを変更しました({% static %}ビルド中にスクリプトが必要になるため、およびテンプレートindex.htmlでスクリプトを適切に追加します。

私のディレクトリ構造は次のとおりです。

- Root
  - app
  - migrations
  - templates
    - app (outputDir)
      - index.html (Built from vue)
      - base.html
      - templateFolder1
      - templateFolder2
  - various .py files
  - assets (assetsDir)
    - css
      - static files
    - js
      - static files
  - frontend
    - public
      - index.html (Template for build for vue)
    - src
    - assets
    - components
    - App.vue
    - main.js

ビルドはフロントエンドディレクトリから実行され、ビルド時にdjangoテンプレートフォルダを削除しないように--no-cleanを指定します。

{% static %}ビルドされたindex.htmlにタグを追加するための回避策は次のとおりです。私は、assetsDirがoutputDirのサブディレクトリであるという規則に違反していることに気付き、慣例に一致するように別のstaticfile dirをsettings.pyに追加することに反対していません(私の問題は同じですが)。

vue.config.js

publicPath: isProd ? '/app/' : '/',
outputDir: __dirname + '/../app/templates/app',
assetsDir: "../../../assets",
indexPath: './index.html',
configureWebpack: {
        ...
        plugins: [
            new HtmlWebpackPlugin({
                template: __dirname + '/public/index.html',
                favicon: __dirname + '/../assets/img/favicon/favicon.ico',
                inject: false,
                minify: false
            })
        ],
    },

public / index.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>MAPP Remote</title>
      <link rel="shortcut icon" href="{% static '<%= htmlWebpackPlugin.files.favicon %>' %}">
      <% for (key in htmlWebpackPlugin.files.css) { %> <link rel="stylesheet" href="{% static '<%= htmlWebpackPlugin.files.css[key] %>' %}"> <% } %>
  </head>
    <body>
    ...
    <div id="app"></div>

    <!-- built files will be auto injected -->
  <% for (key in htmlWebpackPlugin.files.js) { %> <script type="text/javascript" src="{% static '<%= htmlWebpackPlugin.files.js[key] %>' %}"></script> <% } %>
  </body>
</html>

構築されたindex.html:

app / templates / app / index.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>MAPP Remote</title>
      <link rel="shortcut icon" href="{% static '/app/favicon.ico' %}">
       <link rel="stylesheet" href="{% static '/app/../../../assets/css/chunk-vendors.0ba3e87d.css' %}">  <link rel="stylesheet" href="{% static '/app/../../../assets/css/app.fb012fc8.css' %}"> 
  </head>
  <body>
    ...
    <div id="app"></div>

    <!-- built files will be auto injected -->
   <script type="text/javascript" src="{% static '/app/../../../assets/js/chunk-vendors.6a3b11f1.js' %}"></script>  <script type="text/javascript" src="{% static '/app/../../../assets/js/app.45295baa.js' %}"></script> 
  </body>
</html>

静的ファイルのdjangosettings.py構成:

Settings.py

...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = "/static/"
STATICFILES_DIRS = [os.path.join(BASE_DIR, "assets")]
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
...

Djangoを介して静的ファイルファインダーを構成する方法では、app / templates / app /index.html内のビルドされたscript / cssパスを変更する必要があります。

の代わりに <script src="{% static '/app/../../../assets/js/chunk-vendors.6a3b11f1.js' %}">

パスは現在、 <script src="{% static 'js/chunk-vendors.6a3b11f1.js' %}">

アセットをoutputDirのサブディレクトリにするというVueの規則に一致するように、vue.config.jsのassetsDirパスを変更すると、パスが'app/assets/js/...'ではなく、同様の問題が発生します。'js/...'

回答

1 plum0 Aug 19 2020 at 03:16

public / index.htmlファイルとvue.config.jsオプションを変更して、Vueビルド中にテンプレートに読み込まれるパスを調整することにしました。const asset_dir = '/asset/dirvue.config.jsで宣言し、これをHtmlWebpackPluginに追加オプションとして追加して、テンプレートにプルしました。最後に、静的ファイルのパスを、パスの不要な部分の長さで部分文字列化します。

vue.config.js

const asset_dir = "../../../assets"

module.exports = {
    publicPath: isProd ? '/app/' : '/',
    outputDir: __dirname + '/../app/templates/app',
    assetsDir: asset_dir,
    indexPath: './index.html',
    configureWebpack: {
        ...
        plugins: [
            new HtmlWebpackPlugin({
                template: __dirname + '/public/index.html',
                inject: false,
                minify: false,
                assetsDir: asset_dir
            })
        ],
    }
}

public / index.html

{% load static %}
<% if (htmlWebpackPlugin.options['assetsDir'] !== undefined) { %> <% var assetDirLength = htmlWebpackPlugin.options['assetsDir'].length + htmlWebpackPlugin.files.publicPath.length + "/".length%> <% } %>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>MAPP Remote</title>
      <link rel="shortcut icon" href="{% static 'img/favicon/favicon.ico' %}">
      <% for (key in htmlWebpackPlugin.files.css) { %> <link rel="stylesheet" href="{% static '<%= htmlWebpackPlugin.files.css[key].substr(assetDirLength) %>' %}"> <% } %>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <!-- Pulled from htmlWebpackPlugin Docs -->
    <!-- https://github.com/jaketrent/html-webpack-template/blob/86f285d5c790a6c15263f5cc50fd666d51f974fd/index.html -->
    <% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
      <script src="{% static '<%= htmlWebpackPlugin.files.chunks[chunk].entry.substr(assetDirLength) %>' %}"></script>
    <% } %>

  </body>
</html>