rules_closure for Bazel

repository·master·Indexed 41 days ago

https://github.com/bazelbuild/rules_closure

A JavaScript and CSS build system for Bazel that leverages the Closure Compiler and Closure Library. It provides rules for defining JS libraries (closure_js_library), creating optimized minified bundles (closure_js_binary), running unit tests in PhantomJS (closure_js_test), and managing CSS/GSS stylesheets (closure_css_library and closure_css_binary) with support for class name minification and RTL orientation.

Tokens
3.3K
Snippets
10
Records
11
Agent score
50%

What's inside rules_closure

  1. Install Closure Rules via Bazel

    master

    To use Closure Rules, you must first have [Bazel] installed. Then, add the rules_closure dependency to your MODULE.bazel file.

    Note: The root module must also declare overrides for rules_webtesting, rules_scala, and google_bazel_common temporarily until they are registered in BCR. You do not need to manually install Closure Tools or PhantomJS; Bazel will fetch them automatically.

    bazel_dep(name = "rules_closure", version = "0.15.0")
  2. Configure closure_js_binary for AngularJS

    master

    When compiling AngularJS applications, you must pass specific custom flags to the Closure Compiler via the defs attribute in your closure_js_binary rule.

    closure_js_binary(
        # ...
        defs = [
            "--angular_pass",
            "--export_local_property_definitions",
        ],
    )
  3. Run JavaScript unit tests with closure_js_test

    master

    The closure_js_test macro runs JavaScript unit tests inside a headless web browser (PhantomJS). It composes closure_js_library, closure_js_binary, and phantomjs_test.

    Test Definition Requirements:

    • A test is any function in the global namespace starting with test, setUp, or tearDown.
    • If using goog.module or goog.scope, you must register test functions with goog.testing.testSuite.
    • Test files should require goog.testing.jsunit and goog.testing.asserts.
    • It is recommended to include goog.setTestOnly() in test-related files.

    Environment Constraints:

    • Tests run in a hermetically sealed environment with no network access. You cannot send HTTP requests to external servers; use Closure Library mocks for XHR instead.
    • A local HTTP server is provided to request runfiles via the /filez/WORKSPACE_NAME/ path.

    Arguments:

    • srcs: List of _test.js source files.
    • compilation_level: Setting this to "WHITESPACE_ONLY" makes tests run significantly faster by skipping type checking.
    load("@rules_closure//closure:defs.bzl", "closure_js_test")
    
    closure_js_test(
        name = "my_test",
        srcs = ["//path/to:test_js"],
        deps = ["//path/to:lib"],
        compilation_level = "WHITESPACE_ONLY",
    )
  4. Use closure_js_binary to create optimized JavaScript bundles

    master

    The closure_js_binary rule turns JavaScript libraries into a minified, optimized blob of code. It must be used in conjunction with closure_js_library rules.

    Implicit Outputs:

    • {name}.js: A minified JavaScript file containing all transitive sources.
    • {name}.js.map: A sourcemap file for debugging compiled sources in browsers like Chrome or Firefox.

    Key Configuration Options:

    • compilation_level: Controls minification intensity.
      • ADVANCED (Default): Maximal minification and type checking. Strongly recommended for production. Note: Properties accessed via dot notation will be renamed; use quoted notation (e.g., foo['bar']) to prevent this.
      • SIMPLE: Functions like a traditional minifier. Type checking is disabled. Local variables are minified, but object properties and globals are not.
      • WHITESPACE_ONLY: Strips whitespace and comments only. No renaming or inlining.
    • debug: (Boolean, default False) Enables debug mode. Renames properties/variables with $ to help spot bugs in ADVANCED mode, preserves assert statements, and keeps dependency directives.
    • entry_points: (List of Strings) A list of unreferenced namespaces that should not be pruned. Use this for functions you intend to call directly from a <script> tag in HTML.
    • output_wrapper: (String) Wraps the output. To avoid polluting the global namespace, it is recommended to use "(function(){%output%}).call(this);".
    load("@rules_closure//closure:defs.bzl", "closure_js_binary")
    
    closure_js_binary(
        name = "foo_bin",
        deps = ["//path/to:lib"],
        compilation_level = "ADVANCED",
        debug = False,
        entry_points = ["my.namespace.entry"],
        output_wrapper = "(function(){%output%}).call(this);"
    )
  5. Define CSS stylesheets with closure_css_library

    master

    Use closure_css_library to define a set of CSS or GSS stylesheets. This rule does not perform compilation itself; it is a provider used by closure_css_binary to produce minified CSS.

    Integration with JavaScript: If your closure_js_library sources contain calls to goog.getCssName('foo') where 'foo' is a class name defined in this library, you must add this closure_css_library target to the deps of that JavaScript library.

    Ordering and Dependencies:

    • The order of stylesheets in srcs is undefined.
    • If one CSS file overrides another, they must be placed in separate closure_css_library targets. Bazel will then use depth-first preordering of dependencies to ensure correct CSS cascading.
    • It is strongly recommended to use @provide and @require statements in your stylesheets to allow the compiler to verify ordering accuracy.
    load("@rules_closure//closure:defs.bzl", "closure_css_library")
    
    closure_css_library(
        name = "my_css_lib",
        srcs = ["""style.gss"""],
        data = ["""logo.png"""],
        deps = ["//path/to/other_css_lib"],
        orientation = "LTR",
    )
  6. Compile minified CSS with closure_css_binary

    master

    Use closure_css_binary to turn stylesheets defined by closure_css_library rules into a single minified CSS file. This rule evaluates Closure-specific syntax (variables, functions, conditionals, mixins) into standard CSS.

    Key Features:

    • Class Name Minification: By default, it minifies class names (e.g., .foo-bar becomes .a-b). To support this, you must use goog.getCssName("foo-bar") in your JavaScript and point the css attribute of your closure_js_binary to this target.
    • Implicit Outputs:
      • name.css: The minified CSS file.
      • name.css.map: A CSS sourcemap for browser debugging.
      • name.css.js: A JavaScript file containing goog.setCssNameMapping(). This is used by the build system to sync minified names between CSS and JS. If rendering Soy templates from Java, you may need to parse this file manually.

    Orientation Conversion: If the orientation argument differs from the orientation of the input libraries, the rule will automatically flip 'left' and 'right' values in direction-sensitive style rules.

    load("@rules_closure//closure:defs.bzl", "closure_css_binary")
    
    closure_css_binary(
        name = "my_css_bin",
        deps = ["//path/to:my_css_lib"],
        renaming = True,
        debug = False,
        orientation = "LTR",
    )
  7. Use closure_js_library to define JavaScript sources

    master

    The closure_js_library rule defines an abstract graph of JavaScript sources. It performs syntax checking and linting. This rule is intended to be used in conjunction with closure_js_binary to produce a minified output file.

    Rule Polymorphism: When referenced as a filegroup, the srcs attribute will be empty, and data will contain all transitive JS sources and data.

    load("@rules_closure//closure:defs.bzl", "closure_js_library")
    
    closure_js_library(
        name = "my_lib",
        srcs = ["foo.js"],
        deps = ["//other:lib"],
    )
  8. Use phantomjs_test for low-level testing

    master

    The phantomjs_test rule is a low-level rule that runs PhantomJS (QtWebKit) for unit testing. It is recommended to use the closure_js_test macro instead unless you have specific low-level requirements.

    Arguments:

    • harness: (Required) A JS binary or library exporting a single source file to be used as the PhantomJS outer script.
    • deps: Labels of Skylark rules exporting transitive_js_srcs. These are inserted into the webpage as <script> tags using depth-first preordering.
    • html: (Optional) An HTML file containing the DOM structure before <script> tags are inserted. Do not include a <!DOCTYPE> in this file.
    load("@rules_closure//closure:defs.bzl", "phantomjs_test")
    
    phantomjs_test(
        name = "low_level_test",
        deps = ["//path/to:js_lib"],
        harness = "//path/to:test_harness",
        html = "//path/to:test_page.html",
    )
  9. Arguments for closure_css_binary

    master

    The closure_css_binary rule accepts the following arguments:

    ArgumentTypeDescription
    nameNameRequired. Unique name. Conventionally foo_bin or foo_dbg (if debug=True).
    depsList[labels]Required. List of closure_css_library rules. All must have the same orientation.
    renamingBooleanOptional. Default True. Enables CSS class name minification. Requires goog.getCssName() in JS.
    debugBooleanOptional. Default False. Enables pretty printing. If renaming=True, names remain human-readable.
    orientationStringOptional. Default "NOCHANGE". Options: "NOCHANGE", "LTR", or "RTL". Performs automatic RLT conversion if requested orientation differs from input.
    vendorStringOptional. Default None. Strips all proprietary browser-vendor properties except those for the specified vendor: "WEBKIT", "MOZILLA", "MICROSOFT", "OPERA", "KONQUEROR".
    defsList[strings]Optional. Additional flags passed to the Closure Stylesheets compiler.
    closure_css_binary(
        name = "my_css_bin",
        deps = ["//path/to:my_css_lib"],
        renaming = True,
        orientation = "RTL",
        vendor = "WEBKIT",
    )
  10. Arguments for closure_css_library

    master

    The closure_css_library rule accepts the following arguments:

    ArgumentTypeDescription
    nameNameRequired. A unique name. Conventionally ends with _lib.
    srcsList[labels]Required. A list of .gss or .css source files.
    dataList[labels]Optional. Runfiles referenced by CSS (e.g., images used in url() calls).
    depsList[labels]Optional. Other closure_css_library targets on which these sources depend.
    orientationStringOptional. Default is "LTR". Can be "LTR" (Left-to-Right) or "RTL" (Right-to-Left). All deps must share the same orientation.
    closure_css_library(
        name = "my_css_lib",
        srcs = ["style.css"],
        data = ["image.png"],
        deps = ["//other:css_lib"],
        orientation = "RTL",
    )
  11. Configure closure_js_library arguments

    master

    The closure_js_library rule accepts the following arguments:

    ArgumentTypeDefaultDescription
    nameString(Required) A unique name for the rule. Conventionally, use the package name or append _lib if it's a subset of the package's .js files.
    srcsList of labels(Optional) The .js source files. Required unless exports is defined. Can include @externs or @nocompile files.
    dataList of labels(Optional) Runfiles directly referenced by JS sources (e.g., images).
    depsList of labels(Optional) Direct dependencies, pointing to closure_js_library or closure_css_library rules.
    exportsList of labels(Optional) Dependencies that become direct dependencies in parent rules (similar to java_library.exports).
    suppressList of Strings(Optional, default []) List of linter diagnostic codes to ignore (e.g., "JSC_MUST_BE_PRIVATE"). Use "lintChecks" to disable all linting.
    conventionString(Optional, default "CLOSURE") Coding convention for the linter. Values: NONE, CLOSURE, or GOOGLE.
    no_closure_libraryBoolean(Optional, default False) If True, prevents linking base.js from the Closure Library. If used, all deps must also set this to True.