3

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.

pailhead
  • 5,162
  • 2
  • 25
  • 46

2 Answers2

3

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,
)

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.

2

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.

ahumesky
  • 4,203
  • 8
  • 12