Skip to main content

page_react_dep

page_react_dep(src_dir=None, js_file='ui.js', css_file='ui.css', name=None)

Build an HTMLDependency for a React app’s JS and CSS entry points.

The JS file’s mtime is the dependency version, so the /lib/<name>-<version>/ URL changes on every rebuild and the browser re-fetches. That is what you want while developing, and the wrong thing for a published package — an mtime is whatever the install happened to write, so it is neither stable across machines nor meaningful to a reader. There is no version= here on purpose: a package shipping a fixed version should build its own :class:~htmltools.HTMLDependency (the same advice as for a classic, non-module bundle), which is five lines and leaves nothing about the dependency implicit.

Both the script and the stylesheet are attached only when the file exists inside the resolved src_dir, so a bundle that ships no CSS — or that has not been built yet — does not emit a tag pointing at a 404. Pass css_file=None to never attach a stylesheet. A missing js_file warns, since it is the entry point and an empty dependency would otherwise fail silently.

A missing src_dir raises :class:NotADirectoryError, where a missing js_file only warns. The asymmetry is not arbitrary: Shiny mounts the dependency’s source directory as static files, so a directory that does not exist is fatal no matter what this function does — the only question is whether the author gets Starlette’s Directory '...' does not exist from inside App.__init__, or a message naming the argument that chose the path. Matches R’s page_react_dep().

Path resolution

The base directory is src_dir when given. Passing it explicitly is recommended for library authors — the inference below reads the immediate calling frame, so wrapping this function in a helper resolves against the wrapper’s directory rather than the app’s.

When src_dir is omitted it is inferred:

  1. Module call (typical): when the caller is a regular Python module (__file__ set), paths resolve against the module’s directory. This is the expected usage::

    # /path/to/my-app/app.py
    from shinyreact import page_react_dep
    
    dep = page_react_dep(js_file="bundle.js")
    # dep.source["subdir"] == "/path/to/my-app"
    # dep.name == "my-app"
    # version == mtime of /path/to/my-app/bundle.js
  2. REPL / exec’d code (no __file__): falls back to :func:pathlib.Path.cwd — the current working directory of the process. This matches the convention CLI tools use when resolving relative paths::

    >>> import os, shinyreact
    >>> os.chdir("/path/to/my-app")
    >>> shinyreact.page_react_dep(js_file="bundle.js")
    # source["subdir"] == "/path/to/my-app"
    # name == "my-app"

    The fallback is deliberate — call from any working directory and you get a predictable result. If you need a specific directory regardless of CWD, pass src_dir.

Args: src_dir: Directory containing the JS/CSS. Inferred from the calling frame when omitted (see above). js_file: Filename of the JS entry point, relative to src_dir (default "ui.js"). Attached only if the file exists. css_file: Filename of the CSS file, relative to src_dir (default "ui.css"). Attached only if the file exists; None to skip. name: Dependency name. Defaults to src_dir’s basename.