Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions internal/rollup/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ load("//internal:node.bzl", nodejs_binary = "nodejs_binary_macro")

package(default_visibility = ["//internal:__subpackages__"])

exports_files(["rollup.config.js", "uglify.config.json"])
exports_files(["rollup.config.js", "uglify.config.json", "tsconfig.json"])

nodejs_binary(
name = "rollup",
Expand All @@ -36,7 +36,8 @@ nodejs_binary(

nodejs_binary(
name = "uglify",
entry_point = "build_bazel_rules_nodejs_rollup_deps/node_modules/uglify-js/bin/uglifyjs",
entry_point = "build_bazel_rules_nodejs/internal/rollup/uglify.js",
node_modules = "@build_bazel_rules_nodejs_rollup_deps//:node_modules",
visibility = ["//visibility:public"],
data = [":uglify.js"],
)
4 changes: 2 additions & 2 deletions internal/rollup/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"description": "runtime dependencies for rollup",
"devDependencies": {
"rollup": "0.52.3",
"rollup-plugin-commonjs": "8.2.6",
"rollup": "0.55.3",
"rollup-plugin-node-resolve": "3.0.0",
"systemjs": "0.20.19",
"typescript": "2.6.2",
"uglify-js": "3.3.9"
}
Expand Down
7 changes: 4 additions & 3 deletions internal/rollup/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// For Windows, we must deep-import the actual .js file, not rely on reading the "main" from package.json
const rollup = require('rollup/dist/rollup');
const nodeResolve = require('rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.cjs');
const commonjs = require('rollup-plugin-commonjs/dist/rollup-plugin-commonjs.cjs');
const path = require('path');

const binDirPath = "TMPL_bin_dir_path";
Expand Down Expand Up @@ -53,12 +52,14 @@ class NormalizePaths {
}

export default {
output: {format: 'iife'},
input: [TMPL_inputs],
output: {dir: path.join(process.cwd(), binDirPath, buildFileDirname, 'bundles.es6'), format: 'cjs'},
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

experimental code splitting only supports 'cjs' right now

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a formatter in this repo

experimentalCodeSplitting: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not that we're really rolling it out yet - but I think we should consider exposing an experimental flag as a rule attribute when we enable these things - we could have users depend on us to provide a higher guarantee than the thing we depend on

experimentalDynamicImport: true,
plugins: [
TMPL_additional_plugins
].concat([
new NormalizePaths(),
commonjs(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commonjs plugin doesn't play nicely with the experimental code splitting. but its not needed anyway.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I also removed it today as it was giving rxjs when I didn't want it

nodeResolve({jsnext: true, module: true}),
])
}
146 changes: 100 additions & 46 deletions internal/rollup/rollup_bundle.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ def write_rollup_config(ctx, plugins=[]):
config = ctx.actions.declare_file("_%s.rollup.conf.js" % ctx.label.name)

# build_file_path includes the BUILD.bazel file, transform here to only include the dirname
buildFileDirname = "/".join(ctx.build_file_path.split("/")[:-1])
build_file_dirname = "/".join(ctx.build_file_path.split("/")[:-1])

entry_points = []
for e in ctx.attr.entry_points:
entry_points = entry_points + ["\""+"/".join([ctx.workspace_name, e])+"\""]
entry_points = ",".join(entry_points)

mappings = dict()
all_deps = ctx.attr.deps + ctx.attr.srcs
Expand All @@ -48,83 +53,128 @@ def write_rollup_config(ctx, plugins=[]):
output = config,
template = ctx.file._rollup_config_tmpl,
substitutions = {
"TMPL_inputs": entry_points,
"TMPL_bin_dir_path": ctx.bin_dir.path,
"TMPL_workspace_name": ctx.workspace_name,
"TMPL_build_file_dirname": buildFileDirname,
"TMPL_build_file_dirname": build_file_dirname,
"TMPL_label_name": ctx.label.name,
"TMPL_module_mappings": str(mappings),
"TMPL_additional_plugins": ",\n".join(plugins),
})

return config

def run_rollup(ctx, config, output):
entryPoint = "/".join([ctx.workspace_name, ctx.attr.entry_point])

def run_rollup(ctx, config):
args = ctx.actions.args()
args.add(["--config", config.path])
args.add(["--output.file", output.path])
args.add(["--input", entryPoint])

es6_sources = collect_es6_sources(ctx)

output_dir = ctx.actions.declare_directory("bundles.es6")

ctx.action(
executable = ctx.executable._rollup,
inputs = es6_sources + ctx.files.node_modules + [config],
outputs = [output],
outputs = [output_dir],
arguments = [args]
)

def run_tsc(ctx, input, output):
args = ctx.actions.args()
args.add(["--target", "es5"])
args.add("--allowJS")
args.add(input.path)
args.add(["--outFile", output.path])
return output_dir

ctx.action(
executable = ctx.executable._tsc,
inputs = [input],
outputs = [output],
arguments = [args]
)
def run_tsc(ctx, input_dir):
config = ctx.actions.declare_file("_%s.tsconfig.json" % ctx.label.name)

output_dir = ctx.actions.declare_directory("bundles.es5")

def run_uglify(ctx, input, output, debug = False):
config = ctx.actions.declare_file("_%s%s.uglify.json" % (
ctx.label.name, ".debug" if debug else ""))
build_file_dirname = ctx.build_file_path.split("/")[:-1]
input_dir_rerooted = "/".join(input_dir.short_path.split("/")[len(build_file_dirname):])
output_dir_rerooted = "/".join(output_dir.short_path.split("/")[len(build_file_dirname):])

ctx.actions.expand_template(
output = config,
template = ctx.file._uglify_config_tmpl,
template = ctx.file._tsconfig_tmpl,
substitutions = {
"TMPL_mangle": "false" if debug else "true"
},
"TMPL_include_path": input_dir_rerooted + "/*",
"TMPL_out_dir": output_dir_rerooted,
})

args = ctx.actions.args()
args.add(["--project", config.path])

ctx.action(
executable = ctx.executable._tsc,
inputs = [input_dir, config],
outputs = [output_dir],
arguments = [args]
)

return output_dir

def run_uglify(ctx, input_dir, output_dir, debug = False):
args = ctx.actions.args()
args.add(input.path)
args.add(["--config-file", config.path])
args.add(["--output", output.path])
args.add(input_dir.path)
args.add(output_dir.path)
if debug:
args.add("--beautify")
args.add("--debug")

ctx.action(
executable = ctx.executable._uglify,
inputs = [input, config],
outputs = [output],
inputs = [input_dir],
outputs = [output_dir],
arguments = [args]
)

def _generate_html(ctx):
if len(ctx.attr.entry_points) == 0:
fail("\n%s: at least one entry_point must be specified\n" % ctx.label.name)
build_file_prefix = "/".join(ctx.build_file_path.split("/")[:-1]) + "/"
main_entry_point = ctx.attr.entry_points[0].lstrip(build_file_prefix)
entry_points = {}
for e in ctx.attr.entry_points:
entry_point = e.lstrip(build_file_prefix)
entry_points["./" + entry_point] = "bundles.es5_min/" + entry_point.split("/")[-1]
rollup_scripts = """<script src="/system.js"></script>
<script>
(function (global) {
System.config({
packages: {
'' : {
map: """ + str(entry_points) + """,
defaultExtension: 'js'
},
}
});
})(this);
</script>
<script>
System.import('""" + main_entry_point + """').catch(function(err){ console.error(err); });
</script>
"""
ctx.actions.expand_template(
output = ctx.outputs.index_html,
template = ctx.file.index_html_template,
substitutions = {
"TEMPLATED_rollup_scripts": rollup_scripts,
})

def _rollup_bundle(ctx):
rollup_config = write_rollup_config(ctx)
run_rollup(ctx, rollup_config, ctx.outputs.build_es6)
run_tsc(ctx, ctx.outputs.build_es6, ctx.outputs.build_es5)
run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min)
run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min_debug, debug = True)
return DefaultInfo(files=depset([ctx.outputs.build_es5_min]))
output_dir_es6 = run_rollup(ctx, rollup_config)
output_dir_es5 = run_tsc(ctx, output_dir_es6)
output_dir_es5_min = ctx.actions.declare_directory("bundles.es5_min")
output_dir_es5_min_debug = ctx.actions.declare_directory("bundles.es5_min_debug")
run_uglify(ctx, output_dir_es5, output_dir_es5_min)
run_uglify(ctx, output_dir_es5, output_dir_es5_min_debug, debug = True)
_generate_html(ctx)
ctx.actions.expand_template(
output = ctx.outputs.system_js,
template = ctx.file._systemjs,
substitutions = {})
return DefaultInfo(runfiles=ctx.runfiles([output_dir_es6, output_dir_es5, output_dir_es5_min, output_dir_es5_min_debug, ctx.outputs.system_js, ctx.outputs.index_html]), files=depset([]))

