# Build Process This document describes the build process of a theme, built using Sphinx Theme Builder (`stb`). In other words, this document serves as an elaborate answer to the question: "What happens when I run `stb compile` or `stb package`?" (asset-generation)= ## Asset Generation ### nodeenv creation `stb` invokes {pypi}`nodeenv`, in a subprocess and creates an isolated installation of NodeJS in a `.nodeenv` directory. If a `.nodeenv` directory already exists, this step is skipped. ### nodeenv validation Once `stb` has a nodeenv available, it will run `node --version` using the nodeenv's `node` and validate that it matches the requirements of the theme. This serves as a validation check to ensure that the user does not incorrectly use a broken nodeenv (in which case, `node` will fail to run) or a NodeJS version that is incompatible with the theme (which can happen in some situations). Even when the nodeenv was just created, this serves as a sanity-check that the nodeenv that has been created is indeed functional and valid. ### `npm install` Once the nodeenv is created, the JS dependencies of the theme are installed by running `npm install` using from the nodeenv. This will create a `node_modules` directory containing these dependencies. If a `node_modules` directory already exists and is newer than the `package.json` file, this step is skipped. ### `npm run-script build` With all the NodeJS dependencies of the theme installed, the NodeJS-based build is performed by `npm` from the nodeenv. This build is done by using `npm run-script build` which looks at the `"build"` key in the `"scripts"` section of `package.json`. For a package that uses [Webpack] for performing their JS build, this would mean that the `package.json` would look something like: ```json { "devDependencies": { "webpack": "...", "webpack-cli": "..." }, "scripts": { "build": "webpack" } } ``` This command is expected to generate the compiled assets for the theme. If the theme's `build` command is being executed, everything that `stb` does is working correctly. [webpack]: https://webpack.js.org/ ## Python Packaging stuff `stb package` dispatches the task of performing the build to the {pypi}`build` project, by invoking it in a subprocess. The build project orchestrates the details of the build process and ends up invoking `stb`'s build logic, in the appropriate manner. The build project generates a source distribution, unpacks it and builds a wheel from the unpacked source distribution. ## Source Distribution For generating the source distribution, `stb` will generate a tarball that contains files from the `src/` directory of the project. Certain files are not included in this tarball, based on the following rules: - Exclude hidden files. - Exclude `.pyc` files. - Exclude compiled assets. - Exclude files that are excluded from version control (only git is supported). ## Wheel Distribution For generating the wheel distribution, `stb` will generate the theme's assets in production mode (using the {ref}`asset-generation` process described above). Once this is generated, `stb` will generate a wheel file containing the package metadata and all the files in the `src/` directory. ```{caution} It is expected that wheels would only be generated from unpacked source distributions. Attempting to generate a wheel from the source tree directly may result in incorrect contents in the wheel. ``` (controlling-nodejs)= ## Appendix: Controlling NodeJS installation {pypi}`nodeenv` will prefer to use pre-built binaries, if they're available for the platform that the build is taking place on. If a pre-built binary is not available, it tries to build NodeJS from source on the machine. By default, the pre-built binaries are fetched from: - for supported platforms - for musl-based platforms It is possible to configure the behaviour of `nodeenv` using [a `~/.nodeenvrc` file][nodeenv-configuration] to change its behaviour, such as whether it uses a pre-built binary or what mirror it downloads from. [nodeenv-configuration]: https://github.com/ekalinin/nodeenv#configuration ### `STB_USE_SYSTEM_NODE` When set to `true` or `1`, `stb` will ask {pypi}`nodeenv` to use the `node` executable available on `PATH`, for creating the nodeenv. This functionality is primarily for software redistributors who have policies against using prebuilt binaries from the NodeJS team, such as the ones that `nodeenv` tries to use by default. ### `STB_RELAX_NODE_VERSION_CHECK` When set to `true` or `1`, `stb` will _not_ enforce that the NodeJS version in the `.nodeenv` directory exactly match the declared version in the theme. Instead, the check changes to ensuring that it has the same major version and an equal-or-higher minor version. The patch version is ignored. This functionality is primarily for software redistributors who wish to use newer-but-still-compatible versions of the NodeJS.