通过 Pyramid 控制台脚本绑定Static Assets

现代应用程序通常需要某种构建步骤来为开发或生产环境绑定Static Assets。这个方法演示了如何构建一个可以帮助完成这个任务的控制台脚本。它还试图满足典型的要求:

  • 前端源代码可以作为python包分发。

  • 在构建过程中,源代码的存储库和站点包不会写入。

  • 使通过多个Static Assets包在应用程序中提供插件架构成为可能。

  • 应用程序的主目录是构建过程的目标目录,以方便Web服务器提供HTTP服务。

  • 灵活-允许任何前端工具集(纱线,Webpack,卷起等)的JavaScript,CSS,和图像捆绑,以组成更大的管道。

演示

这个配方包括一个演示应用程序。The source files are located on GitHub:

https://github.com/Pylons/pyramid_cookbook/tree/master/docs/static_assets/bundling

演示是从 Pyramid starter cookiecutter .

在目录中 bundling 有两个目录:

  • bundling_example 是从cookiecutter生成的 Pyramid 应用程序,带有一些额外的文件和修改,如本说明手册所述。

  • frontend 包含前端源代码和文件。

您可以从starter cookiecutter生成一个项目,安装它,然后按照这个配方的其余部分进行操作。如果遇到任何问题,请将您的项目与演示项目源文件进行比较,以了解可能有什么问题。

要求

This recipe and the demo application both require YarnNodeJS 8.x packages to be installed.

配置 Pyramid

首先,我们需要告诉Pyramid从一个额外的构建目录提供静态内容。这对开发很有用。在生产中,这通常由nginx处理。

在配置文件中, [app:main] 部分,添加生成过程的位置:

# build result directory
statics.dir = %(here)s/static
# intermediate directory for build process
statics.build_dir = %(here)s/static_build

在应用程序的路由中,添加Static Assets视图和资产覆盖配置:

 1import pathlib
 2# after default static view add bundled static support
 3config.add_static_view(
 4    "static_bundled", "static_bundled", cache_max_age=1
 5)
 6path = pathlib.Path(config.registry.settings["statics.dir"])
 7# create the directory if missing otherwise pyramid will not start
 8path.mkdir(exist_ok=True)
 9config.override_asset(
10    to_override="yourapp:static_bundled/",
11    override_with=config.registry.settings["statics.dir"],
12)

现在,在您的模板中,引用已构建和绑定的Static Assets。

<script src="{{ request.static_url('yourapp:static_bundled/some-package.min.js') }}"></script>

控制台脚本

创建目录 scripts 在应用程序的根目录。添加空 __init__.py 将文件保存到该子目录,使其成为python包。同样,在此子目录中,创建一个文件 build_static_assets.py 作为控制台脚本使用以下代码编译资产。

 1import argparse
 2import json
 3import logging
 4import os
 5import pathlib
 6import shutil
 7import subprocess
 8import sys
 9
10import pkg_resources
11from pyramid.paster import bootstrap, setup_logging
12
13log = logging.getLogger(__name__)
14
15
16def build_assets(registry, *cmd_args, **cmd_kwargs):
17    settings = registry.settings
18    build_dir = settings["statics.build_dir"]
19    try:
20        shutil.rmtree(build_dir)
21    except FileNotFoundError as exc:
22        log.warning(exc)
23    # your application frontend source code and configuration directory
24    # usually the containing main package.json
25    assets_path = os.path.abspath(
26        pkg_resources.resource_filename("bundling_example", "../../frontend")
27    )
28    # copy package static sources to temporary build dir
29    shutil.copytree(
30        assets_path,
31        build_dir,
32        ignore=shutil.ignore_patterns(
33            "node_modules", "bower_components", "__pycache__"
34        ),
35    )
36    # configuration files/variables can be picked up by webpack/rollup/gulp
37    os.environ["FRONTEND_ASSSET_ROOT_DIR"] = settings["statics.dir"]
38    worker_config = {'frontendAssetRootDir': settings["statics.dir"]}
39    worker_config_file = pathlib.Path(build_dir) / 'pyramid_config.json'
40
41    with worker_config_file.open('w') as f:
42        f.write(json.dumps(worker_config))
43    # your actual build commands to execute:
44
45    # download all requirements
46    subprocess.run(["yarn"], env=os.environ, cwd=build_dir, check=True)
47    # run build process
48    subprocess.run(["yarn", "build"], env=os.environ, cwd=build_dir, check=True)
49
50
51def parse_args(argv):
52    parser = argparse.ArgumentParser()
53    parser.add_argument("config_uri", help="Configuration file, e.g., development.ini")
54    return parser.parse_args(argv[1:])
55
56
57def main(argv=sys.argv):
58    args = parse_args(argv)
59    setup_logging(args.config_uri)
60    env = bootstrap(args.config_uri)
61    request = env["request"]
62    build_assets(request.registry)

编辑应用程序 setup.py 在安装将用于启动编译过程的应用程序时创建shell脚本。

 1setup(
 2    name='yourapp',
 3    ....
 4    install_requires=requires,
 5    entry_points={
 6        'paste.app_factory': [
 7            'main = channelstream_landing:main',
 8        ],
 9        'console_scripts': [
10            'yourapp_build_statics = yourapp.scripts.build_static_assets:main',
11        ]
12    },
13)

安装应用程序

pip install -e . 再次注册控制台脚本。

现在,您可以使用webpack/gulp/rollup或其他解决方案配置/运行前端管道。

编译Static Assets

最后,我们可以从前端编译Static Assets并将其写入我们的应用程序。

运行命令:

yourapp_build_statics development.ini

这将启动生成过程。它创造了一个新的 static directory in the same location as your application's ini 文件。The directory should contain all the build process files ready to be served on the web.

您可以在节点构建配置文件中从Pyramid应用程序中检索变量:

destinationRootDir = process.env.FRONTEND_ASSSET_ROOT_DIR

您可以查看生成的 pyramid_config.json Node 脚本中的文件以获取其他信息。