feat: add bazel build utils
This commit is contained in:
parent
f23eb23b96
commit
0a8bb236cf
8
src/bazel/BUILD.bazel
Normal file
8
src/bazel/BUILD.bazel
Normal file
@ -0,0 +1,8 @@
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "nodejs_binary")
|
||||
exports_files(["webpack.config.js", "test.js"])
|
||||
|
||||
nodejs_binary(
|
||||
name = "webpack",
|
||||
entry_point = "webpack/bin/webpack",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
0
src/bazel/WORKSPACE
Normal file
0
src/bazel/WORKSPACE
Normal file
109
src/bazel/karma.conf.js
Normal file
109
src/bazel/karma.conf.js
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Warning: the testing rule will change.
|
||||
*
|
||||
* Instead of running karma outside of bazel against the bin_dir directory, we will run it as part of the bazel process.
|
||||
*/
|
||||
module.exports = function(config) {
|
||||
const webpackConfig = {
|
||||
resolveLoader: {
|
||||
alias: {
|
||||
"template-loader": '@nrwl/nx/bazel/template-loader'
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.component\.js$/,
|
||||
use: [
|
||||
{loader: 'template-loader' }
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: [
|
||||
{loader: 'raw-loader' }
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{loader: 'raw-loader' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
config.set({
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: `${config.opts.bin_dir}/${config.opts.app}`,
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
{ pattern: 'test.js', watched: false}
|
||||
],
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [],
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
'test.js': ['webpack']
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: config.opts.reporters ? config.opts.reporters : (config.opts.progress ? ['progress'] : ['dots']),
|
||||
|
||||
webpack: webpackConfig,
|
||||
|
||||
webpackMiddleware: {
|
||||
stats: 'errors-only'
|
||||
},
|
||||
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('karma-webpack')
|
||||
],
|
||||
|
||||
coverageIstanbulReporter: {
|
||||
reports: [ 'html', 'lcovonly' ],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
|
||||
// web server port
|
||||
port: config.opts.port ? config.opts.port : 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: config.opts.colors,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.opts.log ? config.opts.log: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
// browsers: ['PhantomJS'],
|
||||
browsers: ['Chrome'],
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity
|
||||
});
|
||||
};
|
||||
30
src/bazel/template-loader.js
Normal file
30
src/bazel/template-loader.js
Normal file
@ -0,0 +1,30 @@
|
||||
var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*([,}]))/gm;
|
||||
var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g;
|
||||
var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g;
|
||||
|
||||
function replaceStringsWithRequires(string) {
|
||||
return string.replace(stringRegex, function (match, quote, url) {
|
||||
if (url.charAt(0) !== ".") {
|
||||
url = "./" + url;
|
||||
}
|
||||
return "require('" + url + "')";
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function(source, sourcemap) {
|
||||
// Not cacheable during unit tests;
|
||||
this.cacheable && this.cacheable();
|
||||
|
||||
var newSource = source.replace(templateUrlRegex, function (match, url) {
|
||||
return "template:" + replaceStringsWithRequires(url);
|
||||
}).replace(stylesRegex, function (match, urls) {
|
||||
return "styles:" + replaceStringsWithRequires(urls);
|
||||
});
|
||||
|
||||
// Support for tests
|
||||
if (this.callback) {
|
||||
this.callback(null, newSource, sourcemap)
|
||||
} else {
|
||||
return newSource;
|
||||
}
|
||||
};
|
||||
62
src/bazel/webpack.bzl
Normal file
62
src/bazel/webpack.bzl
Normal file
@ -0,0 +1,62 @@
|
||||
def _collect_es5_sources_impl(target, ctx):
|
||||
result = set()
|
||||
if hasattr(ctx.rule.attr, "srcs"):
|
||||
for dep in ctx.rule.attr.srcs:
|
||||
if hasattr(dep, "es5_sources"):
|
||||
result += dep.es5_sources
|
||||
if hasattr(target, "typescript"):
|
||||
result += target.typescript.es5_sources
|
||||
return struct(es5_sources = result)
|
||||
|
||||
_collect_es5_sources = aspect(
|
||||
_collect_es5_sources_impl,
|
||||
attr_aspects = ["deps", "srcs"],
|
||||
)
|
||||
|
||||
def _webpack_bundle_impl(ctx):
|
||||
inputs = set()
|
||||
for s in ctx.attr.srcs:
|
||||
if hasattr(s, "es5_sources"):
|
||||
inputs += s.es5_sources
|
||||
|
||||
config = ctx.files.config
|
||||
|
||||
if ctx.attr.mode == 'prod':
|
||||
main = ctx.new_file('bundles/main.bundle.prod.js')
|
||||
polyfills = ctx.new_file('bundles/polyfills.bundle.prod.js')
|
||||
vendor = ctx.new_file('bundles/vendor.bundle.prod.js')
|
||||
styles = ctx.new_file('bundles/styles.bundle.prod.js')
|
||||
else:
|
||||
main = ctx.new_file('bundles/main.bundle.js')
|
||||
polyfills = ctx.new_file('bundles/polyfills.bundle.js')
|
||||
vendor = ctx.new_file('bundles/vendor.bundle.js')
|
||||
styles = ctx.new_file('bundles/styles.bundle.js')
|
||||
|
||||
inputs += [config]
|
||||
args = []
|
||||
|
||||
if ctx.attr.mode == 'prod':
|
||||
args += ['-p']
|
||||
|
||||
args += ['--config', config.path]
|
||||
args += ['--env.bin_dir', ctx.configuration.bin_dir.path]
|
||||
args += ['--env.package', ctx.label.package]
|
||||
args += ['--env.mode', ctx.attr.mode]
|
||||
|
||||
ctx.action(
|
||||
progress_message = "Webpack bundling %s" % ctx.label,
|
||||
inputs = inputs.to_list(),
|
||||
outputs = [main, polyfills, vendor, styles],
|
||||
executable = ctx.executable._webpack,
|
||||
arguments = args,
|
||||
)
|
||||
return DefaultInfo(files=depset([main, polyfills, vendor, styles]))
|
||||
|
||||
webpack_bundle = rule(implementation = _webpack_bundle_impl,
|
||||
attrs = {
|
||||
"srcs": attr.label_list(allow_files=True, aspects=[_collect_es5_sources]),
|
||||
"config": attr.label(allow_single_file=True, mandatory=True),
|
||||
"mode": attr.string(default="dev"),
|
||||
"_webpack": attr.label(default=Label("@nrwl//:webpack"), executable=True, cfg="host")
|
||||
}
|
||||
)
|
||||
185
src/bazel/webpack.config.js
Normal file
185
src/bazel/webpack.config.js
Normal file
@ -0,0 +1,185 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
|
||||
const CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
const { NoEmitOnErrorsPlugin, SourceMapDevToolPlugin, NamedModulesPlugin } = require('webpack');
|
||||
const { GlobCopyWebpackPlugin, NamedLazyChunksWebpackPlugin, BaseHrefWebpackPlugin } = require('@angular/cli/plugins/webpack');
|
||||
const { CommonsChunkPlugin } = require('webpack').optimize;
|
||||
|
||||
const nodeModules = path.join(process.cwd(), 'node_modules');
|
||||
const realNodeModules = fs.realpathSync(nodeModules);
|
||||
|
||||
const entryPoints = ["inline", "polyfills", "styles", "vendor", "main"];
|
||||
const baseHref = "";
|
||||
|
||||
module.exports = function(env) {
|
||||
const name = path.parse(env.package).name;
|
||||
const apps = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.angular-cli.json'), 'UTF-8')).apps;
|
||||
const appConfig = apps.filter(a => a.name === name)[0];
|
||||
const out = path.join(process.cwd(), env.bin, env.package, 'bundles');
|
||||
const src = path.join(process.cwd(), env.bin, appConfig.root);
|
||||
|
||||
// victor todo: remove it when ng_module rule is fixed
|
||||
const alias = Object.assign({}, {
|
||||
'@angular/core/core': '@angular/core/@angular/core.es5',
|
||||
'@angular/common/common': '@angular/common/@angular/common.es5',
|
||||
'@angular/platform-browser/platform-browser': '@angular/platform-browser/@angular/platform-browser.es5'
|
||||
});
|
||||
|
||||
return {
|
||||
"resolve": {
|
||||
"extensions": [
|
||||
".js"
|
||||
],
|
||||
"modules": [
|
||||
"./node_modules"
|
||||
],
|
||||
"symlinks": true,
|
||||
alias
|
||||
},
|
||||
"resolveLoader": {
|
||||
"modules": [
|
||||
"./node_modules"
|
||||
]
|
||||
},
|
||||
"entry": {
|
||||
"main": [
|
||||
tsToJs(path.join(src, appConfig.main))
|
||||
],
|
||||
"polyfills": [
|
||||
tsToJs(path.join(src, appConfig.polyfills))
|
||||
],
|
||||
"styles": appConfig.styles.map(s => path.join(src, s))
|
||||
},
|
||||
"output": {
|
||||
"path": out,
|
||||
"filename": "[name].bundle.js",
|
||||
"chunkFilename": "[id].chunk.js"
|
||||
},
|
||||
"module": {
|
||||
"rules": [
|
||||
{
|
||||
"enforce": "pre",
|
||||
"test": /\.js$/,
|
||||
"loader": "source-map-loader",
|
||||
"exclude": [
|
||||
/(\\|\/)node_modules(\\|\/)/
|
||||
]
|
||||
},
|
||||
{
|
||||
"test": /\.html$/,
|
||||
"loader": "raw-loader"
|
||||
},
|
||||
{
|
||||
"test": /\.(eot|svg|cur)$/,
|
||||
"loader": "file-loader?name=[name].[hash:20].[ext]"
|
||||
},
|
||||
{
|
||||
"test": /\.(jpg|png|webp|gif|otf|ttf|woff|woff2|ani)$/,
|
||||
"loader": "url-loader?name=[name].[hash:20].[ext]&limit=10000"
|
||||
}
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
new NoEmitOnErrorsPlugin(),
|
||||
new GlobCopyWebpackPlugin({
|
||||
"patterns": [
|
||||
"assets",
|
||||
"favicon.ico"
|
||||
],
|
||||
"globOptions": {
|
||||
"cwd": src,
|
||||
"dot": true,
|
||||
"ignore": "**/.gitkeep"
|
||||
}
|
||||
}),
|
||||
new ProgressPlugin(),
|
||||
new CircularDependencyPlugin({
|
||||
"exclude": /(\\|\/)node_modules(\\|\/)/,
|
||||
"failOnError": false
|
||||
}),
|
||||
new NamedLazyChunksWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
"template": path.join(src, 'index.html'),
|
||||
"filename": "./index.html",
|
||||
"hash": false,
|
||||
"inject": true,
|
||||
"compile": true,
|
||||
"favicon": false,
|
||||
"minify": false,
|
||||
"cache": true,
|
||||
"showErrors": true,
|
||||
"chunks": "all",
|
||||
"excludeChunks": [],
|
||||
"xhtml": true,
|
||||
"chunksSortMode": function sort(left, right) {
|
||||
let leftIndex = entryPoints.indexOf(left.names[0]);
|
||||
let rightindex = entryPoints.indexOf(right.names[0]);
|
||||
if (leftIndex > rightindex) {
|
||||
return 1;
|
||||
}
|
||||
else if (leftIndex < rightindex) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}),
|
||||
new BaseHrefWebpackPlugin({}),
|
||||
new CommonsChunkPlugin({
|
||||
"name": [
|
||||
"inline"
|
||||
],
|
||||
"minChunks": null
|
||||
}),
|
||||
new CommonsChunkPlugin({
|
||||
"name": [
|
||||
"vendor"
|
||||
],
|
||||
"minChunks": (module) => {
|
||||
return module.resource
|
||||
&& (module.resource.startsWith(nodeModules)
|
||||
|| module.resource.startsWith(realNodeModules));
|
||||
},
|
||||
"chunks": [
|
||||
"main"
|
||||
]
|
||||
}),
|
||||
new SourceMapDevToolPlugin({
|
||||
"filename": "[file].map[query]",
|
||||
"moduleFilenameTemplate": "[resource-path]",
|
||||
"fallbackModuleFilenameTemplate": "[resource-path]?[hash]",
|
||||
"sourceRoot": "webpack:///"
|
||||
}),
|
||||
new CommonsChunkPlugin({
|
||||
"name": [
|
||||
"main"
|
||||
],
|
||||
"minChunks": 2,
|
||||
"async": "common"
|
||||
}),
|
||||
new NamedModulesPlugin({}),
|
||||
],
|
||||
"node": {
|
||||
"fs": "empty",
|
||||
"global": true,
|
||||
"crypto": "empty",
|
||||
"tls": "empty",
|
||||
"net": "empty",
|
||||
"process": true,
|
||||
"module": false,
|
||||
"clearImmediate": false,
|
||||
"setImmediate": false
|
||||
},
|
||||
"devServer": {
|
||||
"historyApiFallback": true
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function tsToJs(s) {
|
||||
return `${s.substring(0, s.length - 3)}.js`;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
load("@build_bazel_rules_angular//:defs.bzl", "ng_module")
|
||||
load("@build_bazel_rules_nrwl//:webpack.bzl", "webpack_bundle")
|
||||
load("@nrwl//:webpack.bzl", "webpack_bundle")
|
||||
|
||||
ng_module(
|
||||
name = "compile",
|
||||
@ -9,6 +9,7 @@ ng_module(
|
||||
tsconfig = "//:tsconfig.json"
|
||||
)
|
||||
|
||||
# temporary work-around to handle static
|
||||
genrule(
|
||||
name = "copy_static",
|
||||
srcs = ["src"] + glob(["src/**/*"], exclude=["**/*.ts"]),
|
||||
@ -31,5 +32,5 @@ filegroup(
|
||||
webpack_bundle(
|
||||
name = "<%= name %>",
|
||||
srcs = ["compile_and_static"],
|
||||
config = "@build_bazel_rules_nrwl//:webpack.config.js"
|
||||
config = "@nrwl//:webpack.config.js"
|
||||
)
|
||||
|
||||
@ -3,6 +3,7 @@ exports_files(["tsconfig.json"])
|
||||
|
||||
load("@build_bazel_rules_angular//:defs.bzl", "ng_external_libraries")
|
||||
|
||||
# change to glob(["node_modules/**/*.js", "node_modules/**/*.json", "node_modules/**/*.d.ts"])
|
||||
filegroup(name = "node_modules", srcs = glob([
|
||||
# should not be whitelisted
|
||||
"node_modules/@angular/**",
|
||||
@ -20,14 +21,13 @@ filegroup(name = "node_modules", srcs = glob([
|
||||
"node_modules/webpack/**"
|
||||
], exclude=["node_modules/@angular/cli/**"]))
|
||||
|
||||
# this should go away soon when we do bootstrap codegen in the scripts.postinstall
|
||||
ng_external_libraries(name = "ng_libs", srcs = glob([
|
||||
"node_modules/@angular/**"
|
||||
], exclude = [
|
||||
"node_modules/@angular/cli/**",
|
||||
"node_modules/@angular/platform-browser/animations*",
|
||||
"node_modules/@angular/platform-browser/animations/**",
|
||||
|
||||
# Alex E?
|
||||
"node_modules/@angular/router*",
|
||||
"node_modules/@angular/router/**",
|
||||
]))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# <%= className %>
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version <%= version %>.
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version EXPERIMENTAL BAZEL.
|
||||
|
||||
## Development server
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user