Skip to content
This repository has been archived by the owner on Jun 5, 2021. It is now read-only.

Commit

Permalink
Add hot reloading (not yet working with CSS)
Browse files Browse the repository at this point in the history
See #6.
  • Loading branch information
fwouts committed May 18, 2018
1 parent 201e8e4 commit cec299e
Show file tree
Hide file tree
Showing 6 changed files with 1,094 additions and 50 deletions.
3 changes: 2 additions & 1 deletion internal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"sass-loader": "^7.0.1",
"style-loader": "^0.21.0",
"typescript": "^2.8.3",
"webpack": "^4.6.0"
"webpack": "^4.6.0",
"webpack-serve": "^1.0.2"
}
}
2 changes: 1 addition & 1 deletion internal/web_bundle/BUILD
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package(default_visibility = ["//internal:rules"])
package(default_visibility = ["//visibility:public"])

exports_files([
"compile.js",
Expand Down
23 changes: 20 additions & 3 deletions internal/web_bundle/compile.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
const fs = require("fs-extra");
const path = require("path");
const webpack = require("webpack");

const [nodePath, scriptPath, webpackConfigFilePath] = process.argv;
const [
nodePath,
scriptPath,
htmlTemplatePath,
loadersNpmPackagesDir,
installedNpmPackagesDir,
sourceDir,
outputBundleDir,
webpackConfigFilePath
] = process.argv;

webpack(require(path.resolve(webpackConfigFilePath)), (err, stats) => {
const configGenerator = require(path.resolve(webpackConfigFilePath));
const config = configGenerator(
sourceDir,
outputBundleDir,
installedNpmPackagesDir,
loadersNpmPackagesDir,
htmlTemplatePath
);

webpack(config, (err, stats) => {
// See https://webpack.js.org/api/node/#error-handling.
if (err) {
console.error(err.stack || err);
Expand Down
33 changes: 18 additions & 15 deletions internal/web_bundle/create_webpack_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ const [
scriptPath,
libBuildfilePath,
entry,
htmlTemplatePath,
target,
mode,
optionalLibrary,
splitChunksStr,
loadersNpmPackagesDir,
installedNpmPackagesDir,
sourceDir,
outputBundleDir,
webpackConfigPath
] = process.argv;

Expand All @@ -25,15 +20,21 @@ const config = `const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: path.resolve("${path.join(
module.exports = (
sourceDir,
outputBundleDir,
installedNpmPackagesDir,
loadersNpmPackagesDir,
htmlTemplatePath,
) => ({
entry: (sourceDir.startsWith("/tmp/") ? "" : "./") + path.join(
sourceDir,
path.dirname(libBuildfilePath),
entry
)}"),
path.dirname("${libBuildfilePath}"),
"${entry}",
),
output: {
filename: "bundle.js",
path: path.resolve("${outputBundleDir}"),
path: path.resolve(outputBundleDir),
publicPath: "/",
${
optionalLibrary
Expand Down Expand Up @@ -137,17 +138,19 @@ module.exports = {
)},
resolve: {
modules: [
path.resolve("${path.join(installedNpmPackagesDir, "node_modules")}")
path.join(installedNpmPackagesDir, "node_modules"),
// Necessary for webpack-hot-client with the dev server.
path.join(loadersNpmPackagesDir, "node_modules")
]
},
resolveLoader: {
modules: [
path.resolve("${path.join(loadersNpmPackagesDir, "node_modules")}")
path.join(loadersNpmPackagesDir, "node_modules")
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve("${htmlTemplatePath}"),
template: htmlTemplatePath,
inject: true
}),
${
Expand All @@ -159,7 +162,7 @@ module.exports = {
}),`
}
]
};
});
`;

fs.writeFileSync(webpackConfigPath, config, "utf8");
100 changes: 89 additions & 11 deletions internal/web_bundle/rule.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ def _web_bundle_impl(ctx):
ctx.attr.lib[JsLibraryInfo].build_file_path,
# Entry point for Webpack (e.g. "main.ts").
ctx.attr.entry,
# Template index.html for Webpack.
ctx.file.html_template.path,
# Target for Webpack.
ctx.attr.target,
# Mode for Webpack.
Expand All @@ -35,14 +33,6 @@ def _web_bundle_impl(ctx):
ctx.attr.library_name + "/" + ctx.attr.library_target if ctx.attr.library_name else "",
# Enable split chunks or not.
"1" if ctx.attr.split_chunks else "0",
# Directory containing internal NPM dependencies (for build tools).
ctx.attr._internal_packages[NpmPackagesInfo].installed_dir.path,
# Directory containing external NPM dependencies the code depends on.
ctx.attr.lib[JsLibraryInfo].npm_packages_installed_dir.path,
# Directory containing the compiled source code of the js_library.
ctx.attr.lib[JsLibraryInfo].full_src_dir.path,
# Directory in which to place the compiled JavaScript.
ctx.outputs.bundle_dir.path,
# Path where to create the Webpack config.
webpack_config.path,
],
Expand All @@ -66,12 +56,89 @@ def _web_bundle_impl(ctx):
arguments = [
# Run `node web_bundle/compile.js`.
ctx.file._web_bundle_compile_script.path,
# Template index.html for Webpack.
ctx.file.html_template.path,
# Directory containing internal NPM dependencies (for build tools).
ctx.attr._internal_packages[NpmPackagesInfo].installed_dir.path,
# Directory containing external NPM dependencies the code depends on.
ctx.attr.lib[JsLibraryInfo].npm_packages_installed_dir.path,
# Directory containing the compiled source code of the js_library.
ctx.attr.lib[JsLibraryInfo].full_src_dir.path,
# Directory in which to place the compiled JavaScript.
ctx.outputs.bundle_dir.path,
# Path of the webpack config file.
webpack_config.path,
],
)

web_bundle = rule(
# Serve using Webpack development server.
webpack_devserver_js = ctx.actions.declare_file(ctx.label.name + ".serve.js")
ctx.actions.write(
output = webpack_devserver_js,
content = """
const fs = require("fs-extra");
const path = require("path");
const serve = require("webpack-serve");
const configGenerator = require(path.resolve("{webpack_config}"));
const config = configGenerator(
"{source_dir}",
"{output_bundle_dir}",
"{dependencies_packages_dir}",
"{internal_packages_dir}",
"{html_template}",
);
serve({{
config,
}}).then(server => {{
server.on("build-started", ({{ compiler }}) => {{
compiler.hooks.watchRun.tapPromise("check-entry-exists", async () => {{
while (!fs.existsSync(config.entry[0])) {{
console.log("Waiting for config.entry[0] to be compiled...");
await new Promise(resolve => setTimeout(resolve, 1000));
}}
}})
}});
}});
""".format(
webpack_config = webpack_config.short_path,
# Directory containing the compiled source code of the js_library.
source_dir = ctx.attr.lib[JsLibraryInfo].full_src_dir.short_path,
# Directory in which to place the compiled JavaScript.
output_bundle_dir = ctx.outputs.bundle_dir.path,
# Directory containing external NPM dependencies the code depends on.
dependencies_packages_dir = ctx.attr.lib[JsLibraryInfo].npm_packages_installed_dir.short_path,
# Directory containing internal NPM dependencies (for build tools).
internal_packages_dir = ctx.attr._internal_packages[NpmPackagesInfo].installed_dir.short_path,
# Template index.html for Webpack.
html_template = ctx.file.html_template.short_path,
),
)
ctx.actions.write(
output = ctx.outputs.devserver,
is_executable = True,
content = "NODE_PATH=" + ctx.attr._internal_packages[NpmPackagesInfo].installed_dir.short_path + "/node_modules node " + webpack_devserver_js.short_path,
)

return [
DefaultInfo(
executable = ctx.outputs.devserver,
runfiles = ctx.runfiles(
files = [
ctx.file._web_bundle_compile_script,
webpack_devserver_js,
ctx.attr._internal_packages[NpmPackagesInfo].installed_dir,
ctx.attr.lib[JsLibraryInfo].npm_packages_installed_dir,
ctx.attr.lib[JsLibraryInfo].full_src_dir,
ctx.file.html_template,
webpack_config,
],
),
),
]

web_bundle_internal = rule(
implementation=_web_bundle_impl,
attrs = {
"lib": attr.label(
Expand Down Expand Up @@ -138,5 +205,16 @@ web_bundle = rule(
},
outputs = {
"bundle_dir": "%{name}_bundle",
"devserver": "%{name}_devserver",
},
executable = True,
)

def web_bundle(tags = [], **kwargs):
web_bundle_internal(
tags = tags + [
"ibazel_notify_changes",
"ibazel_live_reload",
],
**kwargs
)
Loading

0 comments on commit cec299e

Please sign in to comment.