| load("@build_bazel_rules_nodejs//:index.bzl", "pkg_web") |
| load("@infra-sk_npm//@bazel/typescript:index.bzl", "ts_library") |
| load("@infra-sk_npm//@bazel/rollup:index.bzl", "rollup_bundle") |
| load("@infra-sk_npm//@bazel/terser:index.bzl", "terser_minified") |
| load("@infra-sk_npm//html-insert-assets:index.bzl", "html_insert_assets") |
| load("@io_bazel_rules_sass//:defs.bzl", "sass_library", "sass_binary") |
| load("//infra-sk/html_insert_nonce_attribute:index.bzl", "html_insert_nonce_attribute") |
| |
| # Utility macro to copy a single file to a destination path, making parent directories as needed. |
| def copy_file(name, src, dst): |
| native.genrule( |
| name = name, |
| srcs = [src], |
| outs = [dst], |
| cmd = "mkdir -p $$(dirname $@) && cp $< $@" |
| ) |
| |
| # This macro takes a page name, e.g. "mypage", assumes the existence of files mypage.html, mypage.ts |
| # and mypage.scss, and defines the necessary build targets to generate development and production |
| # bundles for said page. |
| # |
| # Input files: |
| # <name>.html |
| # <name>.ts |
| # <name>.scss |
| # |
| # Generated files: |
| # development/<name>.html |
| # development/<name>.ts |
| # development/<name>.scss |
| # production/<name>.html |
| # production/<name>.ts |
| # production/<name>.scss |
| # |
| # For convenience, a target with the same name as the "name" argument is defined, which generates |
| # all of the above files (e.g. bazel build //path/to:mypage). |
| # |
| # Tags <script> and <link> will be inserted into the output HTML pointing to the generated bundles. |
| # The serving path for said bundles defaults to "/" and can be overriden via the |
| # assets_serving_path argument. |
| # |
| # A timestamp will be appended to the URLs for any referenced assets for cache busting purposes, |
| # e.g. <script src="/index.js?v=27396986"></script>. |
| # |
| # If the nonce argument is provided, a nonce attribute will be inserted to all <link> and <script> |
| # tags. For example, if the nonce argument is set to "{% .Nonce %}", then the generated HTML will |
| # contain tags such as <script nonce="{% .Nonce %}" src="/index.js?v=27396986"></script>. |
| # |
| # This macro is designed to work side by side with the existing Webpack build without requiring any |
| # major changes to the pages in question. |
| def sk_page(name, deps, sass_deps, assets_serving_path="/", nonce=None): |
| # Output directories. |
| DEV_OUT_DIR = "development" |
| PROD_OUT_DIR = "production" |
| |
| ####################### |
| # JavaScript bundles. # |
| ####################### |
| |
| ts_library( |
| name = "%s_ts_lib" % name, |
| srcs = ["%s.ts" % name], |
| deps = deps, |
| ) |
| |
| # Generates file <name>_js_bundle.js. Intermediate result; do not use. |
| rollup_bundle( |
| name = "%s_js_bundle" % name, |
| deps = [ |
| ":%s_ts_lib" % name, |
| "@infra-sk_npm//@rollup/plugin-node-resolve", |
| "@infra-sk_npm//@rollup/plugin-commonjs", |
| "@infra-sk_npm//rollup-plugin-sourcemaps", |
| ], |
| entry_point = "%s.ts" % name, |
| format = "umd", |
| config_file = "//infra-sk:rollup.config.js", |
| ) |
| |
| # Generates file <name>_js_bundle_minified.js. Intermediate result; do not use. |
| terser_minified( |
| name = "%s_js_bundle_minified" % name, |
| src = "%s_js_bundle.js" % name, |
| sourcemap = False, |
| ) |
| |
| # Generates file development/<name>.js. |
| copy_file( |
| name = "%s_js_dev" % name, |
| src = "%s_js_bundle.js" % name, |
| dst = "%s/%s.js" % (DEV_OUT_DIR, name), |
| ) |
| |
| # Generates file production/<name>.js. |
| copy_file( |
| name = "%s_js_prod" % name, |
| # For some reason the output of the terser_minified rule above is not directly visible as a |
| # source file, so we use the rule name instead (i.e. we drop the ".js" extension). |
| src = "%s_js_bundle_minified" % name, |
| dst = "%s/%s.js" % (PROD_OUT_DIR, name), |
| ) |
| |
| ################ |
| # CSS Bundles. # |
| ################ |
| |
| # Notes: |
| # - The source maps generated by the sass_binary rule are currently broken. |
| # - Sass compilation errors are not visible unless "bazel build" is invoked with flag |
| # "--strategy=SassCompiler=sandboxed". This is due to a known issue with sass_binary. For |
| # more details please see https://github.com/bazelbuild/rules_sass/issues/96. |
| |
| # Generates file development/<name>.css. |
| sass_binary( |
| name = "%s_css_dev" % name, |
| src = "%s.scss" % name, |
| output_name = "%s/%s.css" % (DEV_OUT_DIR, name), |
| deps = sass_deps, |
| include_paths = ["//infra-sk/node_modules"], |
| output_style = "expanded", |
| sourcemap = True, |
| ) |
| |
| # Generates file production/<name>.css. |
| sass_binary( |
| name = "%s_css_prod" % name, |
| src = "%s.scss" % name, |
| output_name = "%s/%s.css" % (PROD_OUT_DIR, name), |
| deps = sass_deps, |
| include_paths = ["//infra-sk/node_modules"], |
| output_style = "compressed", |
| sourcemap = False, |
| ) |
| |
| ############### |
| # HTML files. # |
| ############### |
| |
| # Generates file <name>.with_assets.html. Intermediate result; do not use. |
| # |
| # See https://www.npmjs.com/package/html-insert-assets. |
| html_insert_assets( |
| name = "%s_html" % name, |
| outs = ["%s.with_assets.html" % name], |
| args = [ |
| "--html=$(location %s.html)" % name, |
| "--out=$@", |
| "--roots=$(RULEDIR)", |
| "--assets", |
| # This is OK because html-insert-assets normalizes paths with successive slashes. |
| "%s/%s.js" % (assets_serving_path, name), |
| "%s/%s.css" % (assets_serving_path, name), |
| ], |
| data = ["%s.html" % name], |
| ) |
| |
| if nonce: |
| # Generates file <name>.with_assets_and_nonce.html. Intermediate result; do not use. |
| html_insert_nonce_attribute( |
| name = "%s_html_nonce" % name, |
| src = "%s.with_assets.html" % name, |
| out = "%s.with_assets_and_nonce.html" % name, |
| nonce = nonce, |
| ) |
| |
| instrumented_html = ("%s.with_assets_and_nonce.html" if nonce else "%s.with_assets.html") % name |
| |
| # Generates file development/<name>.html. |
| copy_file( |
| name = "%s_html_dev", |
| src = instrumented_html, |
| dst = "%s/%s.html" % (DEV_OUT_DIR, name), |
| ) |
| |
| # Generates file production/<name>.html. |
| copy_file( |
| name = "%s_html_prod", |
| src = instrumented_html, |
| dst = "%s/%s.html" % (PROD_OUT_DIR, name), |
| ) |
| |
| ########################### |
| # Convenience filegroups. # |
| ########################### |
| |
| # Generates all output files (that is, the development and production bundles). |
| native.filegroup( |
| name = name, |
| srcs = [ |
| ":%s_dev" % name, |
| ":%s_prod" % name, |
| ], |
| ) |
| |
| # Generates the development bundle. |
| native.filegroup( |
| name = "%s_dev" % name, |
| srcs = [ |
| "development/%s.html" % name, |
| "development/%s.js" % name, |
| "development/%s.css" % name, |
| ] |
| ) |
| |
| # Generates the production bundle. |
| native.filegroup( |
| name = "%s_prod" % name, |
| srcs = [ |
| "production/%s.html" % name, |
| "production/%s.js" % name, |
| "production/%s.css" % name, |
| ] |
| ) |