hyperboria/rules/nodejs/webpack.bzl

218 lines
6.9 KiB
Python

"""JS build rules"""
load("//rules/nodejs:common.bzl", "get_transitive_depsets")
CONTENT_PREFIX = """
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
"""
WEBPACK_DEV_SERVER_WRAPPER_TEMPLATE = """
{webpack_dev_server_cmd} --config {webpack_config_file}
"""
CompiledInfo = provider(fields = ["compiled_files", "source_files"])
def _generate_server_js_impl(ctx):
short_path = ctx.outputs.server_js.short_path
short_path = short_path[:short_path.rfind("/")]
ctx.actions.expand_template(
template = ctx.file.template,
output = ctx.outputs.server_js,
substitutions = {
"{config_path}": ctx.file.config.basename,
"{webpack_config_path}": ctx.file.webpack_config.basename,
"{static_path}": short_path + "/webpack_dist",
},
)
_generate_server_js = rule(
implementation = _generate_server_js_impl,
attrs = {
"config": attr.label(mandatory = True, allow_single_file = True),
"webpack_config": attr.label(allow_single_file = True),
"template": attr.label(
default = Label("//rules/nodejs:webpack.server.js"),
allow_single_file = True,
),
},
outputs = {
"server_js": "server.js",
},
)
def _generate_webpack_dev_server_wrapper(ctx):
webpack_dev_server_wrapper_content = WEBPACK_DEV_SERVER_WRAPPER_TEMPLATE.format(
webpack_dev_server_cmd = ctx.attr._webpack_dev_server_binary.files_to_run.executable.short_path,
webpack_config_file = ctx.file.webpack_config.short_path,
)
ctx.actions.write(
ctx.outputs.webpack_dev_server_runner,
CONTENT_PREFIX + webpack_dev_server_wrapper_content,
is_executable = True,
)
def _webpack_binary_impl(ctx):
depsets, node_modules_depsets = get_transitive_depsets(ctx.attr.data)
trans_srcs = depset(ctx.files.srcs + [ctx.file.config, ctx.file.webpack_config], transitive = depsets + node_modules_depsets)
runfiles = ctx.runfiles(transitive_files = trans_srcs).merge(
ctx.attr._webpack_dev_server_binary[DefaultInfo].default_runfiles,
)
_generate_webpack_dev_server_wrapper(ctx)
return [
DefaultInfo(
executable = ctx.outputs.webpack_dev_server_runner,
runfiles = runfiles,
files = trans_srcs,
),
]
_webpack_binary = rule(
implementation = _webpack_binary_impl,
attrs = {
"config": attr.label(mandatory = True, allow_single_file = True),
"webpack_config": attr.label(mandatory = True, allow_single_file = True),
"srcs": attr.label_list(allow_files = True),
"data": attr.label_list(),
"_webpack_binary": attr.label(
default = Label("//rules/nodejs:webpack-binary"),
executable = True,
cfg = "host",
),
"_webpack_dev_server_binary": attr.label(
default = Label("//rules/nodejs:webpack-dev-server-binary"),
executable = True,
cfg = "host",
),
},
outputs = {
"webpack_dev_server_runner": "webpack_dev_server_runner",
},
executable = True,
)
def _webpack_compile_impl(ctx):
depsets, node_modules_depsets = get_transitive_depsets(ctx.attr.deps)
trans_srcs = depset(ctx.files.srcs + [ctx.file.config, ctx.file.webpack_config], transitive = depsets + node_modules_depsets)
runfiles = ctx.runfiles(transitive_files = trans_srcs).merge(
ctx.attr._webpack_dev_server_binary[DefaultInfo].default_runfiles,
)
_generate_webpack_dev_server_wrapper(ctx)
ctx.actions.run(
inputs = trans_srcs,
outputs = [ctx.outputs.webpack_dist],
arguments = [
"--mode",
"production",
"--config",
ctx.file.webpack_config.short_path,
"--output-path",
ctx.outputs.webpack_dist.path,
],
progress_message = "Compiling %s by Webpack..." % ctx.outputs.webpack_dist.short_path,
executable = ctx.executable._webpack_binary,
)
return [
DefaultInfo(
executable = ctx.outputs.webpack_dev_server_runner,
runfiles = runfiles,
files = trans_srcs,
),
CompiledInfo(
compiled_files = depset([ctx.outputs.webpack_dist]),
source_files = depset([ctx.file.config]),
),
]
_webpack_compile = rule(
implementation = _webpack_compile_impl,
attrs = {
"config": attr.label(mandatory = True, allow_single_file = True),
"webpack_config": attr.label(mandatory = True, allow_single_file = True),
"srcs": attr.label_list(allow_files = True),
"data": attr.label_list(),
"_webpack_binary": attr.label(
default = Label("//rules/nodejs:webpack-binary"),
executable = True,
cfg = "host",
),
"_webpack_dev_server_binary": attr.label(
default = Label("//rules/nodejs:webpack-dev-server-binary"),
executable = True,
cfg = "host",
),
},
outputs = {
"webpack_dist": "webpack_dist",
"webpack_dev_server_runner": "webpack_dev_server_runner",
},
executable = True,
)
def _webpack_data_impl(ctx):
return [DefaultInfo(
files = depset(
transitive = [
ctx.attr.compiled[CompiledInfo].compiled_files,
ctx.attr.compiled[CompiledInfo].source_files,
],
),
)]
_webpack_data = rule(
implementation = _webpack_data_impl,
attrs = {
"compiled": attr.label(),
},
)
def webpack_binary(
name,
config = "config.js",
webpack_config = "webpack.config.js",
srcs = [],
data = []):
_webpack_binary(
name = name,
config = config,
webpack_config = webpack_config,
srcs = srcs,
data = data,
)
_generate_server_js(
name = name + ".server.js",
config = config,
webpack_config = webpack_config,
template = "//rules/nodejs:webpack.dynamic.server.js",
)
def webpack_compile(
name,
config = "config.js",
webpack_config = "webpack.config.js",
srcs = [],
data = []):
_webpack_compile(
name = name,
config = config,
webpack_config = webpack_config,
srcs = srcs,
data = data,
)
_webpack_data(name = name + ".compiled", compiled = name)
_generate_server_js(
name = name + ".server.js",
config = config,
webpack_config = webpack_config,
)