【问题标题】:Can manage.py runserver execute npm scripts?manage.py runserver 可以执行 npm 脚本吗?
【发布时间】:2017-07-18 17:40:13
【问题描述】:

我正在开发一个 Web 应用程序,其中 React 用于前端,Django 用于后端。我使用 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 来运行这两个任务?

标签: django reactjs webpack webpack-dev-server webpack-2


【解决方案1】:

如果你已经在使用 webpack 和 django,也许你会对使用 webpack-bundle-tracker 和 django-webpack-loader 感兴趣。

基本上 webpack-bundle-tracker 会在每次构建 bundle 时创建一个 stats.json 文件,而 django-webpack-loader 会监视那些 stats.json 文件以重新启动开发服务器。该堆栈允许分离服务器和客户端之间的关注点。

这条管道有a couple 的帖子explaining

【讨论】:

    【解决方案2】:

    我迟到了两年半,但这是一个实现 OP 想要的解决方案的管理命令,而不是重定向到另一个解决方案。它继承自静态文件 runserver 并在一个线程中并发运行 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.py,并确保它所在的应用程序在您的设置模块的 INSTALLED_APPS之前 django.contrib.static。 p>

    【讨论】:

      【解决方案3】:

      您不应该乱用内置的管理命令,但您可以自己制作: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,但这是另一个主题)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-16
        • 1970-01-01
        • 1970-01-01
        • 2015-10-13
        • 1970-01-01
        • 2019-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多