ROLLUP_ATTRS = {
"entry_point": attr.string(mandatory = True),
"entry_points": attr.string_list(mandatory = True),
"index_html_template": attr.label(allow_files = [".template.html"], single_file = True),
"srcs": attr.label_list(allow_files = [".js"]),
"deps": attr.label_list(aspects = [rollup_module_mappings_aspect]),
"node_modules": attr.label(default = Label("@//:node_modules")),
Expand All @@ -140,6 +190,14 @@ ROLLUP_ATTRS = {
executable = True,
cfg="host",
default = Label("@build_bazel_rules_nodejs//internal/rollup:uglify")),
"_systemjs": attr.label(
default = Label("@build_bazel_rules_nodejs_rollup_deps//:node_modules/systemjs/dist/system.js"),
allow_files = True,
single_file = True),
"_tsconfig_tmpl": attr.label(
default = Label("@build_bazel_rules_nodejs//internal/rollup:tsconfig.json"),
allow_files = True,
single_file = True),
"_rollup_config_tmpl": attr.label(
default = Label("@build_bazel_rules_nodejs//internal/rollup:rollup.config.js"),
allow_files = True,
Expand All @@ -150,15 +208,11 @@ ROLLUP_ATTRS = {
single_file = True),
}

ROLLUP_OUTPUTS = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't land it if we remove these. Can we still output the files for the "main" bundle or something?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make it so that the rule could output both a regular bundle or a code split one but without a devserver that can support code splitting is there any value in a landing the production bundler at this point?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to land this somewhere with CI so that it doesn't rust, and people can try it and build on it.
I think there are some users who would be satisfied with lazy-loading only for production, if they have simple enough code splitting and are okay with having to debug issues in production mode.
I dunno it seems like a tough call.

"build_es6": "%{name}.es6.js",
"build_es5": "%{name}.js",
"build_es5_min": "%{name}.min.js",
"build_es5_min_debug": "%{name}.min_debug.js",
}

