带有 vue.js 前端的 Django - 静态文件路径

Django with vue.js frontend - Static Files Path

我正在尝试使用 vue 前端提供 django 应用程序,需要一些配置静态文件的帮助。

问题 TLDR:

如何让 Django 将此构建路径识别为尝试访问静态文件,或者如何修改 Vue 端的 post-build 注入路径以匹配当前 Django静态文件设置?

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

构建来自前端目录 运行,使用 --no-clean 不删除构建时我的 django 模板文件夹。

这是我将 {% static %} 标签添加到构建的 index.html 的解决方法。我意识到我打破了 vue 的约定,因为 assetsDir 是 outputDir 的子目录,我不反对向 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>

My django settings.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' %}">

更改 vue.config.js 中的 assetsDir 路径以匹配将资产作为 outputDir 的子目录的 Vue 约定会导致类似的问题,其中路径是 'app/assets/js/...' 而不是 'js/...'

我决定通过修改 public/index.html 文件以及 vue.config.js 选项来调整在 Vue 构建期间加载到模板中的路径。我在 vue.config.js 中声明了一个 const asset_dir = '/asset/dir,然后将其作为额外选项添加到 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>