react django отрисовывает тот же контент

#django #reactjs #rendering

#django #reactjs #рендеринг

Вопрос:

Я работаю над проектом Django-react и у меня проблема с рендерингом компонента React на сервере Django. Если быть точным, React всегда предоставляет мне один и тот же контент, даже если я его изменяю. Я использую Webpack, Babel-loader и запускаю его на localhost.

project/templet/frontend/index.html

 <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">   
  <title>Django-React</title>
</head>
<body>

    <div id="app" class="columns"><!-- React --></div>
	{% load static %}
	<script  type='text/javascript' src="{% static "frontend/main.js" %}"></script>
</body>

</html>  

Точка входа:

 import ReactDOM from "react-dom";
import App from './components/App';

ReactDOM.render(<App/>, document.getElementById("app"));  

Скрипты в package.json:

   "scripts": {
    "dev": "webpack --mode development ./frontend/src/index.js --watch ./frontend/static/frontend/main.js",
    "build": "webpack --mode production ./frontend/src/index.js --output ./frontend/static/frontend/main.js"
  }  

Конфигурация Babel:

 module.exports = {
  module: {
    rules: [
      {
        test: /.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};  

Итак, когда я пишу некоторый контент в компоненте приложения (например, визуализирую div с помощью «test») Я вижу это в своем браузере, но когда я хочу его изменить и после обновления страницы получаю тот же контент из тега div

Ответ №1:

Из того, что я могу понять из вашего вопроса, когда вы впервые рендерите div с ‘test’ в нем, он рендерится, но после этого дальнейшие изменения не обновляются.

Это потому, что javascript не обновляется в Django, и вам нужно использовать collectstatic для синхронизации сборок, что не очень эффективно.

Для этого нужно использовать django-webpack-loader и webpack-bundle-tracker.

установите webpack-bundle-tracker

npm install —save-веб-пакет разработки-bundle-tracker

установите django-webpack-loader:

pip-установка django-webpack-loader

django-webpack-loader — это пакет python, который вставляет ссылку и тег script для пакетов, которые webpack генерирует динамически.

плагин для отслеживания пакетовwebpack передает необходимую информацию о процессе компиляции webpack в файл json, чтобы django-webpack-loader мог ее использовать.

Чтобы webpack мог отслеживать изменения, внесенные в ваше приложение, вам необходимо создать сервер, который отслеживает изменения в вашем приложении React и объединяет ваш JS.

Примечание: Мы используем сервер узла.

 // Webpack Server

const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('./webpack.server.config');

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  inline: true,
  historyApiFallback: true
}).listen(3000, '0.0.0.0', function (err, result) {
  if (err) {
    console.log(err)
  }

  console.log('Listening at 0.0.0.0:3000')
});
  

Конфигурационные файлы, используемые webpack.server.js было бы в webpack.server.config.js

 // webpack.server.config.js

const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');

module.exports = {
    mode: 'development',

    entry: {
        main: './frontend/src/index.js',
        devServer: 'webpack-dev-server/client?http://localhost:3000'
    },

    output: {
        filename: "[name].js",
        path: path.resolve('./frontend/static/frontend/bundles/'),
        publicPath: 'http://localhost:3000/frontend/static/frontend/bundles/', // django-webpack-loader overrides django's STATIC_URL with this path
    },

    plugins: [
        new BundleTracker({filename: './frontend/webpack-stats.json'}), // Pass the correct path to the WEBPACK_LOADER in django settings
    ],

    devServer: {
        contentBase: './frontend/static/frontend/bundles/',
    },
};
  

Обратите внимание, что сервер по умолчанию будет хранить пакеты в памяти и
не выполняется запись на диск

Когда сервер остановлен, не будет никаких признаков связанных файлов, поскольку они не были скомпилированы в память.

Чтобы сохранить ваши файлы в памяти при разработке, создайте другой конфигурационный файл по адресу webpack.dev.config.js

 // webpack.dev.config.js

const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');

module.exports = {
    mode: 'development',

    entry: {
        main: './frontend/src/index.js',
    },

    output: {
        filename: "[name].js",
        path: path.resolve('./frontend/static/frontend/bundles/'),
    },

    plugins: [
        new BundleTracker({filename: './frontend/webpack-stats.json'}), // Pass the correct path to the WEBPACK_LOADER in django settings
    ],

};
  

Пока для сборки ваших файлов для производства создайте другой конфигурационный файл по адресу webpack.prod.config.js

 // webpack.prod.config.js

const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');

module.exports = {
    mode: 'production',

    entry: {
        main: './frontend/src/index.js',
    },

    output: {
        filename: "[name].js",
        path: path.resolve('./frontend/static/frontend/dist/'),
    },

    plugins: [
        new BundleTracker({filename: './frontend/webpack-stats-prod.json'}), // Pass the correct path to the WEBPACK_LOADER in django settings
    ],

};
  

В ваших настройках Django;

 import sys
import os

# Assuming this is your base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Also assuming this is your base directory
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'), 

# In development
WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'bundles/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), # Path to 'webpack-stats.json'
    }
}

# In production
if not DEBUG:
    WEBPACK_LOADER['DEFAULT'].update({
        'BUNDLE_DIR_NAME': 'dist/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-prod.json') # Path to 'webpack-stats-prod.json'
    })

INSTALLED_APPS = (
 ...
 'webpack_loader',
)
  

Ваш index.html теперь должно выглядеть так;

 {% load render_bundle from webpack_loader %}  <<< Add this.
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">   
  <title>Django-React</title>
</head>
<body>

    <div id="app" class="columns">
        <!-- React -->
    </div>

    {% render_bundle 'main' %}  <<< Add this.

</body>

</html>
  

Теперь Ваш package.json должен выглядеть следующим образом;

 "scripts": {
    "dev": "node ./webpack.server.js",
    "build-dev": "webpack --mode development --config ./webpack.dev.config.js",
    "build-prod": "webpack --mode production --config ./webpack.prod.config.js"
  }
  

Итак, для разработки с автоматическим объединением просто запустите:

npm запускает разработку

Чтобы сохранить ваши файлы в памяти после остановки сервера webpack, просто запустите:

сборка при запуске npm-dev

И, наконец, для сборки с производственной оптимизацией просто запустите:

сборка запуска npm-prod

Я пытался внести изменения в ваш проект, чувствую, что нужно подстроиться в соответствии со структурой вашего проекта. Проверьте приведенные ниже ссылки, чтобы лучше ориентироваться. Они мне помогли!

Ссылки:

  1. Давайте усовершенствуем способ обработки интерфейса с помощью Django
  2. Прозрачное использование Webpack с Django горячая перезагрузка компонентов React в качестве бонуса
  3. Современный Django: Часть 1. Настройка Django и React

Комментарии:

1. Спасибо вам, ОБА, постараюсь реализовать это после прочтения ссылок 🙂