The ESBuild Tool is a wrapper around the esbuild JavaScript bundler and minifier, tailored to work seamlessly with the Please build system and the JS Rules plugin. It provides a structured "compile" and "link" workflow, enabling efficient bundling of JavaScript and CSS code in a manner similar to traditional build processes. This tool is integrated under the hood and is used in js_library
, jsx_library
, css_module
and node_module
build definitions for compiling, and the js_binary
for linking.
- Structured Workflow: Separates the build process into distinct "compile" and "link" phases.
- Module Resolution: Custom plugins handle module resolution for Node.js modules and CSS modules within the Please build system.
- TypeScript Support: Supports compiling TypeScript files out of the box.
- JSX and React Support: Handles JSX syntax with customizable factory and fragment options.
- Efficient Bundling: Utilizes esbuild's high performance for fast builds.
The ESBuild Tool operates in two primary phases:
-
Compile Phase:
- Purpose: Prepares individual modules or libraries by compiling their source code into a format suitable for linking.
- Process:
- Compiles source files (e.g., JavaScript, TypeScript) into JavaScript.
- Uses custom plugins to handle module resolution and asset loading.
- Marks external dependencies to be resolved during the link phase.
- Used By:
js_library
,jsx_library
,css_module
, andnode_module
build definitions.
-
Link Phase:
- Purpose: Bundles compiled modules and their dependencies into a final output suitable for deployment or execution.
- Process:
- Resolves and includes all dependencies.
- Bundles the code into a single or multiple output files.
- Handles CSS imports and other assets.
- Used By:
js_binary
build definition.
Why Separate Compile and Link Phases?
Separating the compile and link phases offers several benefits:
- Modularity: Allows individual modules to be compiled independently, promoting reuse, caching build artifacts and parallelism.
- Efficiency: Speeds up incremental builds by recompiling only changed modules.
- Control: Provides more granular control over the build process, enabling optimizations and customizations.
- Scalability: Better supports large projects with many dependencies by breaking down the build into manageable steps.
Compiles Node.js modules for use in your project.
def node_module(
name: str,
scope: str = '',
module: str = '',
version: str = '',
visibility: list = [],
deps: list = [],
hashes: list = None,
binary: bool = False,
entry_point: str = ''
)
- Downloads the specified module from the NPM registry.
- Compiles the module during the compile phase.
- Exports the module for use in other build targets.
node_module(
name = "lodash",
version = "4.17.21",
visibility = ["PUBLIC"],
)
Compiles JavaScript source code into a library.
def js_library(
name: str,
module_name: str = '',
srcs: list = [],
deps: list = [],
visibility: list = [],
entry_point: str = "index.js"
)
- Compiles JavaScript or TypeScript source files.
- Defines an entry point for the library.
- Specifies dependencies that will be resolved during the link phase.
js_library(
name = "my_library",
srcs = ["utils.js", "helpers.js"],
deps = [":lodash"],
visibility = ["PUBLIC"],
entry_point = "main.js",
)
A syntactic sugar for js_library
tailored for JSX files.
def jsx_library(
name: str,
module_name: str = '',
srcs: list = [],
deps: list = [],
visibility: list = [],
entry_point: str = "index.jsx"
)
- Compiles JSX source files.
- Supports React and other libraries that use JSX syntax.
jsx_library(
name = "my_component",
srcs = ["Button.jsx", "Modal.jsx"],
deps = [":react"],
visibility = ["PUBLIC"],
entry_point = "App.jsx",
)
Compiles CSS modules ensuring they are bundled into the index.css
.
def css_module(
name: str,
module_name: str = '',
srcs: list = [],
deps: list = [],
visibility: list = [],
entry_point: str = "index.css"
)
- Compiles CSS files into CSS modules.
- Enables importing CSS in JavaScript files with module support.
css_module(
name = "styles",
srcs = ["main.css", "theme.css"],
visibility = ["PUBLIC"],
entry_point = "main.css",
)
Links compiled modules and dependencies into an executable JavaScript bundle.
def js_binary(
name: str,
entry_point: str = "index.js",
srcs: list = [],
deps: list = [],
visibility: list = [],
out_dir: str = 'dist'
)
- Links compiled libraries and modules into a final bundle.
- Resolves all dependencies specified in the
deps
parameter. - Outputs the bundle to the specified
out_dir
.
js_binary(
name = "app_bundle",
entry_point = "main.js",
deps = [
":my_library",
":my_component",
":styles",
":lodash",
],
visibility = ["PUBLIC"],
out_dir = "dist",
)
The ESBuild Tool provides a command-line interface with two primary commands:
-
Compile Command:
- Usage:
compile
- Description: Compiles entry points, marking dependencies as external for later resolution.
- Options:
--entry_point
: Specifies the entry point file.--package_json
: Specifies thepackage.json
file to determine the entry point.--external
: Marks modules as external.--binary
: Indicates if the package is a binary module.--out-dir
: Specifies the output directory.
- Usage:
-
Link Command:
- Usage:
link
- Description: Compiles entry points, resolving and bundling specified modules.
- Options:
--entry_point
: Specifies the entry point file.--module
: Maps module names to paths for resolution.--css
: Maps CSS module names to paths.--out-dir
: Specifies the output directory.
- Usage:
The ESBuild Tool uses custom plugins to extend esbuild's functionality:
- Purpose: Handles module resolution for Node.js modules and CSS modules.
- How It Works:
- Intercepts module resolution requests during the build process.
- Checks if the requested module matches any provided mappings.
- Resolves the module to the specified path and assigns it to a custom namespace.
- Purpose: Loads files from the custom "please" namespace.
- How It Works:
- Intercepts file loading requests in the "please" namespace.
- Reads the file contents and provides them to esbuild.
- Purpose: Loads CSS modules from the "css" namespace.
- How It Works:
- Intercepts file loading requests in the "css" namespace.
- Reads the CSS file contents and provides them to esbuild with the appropriate loader.
- Custom Module Resolution: Allows precise control over how modules are resolved, enabling integration with the Please build system's dependency management.
- Namespace Isolation: Prevents conflicts by isolating modules in custom namespaces.
- Asset Handling: Provides specialized handling for different asset types like CSS modules.
- No Hot Module Replacement: The tool does not support hot module replacement (HMR) during development.
- Single Entry Point for Binaries: The
js_binary
build definition expects a single entry point. - Limited CSS Processing: Advanced CSS processing features (e.g., Sass, Less) are not handled out of the box.
- Plugin Complexity: Custom plugins add complexity to the build process, which may require understanding the underlying implementation for advanced use cases.
If you have any questions or need further assistance, feel free to consult the tool's source code or reach out to the maintainers.