aspect-build / rules_js

High-performance Bazel rules for running Node.js tools and building JavaScript projects
https://docs.aspect.build/rules/aspect_rules_js
Apache License 2.0
299 stars 103 forks source link

Example of building an ejected React app #427

Open alexeagle opened 2 years ago

alexeagle commented 2 years ago

If you eject from CRA (react-scripts) you can make something more incremental and bazel-idiomatic.

https://github.com/heartless-clown/bazel_aspect_rules_js_react/blob/ejected/app/react-app/BUILD.bazel#L111-L112 is a start

Also note: we promised this as "react-scripts-like" in https://github.com/bazelbuild/rules_nodejs/blob/stable/docs/examples.md#react

gregmagolan commented 1 year ago

The https://github.com/aspect-build/bazel-examples/tree/main/react-cra is now ejected with fine grained ts_project transpilation & type checking done before the react-scripts build step. Babel not being used as suggested in https://github.com/bazelbuild/rules_nodejs/blob/stable/docs/examples.md#react but that would be easy to support with the transpiler attribute of ts_project.

alexeagle commented 1 year ago

Should we still keep an example of react that's not ejected?

yads commented 1 year ago

Am I missing something? The example react-cra does not appear to be ejected as it's still using react-scripts rather than the ejected scripts that are generated.

gregmagolan commented 1 year ago

I "ejected" it in the Bazel sense that it is now using fine grained ts_project targets for transpilation: https://github.com/aspect-build/bazel-examples/blob/main/react-cra/src/BUILD.bazel#L34 and not in the webpack config sense. The CRA webpack build is now consuming the pre-transpiled .js files by the ts_project targets it depends on instead of doing transpilation & bundling.

Ejecting the webpack config is orthogonal to ejecting the transpilation. It could be done relatively easily as well.

gregmagolan commented 1 year ago

I'll re-open this as a place holder to add an example of an ejected CRA webpack config as well.

yads commented 1 year ago

That would be great, I'm currently trying to use the various js_rules to replace some legacy custom rules that were written a while ago and an example with a CRA ejected app would be great.

On a tangential topic, I noticed that due to the use of symlinks in the rules/bazel live reload features don't seem to work (due to watchman). Is there a way to get around using symlinked files?

gregmagolan commented 1 year ago

On a tangential topic, I noticed that due to the use of symlinks in the rules/bazel live reload features don't seem to work (due to watchman). Is there a way to get around using symlinked files?

The js_run_devserver rule should solve for that. Do you have an example or repro of it failing?

yads commented 1 year ago

Hey there, sorry I've been out on holidays. The issue I'm seeing with js_run_devserver is I'm trying to run what is effectively scripts/start.js


js_run_devserver(
    name = "start",
    chdir = package_name(),
    data = _RUNTIME_DEPS,
    entry_point = "scripts/start.js",
)

However, it is complaining that the rule got multiple values for paramter 'entry_point'. Not sure if that's a bug, since the docs seem to indicate it is a valid parameter.

yads commented 1 year ago

Ah the thing I also missed is that you need ibazel in order to pick up the changes. I think just using js_binary likely will work with ibazel.

gregmagolan commented 1 year ago

Ahh. Looks like the doc generation is wrong for that attribute since it is not meant to be set the by the user. The macro looks like this,

def js_run_devserver(**kwargs):
    _js_run_devserver(
        enable_runfiles = select({
            "@aspect_rules_js//js/private:enable_runfiles": True,
            "//conditions:default": False,
        }),
        entry_point = "@aspect_rules_js//js/private:js_devserver_entrypoint",
        # This rule speaks the ibazel protocol
        tags = kwargs.pop("tags", []) + ["ibazel_notify_changes"],
        **kwargs
    )

User facing API equivalents to entry_point are the command ortool attributes. Some basic usage examples here: https://github.com/aspect-build/rules_js/blob/main/e2e/js_run_devserver/src/BUILD.bazel and a more representative example of how you'd hold it in a real application here for a react-cra devserver https://github.com/aspect-build/bazel-examples/blob/ec19825e711ef2d1db68352ed8b152cad65cd257/react-cra/BUILD.bazel#L40.

rules_webpack has its own webpack_devserver convenience macro that wraps js_run_devserver and sets the tool as webpack: https://github.com/aspect-build/rules_webpack/blob/05fdb5a721dedf05e92c274a25cbc41edd602f0a/webpack/private/webpack_devserver.bzl#L5

gregmagolan commented 1 year ago

I'll make an issue for it and also post a better failure message if it gets set by accident by a user.

yads commented 1 year ago

That makes sense, thanks for looking into it. I'll try using node as the tool.

gregmagolan commented 1 year ago

That makes sense, thanks for looking into it. I'll try using node as the tool.

You can pass a js_binary target as the tool. That is where you'll specify your custom entry point.