整合 Bazel 和 Webpack

4

我正在尝试将Webpack引入由Bazel构建的Monorepo中。

我的代码结构类似如下:

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

我已经设置好了 webpack.config.js,所以当我运行 webpack 时,会得到以下类似的内容:

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

据我所知,这是构建一个 Web 应用程序的过程。如果我将 /dist 目录作为服务目录,在浏览器中加载 generated.html 文件,该文件会进而加载其他文件。
Bazel 不支持我的 /dist 目录,但我无法理解所有遇到的错误。我正在尝试运行类似以下命令的操作。
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",
  ],
)

当我进行调整时,我并不完全知道自己在调整什么,但有时会出现“dist”是目录的投诉,有时则会抱怨正在使用只读文件系统。

我的期望是,如果我能够在没有bazel的情况下运行npm run buildwebpack,那么我应该能够在使用bazel时运行它。在我看来,这似乎应该是bazel的某种中间步骤,类似于部署,并使用来自webpack的结果。我甚至可以将所有结果压缩在/dist中,但仍然不确定如何使bazel接受它。

我能否以某种方式告诉bazel“制作文件webpacked.zip,然后在你的下一步中使用它”?

到目前为止,我的研究结果很少表明这要么非常复杂,要么不可能,很可能不是这些工具的正确使用方式。任何帮助都将不胜感激。

2个回答

4

正如 ahumesky 提到的,有nodejs规则可供使用。建议优先使用该规则而不是genrule。 但是,ahumesky提到的示例仅处理一个输出文件。

下面是适用于多个输出文件的工作示例:

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

您可以在下一步中使用标签 "webpack_build"。除非您的下一个规则期望单个文件,否则无需压缩它。

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

你可以在这里找到所有的代码。

2

genrule在其outs中无法处理目录。有几种方法:

  1. genrule的最后一步中将输出目录中的所有内容打包成zip文件,并将该zip文件声明在outs中。缺点是您必须在每个处理这些文件的步骤中压缩和解压缩它们(跳过压缩可能会加快速度)。

  2. 编写Starlark规则,其中有用于处理目录输出的API。有关如何执行此操作的更多信息,请参见此问题:Bazel: genrule that outputs an directory

  3. nodejs bazel rules似乎支持webpack:https://github.com/bazelbuild/rules_nodejs/tree/c5d09095ba4653b4cd5837360e13ff2b105ba3be/examples/react_webpack因此,可以尝试使用nodejs规则。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接