Django con frontend vue.js - Percorso file statici
Sto tentando di servire un'app django con un frontend vue e ho bisogno di aiuto per configurare i file statici.
La domanda TLDR:
Come faccio a far sì che Django riconosca questo percorso compilato come un tentativo di raggiungere un file statico o, in alternativa, come modifico il percorso di iniezione post-compilazione sul lato Vue in modo che corrisponda alle impostazioni correnti del file statico Django?
Django fornisce index.html compilato da vue, tuttavia non riesce a trovare i file statici (scripts / css) che vengono autoiniettati dal processo di compilazione a causa del percorso "assoluto". Ho modificato vue.config.js per non autoiniettare gli script (poiché ne avranno bisogno {% static %}
durante la compilazione e il template index.html per aggiungerli in modo appropriato.
La mia struttura di directory è la seguente:
- 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
La build viene eseguita dalla directory frontend, con --no-clean per non eliminare la mia cartella dei modelli django in build.
Ecco la mia soluzione alternativa per aggiungere {% static %}
tag al file index.html costruito. Mi rendo conto che sto infrangendo la convenzione che ha che assetsDir è una sottodirectory di outputDir, e non sono contrario ad aggiungere un'altra directory staticfile a settings.py per abbinare la convenzione (sebbene il mio problema sia sempre lo stesso).
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>
Il index.html costruito:
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>
La mia configurazione django settings.py per file statici:
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"
...
Il modo in cui i miei cercatori di file statici sono configurati tramite Django richiede la modifica dei percorsi script / css costruiti all'interno di app / templates / app / index.html.
Invece di <script src="{% static '/app/../../../assets/js/chunk-vendors.6a3b11f1.js' %}">
Il percorso attualmente deve essere <script src="{% static 'js/chunk-vendors.6a3b11f1.js' %}">
La modifica del percorso assetsDir in vue.config.js in modo che corrisponda alla convenzione di Vue di avere asset come sottodirectory di outputDir si traduce in un problema simile in cui il percorso è 'app/assets/js/...'
invece di'js/...'
Risposte
Ho deciso di regolare il percorso caricato nel modello durante la compilazione di Vue modificando il file public / index.html e le opzioni vue.config.js. Ho dichiarato un const asset_dir = '/asset/dir
in vue.config.js e poi l'ho aggiunto come opzione extra a HtmlWebpackPlugin per inserirlo nel modello. Infine, sottostringo il percorso per i file statici per la lunghezza della parte non necessaria del percorso.
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>