rollup_bundle = rule(
implementation = _rollup_bundle,
attrs = ROLLUP_ATTRS,
outputs = ROLLUP_OUTPUTS,
outputs = {
"system_js": "system.js",
"index_html": "index.html",
}
)
12 changes: 12 additions & 0 deletions internal/rollup/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["es6"],
"allowJs": true,
"outDir": "TMPL_out_dir"
},
"include": [
"TMPL_include_path"
],
"exclude": []
}
11 changes: 0 additions & 11 deletions internal/rollup/uglify.config.json

This file was deleted.

61 changes: 61 additions & 0 deletions internal/rollup/uglify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @license
* Copyright 2017 The Bazel Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const UglifyJS = require("uglify-js");
const fs = require('fs');
const path = require('path');

if (process.argv.length < 4) {
throw new Error("input_path and output_path arguments required");
}

const inputPath = process.argv[2];
const outputPath = process.argv[3];
const args = process.argv.slice(4);
let debug = false;
args.forEach(a => {
if (a === '--debug') {
debug = true;
}
})

const uglifyOptions = {
"compress": {
"pure_getters": true,
"passes": 3,
"global_defs": {
"ngDevMode": false
}
},
"mangle": !debug
};

if (!fs.existsSync(outputPath)){
fs.mkdirSync(outputPath);
}
const dir = fs.readdirSync(inputPath);
dir.forEach(f => {
const inputFile = path.join(inputPath, path.basename(f));
const outputFile = path.join(outputPath, path.basename(f));
console.log(`Minifying ${inputFile} -> ${outputFile}`);
const code = fs.readFileSync(inputFile, {encoding: 'utf-8'});
const result = UglifyJS.minify(code, uglifyOptions);
if (result.error) {
throw result.error;
}
fs.writeFileSync(outputFile, result.code, 'utf8');
});