manage.py runserver能够执行npm脚本吗?

5
我正在使用React作为前端和Django作为后端开发Web应用程序。我使用Webpack来监视更改并捆绑React应用程序的代码。
问题是我必须同时运行两个命令,一个用于React,另一个用于Django:
webpack --config webpack.config.js --watch
./manage.py runserver

有没有办法自定义runserver命令来执行npm脚本,比如npm run start:dev?当你使用Node.js作为后端平台时,你可以做类似的工作,比如npm run build:client && npm run start:server


你有没有研究过使用Grunt或Gulp来运行这两个任务? - turbotux
3个回答

2
如果您已经在使用webpack和django,则可能会对使用webpack-bundle-tracker和django-webpack-loader感兴趣。
基本上,webpack-bundle-tracker将在每次构建捆绑包时创建一个stats.json文件,而django-webpack-loader将监视这些stats.json文件以重新启动开发服务器。这个堆栈允许在服务器和客户端之间分离关注点。
几篇文章解释了这个流程。

2

虽然有点晚了,但这里提供一个管理命令,实现了OP想要的解决方案,而不是重定向到另一个解决方案。它继承自静态文件运行服务器,并在线程中同时运行webpack。

<some_app>/management/commands/my_runserver.py中创建此管理命令:

import os
import subprocess
import threading

from django.contrib.staticfiles.management.commands.runserver import (
    Command as StaticFilesRunserverCommand,
)
from django.utils.autoreload import DJANGO_AUTORELOAD_ENV


class Command(StaticFilesRunserverCommand):
    """This command removes the need for two terminal windows when running runserver."""

    help = (
        "Starts a lightweight Web server for development and also serves static files. "
        "Also runs a webpack build worker in another thread."
    )

    def add_arguments(self, parser):
        super().add_arguments(parser)
        parser.add_argument(
            "--webpack-command",
            dest="wp_command",
            default="webpack --config webpack.config.js --watch",
            help="This webpack build command will be run in another thread (should probably have --watch).",
        )
        parser.add_argument(
            "--webpack-quiet",
            action="store_true",
            dest="wp_quiet",
            default=False,
            help="Suppress the output of the webpack build command.",
        )

    def run(self, **options):
        """Run the server with webpack in the background."""
        if os.environ.get(DJANGO_AUTORELOAD_ENV) != "true":
            self.stdout.write("Starting webpack build thread.")
            quiet = options["wp_quiet"]
            command = options["wp_command"]
            kwargs = {"shell": True}
            if quiet:
                # if --quiet, suppress webpack command's output:
                kwargs.update({"stdin": subprocess.PIPE, "stdout": subprocess.PIPE})
            wp_thread = threading.Thread(
                target=subprocess.run, args=(command,), kwargs=kwargs
            )
            wp_thread.start()
        super(Command, self).run(**options)

对于任何试图编写从runserver继承的命令的人来说,请注意需要检查DJANGO_AUTORELOAD_ENV变量,以确保您不会在每次Django注意到.py文件更改时都创建一个新线程。 Webpack应该正在执行自己的自动重新加载。
使用--webpack-command参数来更改运行的webpack命令(例如,我使用--webpack-command 'vue-cli-service build --watch')
使用--webpack-quiet来禁用命令的输出,因为它可能会变得混乱。
如果您真的想覆盖默认的runserver,请将文件重命名为runserver.py,并确保其所在的应用程序在您的设置模块的INSTALLED_APPS中位于django.contrib.static之前。

0

你不应该搞乱内置的管理命令,但是你可以自己创建:https://docs.djangoproject.com/en/1.10/howto/custom-management-commands/

如果是我,我会保留runserver并创建一个运行你自定义(在这种情况下是npm)脚本的命令,例如使用os.execvp

理论上,你可以运行两个并行的子进程,一个执行django.core.management.execute_from_command_line,另一个运行你的脚本。但这会使像pbd这样的工具无法使用(这会让工作变得非常困难)。

我的做法是利用Docker和Docker compose。然后当我使用docker-compose up -d时,我的数据库服务、npm脚本、redis等在后台运行(单独运行runserver是另一个话题)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接