Skip to main content

Hatch NodeJS Build

PyPI - Version

A plugin for Hatch that allows you to run Node.js builds and include the build artifacts in your Python package.

Installation

To set up hatch-nodejs-build, set hatchling as your build backend, and add hatch-nodejs-build as a dependency, and as a Hatch build hook:

[build-system]
requires = ["hatchling", "hatch-nodejs-build"]
build-backend = "hatchling.build"

[tool.hatch.build.hooks.nodejs-build]

Including simply the table header as shown here is valid minimal TOML to enable the hook. Additional configuration of the plugin is added here as well.

Usage

The plugin allows you to build a JavaScript bundle with npm run build (by default, see configuration). Include your Node assets in a folder called /browser, and it will be included in your Python package.

A minimal React app using esbuild would look as follows:

/
├─ my_python_module/
│  └─ __init__.py
└─ browser/
   ├─ src/
   │  └─ index.jsx
   └─ package.json

browser/package.json

{
  "name": "my-react-esbuild-app",
  "version": "1.0.0",
  "description": "A minimal React app using ESBuild",
  "type": "module",
  "scripts": {
    "build": "esbuild src/index.jsx --bundle --outfile=dist/bundle.js --format=iife --minify",
    "watch": "esbuild src/index.jsx --bundle --outfile=dist/bundle.js --format=iife --sourcemap --watch"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "esbuild": "^0.18.0"
  }
}

browser/src/index.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';

const App = () => {
  return <h1>Hello, React with ESBuild in a Python package!</h1>;
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

After the build, the Python package would include bundle/bundle.js. See Runtime for more information on different ways to launch your JavaScript bundle when a user uses your package.

Build & build configuration

The default build uses the /browser directory in your repository as the source directory, and bundles the output (from the /browser/dist directory) in the output distribution in the bundle directory.

The steps of a build are as follows:

  • Check /browser/package.json for Node.js requirements.
  • Use Node.js found on PATH
    • If no matching version is found, install LTS version in cache.
  • Run npm install in /browser
  • Run npm run build in /browser
  • Include /browser/dist in output as /bundle

The build can be configured in the following ways:

Key Default Description
node_executable "node" Path to node executable to use.
lts True Only install LTS versions.
install_command "npm install" The command to run to initialize the Node environment.
build_command "npm run build" The command to run to build the artifacts.
source_dir "browser" The location where the JavaScript source assets are stored.
artifact_dir "dist" The location relative to the source directory where the build artifacts end up.
bundle_dir "bundle" The location in the Python package output the bundle should be included at.
inline_bundle False Inline the JavaScript bundle {artifact_dir}/bundle.js in {source_dir}/index.html.

If you need to make changes to the configuration, specify them in the build hook configuration:

[tool.hatch.build.hooks.nodejs-build]
source_dir = "src/web"
bundle_dir = "web"

Runtime

Using hatch-nodejs-build you can include the bundle in your package, but that doesn't open the app yet when someone uses your package.

There are a few things to consider, for example, the user's target machine might not have the Node.js runtime available, so hatch-nodejs-build works best, and focuses on frontend application bundles to be run in the browser.

Most web bundlers create bundles that span multiple files/chunks so that the web app can be loaded incrementally for faster load times, and the bundle has to be served from an HTTP server. Spawning and controlling an HTTP server from Python create challenging restrictions on the architecture of your code. It can be a lot simpler for small applications to inline the JavaScript bundle in an HTML file and have the user's platform open it for you.

Inlining the bundle

hatch-nodejs-build supports simple inlining of your built bundle if the inline_bundle setting is turned on. It will look for a file called index.html in the source directory, and will inline the JavaScript and CSS bundles into the placeholders:

/
├─ my_python_module/
│  └─ __init__.py
└─ browser/
   ├─ src/
   │  ├─ index.css
   │  └─ index.jsx
   │  index.html
   └─ package.json
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Sample React App</title>
    <style data-bundle-css></style>
  </head>
  <body>
    <div id="root"></div>
    <script data-bundle-js></script>
  </body>
</html>

Your Python package will then include bundle/index.html instead of bundle/bundle.js, and you can simply:

import pathlib
import webbrowser

webbrowser.open(pathlib.Path(__file__).parent / "bundle" / "index.html")

Your code will not block and simply continue its execution.

Running through an HTTP server

This is a simple example for an HTTP server. The Python process will be blocked while serving the HTTP server, so you'll likely want a better and event-loop or async-based solution:

import http.server
import socketserver
import os

PORT = 8000
web_dir = os.path.join(os.path.dirname(__file__), "static")
os.chdir(web_dir)

Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print(f"Serving at http://localhost:{PORT}")
    httpd.serve_forever()

Metadata

Release files for hatch-nodejs-build 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hatch-nodejs-build 1.1.1
File Size Uploaded Provenance Actions
hatch_nodejs_build-1.1.1.tar.gz 10.1 kB Without provenance Details for hatch_nodejs_build-1.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for hatch-nodejs-build 1.1.1
File Interpreter ABI Platform Actions
hatch_nodejs_build-1.1.1-py3-none-any.whl Python 3 none any Details for hatch_nodejs_build-1.1.1-py3-none-any.whl

Total release size: 21.1 kB

Release files / hatch_nodejs_build-1.1.1.tar.gz

Download URL hatch_nodejs_build-1.1.1.tar.gz
Size 10.1 kB
Tags Source
SHA-256 checksum
How to use checksums
919bba34c6b2188e614945c2db7333224cb451ba6567aee572ea533a78ae3706
BLAKE2b-256 checksum
How to use checksums
e4a370e45f1da83e2a62e0efa5445af7c910f677b4acb023a5a7b6bc58597b4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.28.1

Release files / hatch_nodejs_build-1.1.1-py3-none-any.whl

Download URL hatch_nodejs_build-1.1.1-py3-none-any.whl
Size 11.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6dcfdd7771ada46ad57f279787e0b21f5eb2d6da6d86ec062870cdd9bb97900
BLAKE2b-256 checksum
How to use checksums
5f44d092176369addb0927f94c1ef649f84d4ea3d29128cb025035443f4f7856
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.28.1

Security for hatch-nodejs-build 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page