| .github/workflows | ||
| examples/print-bundle | ||
| src | ||
| .gitignore | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| LICENSE | ||
| README.md | ||
esbuild-bundle
This crate provides a very simple way of bundling JavaScript modules using esbuild with a
javascript! macro.
The javascript! expands to a literal string, and as such can be invoked wherever an expression
macro can be used. The macro takes an argument that is interpreted as a path to a JavaScript module.
The paths can include variable expansion, which can be useful when combined with the
CARGO_MANIFEST_DIR environment variable. The macro causes the JavaScript module to be bundled
using esbuild and writes the output to a bundle directory. The output bundle path is then output
from the macro.
The bundles directory is either specified directly in the javascript! macro invocation after a
=> symbol, or it is specified in a esbuild-bundle.json configuration file. As with the script
path, the bundle directory may also use environment variables such as CARGO_MANIFEST_DIR.
Here's a simple example. Let's assume that we have a scripts/my-module.js file relative to the
Cargo.toml file for our crate. We want to bundle this module into a bundles directory and then
print out the bundled path.
use esbuild_bundle::javascript;
pub fn main() {
let path = javascript!("${CARGO_MANIFEST_DIR}/scripts/my-module.js" => "bundles");
println!("output path: {path}");
}
When we compile this code, the JavaScript module in the scripts directory will get bundled into
the given bundles directory, and macro will expand to the output bundle. In this case, the bundles
directory was given as bundles.
During compilation, two files to be created in the bundles directory by the macro: the bundled
JavaScript file and a .bundles.json manifest file. The macro expands to the path to the bundled
JavaScript file as a string literal.
For example, the scripts/my-module.js module could get bundled to the file bundles/eUmAqV.js
(actual file name will be 32 characters). The script name (eUmAqV.js) is what will be printed out
by the program.
The .bundles.json manifest file is used to reduce replication, so that every input file is mapped
to the same random filename, rather than ending up with lots of bundles. Examining the
.bundles.json file we can see how this works for our example:
{
"/path/to/this/crate/scripts/my-module.js": "eUmAqV.js"
}
Configuration
Rather than specify the bundle path in every call of the javascript! macro, you can specify a
bundle_path in the esbuild-bundle.json configuration file. This file is expected to be found
adjacent to the Cargo.toml file for your crate; that is to say, the macro looks for the
configuration file under $CARGO_MANIFEST_DIR/esbuild-bundle.json.
In the above example, where bundles are written to the bundles directory, this can be configured
as follows:
{
"bundle_path": "${CARGO_MANIFEST_DIR}/bundles"
}
If the bundle path does not exist, it will be created.
Working Directory
When executing, the working directory is usually to location of the Cargo.toml (after all, this is
a Rust macro). However there may be times where this is not desirable. For example, in a Cargo
workspace you might have the package.json in a sub-crate and therefore will need to run the
esbuild command in that directory. This can be specified using the working_dir configuration.
{
"working_dir": "${CARGO_MANIFEST_DIR}"
}
As with the bundle_path, the working_dir can use environment variables for expansion.
Esbuild Command
Without any configuration, the macro assumes it can invoke esbuild by using npx: npx esbuild.
This can be changed to one of three other modes by specifying the esbuild configuration in the
esbuild-bundle.json configuration file.
{
"esbuild": {
"type": "npx"
}
}
The esbuild key expects to be an object with a type property, which supports the following
values:
"npx"will use thenpxcommand to invokeesbuild. This is the default behaviour."yarn"will use theyarncommand to invokeesbuild."npm"will invoke a script from thescriptssection of apackage.jsonfile. The script name is specified using thescriptproperty in theesbuildobject. The script is passed two arguments: the path to the given entry-point (the JavaScript module) and the expected path to the output bundle file."pnpm"will usepnpmto either invokeesbuildviapnpm exec esbuildor it can be used to run a script from thescriptssection of apackage.jsonfile, similar to the"npm"option.