Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

integrating bazel and webpack

Tags:

webpack

bazel

I'm trying to bring webpack into a monorepo that's being built by bazel.

I have something like

source/
-moduleA/
-moduleB/
--package.json
--static/
---image.png
--source/
---foo.ts
---bar.js
---baz.jsx

I've setup my webpack.config.js so that when i run webpack i get something like:

dist/
-generated.html
-bundled.js
-copied/
--css/
--img/

As far as my knowledge goes this builds a web app. If i serve /dist somehow my browser will load generated.html which will in turn load the other files.

Bazel does not like my /dist dir, but i can't make sense out of all the errors that i've encountered. I'm trying to run something like this

genrule(
  name = "webpack_stuff",
  srcs = [
    ":deps"
  ],
  cmd = " && ".join([
    "cd source/core/viewer",
    "node node_modules/webpack/bin/webpack.js --config webpack.prod.js --output-path $@",
  ]),
  outs = ["dist"],
  visibility = [
    "//visibility:public",
  ],
)

I'm not entirely sure what i'm tweaking when i tweak, but at times i get a complaint that "dist" is a directory, other times it complains about working with a read-only file system.

My expectation was that if i'm able to run npm run build or webpack without bazel, that i would be able to run it with bazel. This looks like it should be some intermediary step for bazel as it should do something akin to deployment in my layman mind, with the results from webpack. I'm even able to zip all the results in /dist but still not sure how to make bazel accept it.

Can i somehow tell bazel "make the file webpacked.zip and then use it in your next steps"?

My research so far yielded few results indicating that this is either very involved or impossible, and most likely not how these tools are supposed to be used. Any help would be most welcome.

like image 722
pailhead Avatar asked Oct 28 '25 05:10

pailhead


2 Answers

As ahumesky mentioned, there is rules for nodejs. I would recommend using that over genrule. However, the example ahumesky mentioned only handles one output file.

Here's a working example that works for multiple output files:

BUILD.bazel

load("@npm//webpack-cli:index.bzl", webpack = "webpack_cli")

webpack(
    name = "webpack_build",
    args = [
        "-o",
        "$(@D)",
    ],
    data = [
        ":babel.config.js",
        ":src",
        ":webpack.config.js",
        "@npm//:node_modules",
    ],
    output_dir = True,
)
  • $(@D) is the output directory. See npm_package_bin's args for more info.
  • output_dir = 1 declares that the output should be a directory. See npm_package_bin's output_dir for more information.

You can use the label "webpack_build" in your next step. There is no need to zip it up, unless your next rule is expecting a single file.

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = () => {
    return {
        entry: [
            './src/js/index.tsx',
        ],
        mode: 'development',
        module: {
            rules: [{
                test: /\.(js|jsx|ts|tsx)$/,
                exclude: /node_modules/,
                use: ['babel-loader'],
            }],
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './src/html/index.html',
                favicon: './src/media/favicon.ico',
            }),
        ],
        resolve: {
            extensions: ['.wasm', '.mjs', '.json', '.js', '.jsx', '.ts', '.tsx'],
        },
    };
};

WORKSPACE

workspace(
    name = "question_60049886",
    managed_directories = {"@npm": ["node_modules"]},
)

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "build_bazel_rules_nodejs",
    sha256 = "4501158976b9da216295ac65d872b1be51e3eeb805273e68c516d2eb36ae1fbb",
    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/4.4.1/rules_nodejs-4.4.1.tar.gz"],
)

load("@build_bazel_rules_nodejs//:index.bzl", "npm_install")

npm_install(
    name = "npm",
    package_json = "//:package.json",
    package_lock_json = "//:package-lock.json",
)

You can find all the code here.

like image 58
Brok Bucholtz Avatar answered Oct 31 '25 08:10

Brok Bucholtz


genrule doesn't know how to work with directories in its outs. There are a few approaches:

  1. Zip up everything in the output directory as the last step in the genrule, and declare that zip file in the outs. The disadvantage is that you have to zip and unzip at every step that deals with these files (skipping compression might speed that up a little).

  2. Write Starlark rules, where there are APIs for working with directory outputs. More information on how to do this is in this question: Bazel: genrule that outputs an directory

  3. The nodejs bazel rules appear to support webpack: https://github.com/bazelbuild/rules_nodejs/tree/c5d09095ba4653b4cd5837360e13ff2b105ba3be/examples/react_webpack So maybe try investigating using the nodejs rules.

like image 44
ahumesky Avatar answered Oct 31 '25 08:10

ahumesky