| 1 | """Wrapper macro to make the next.js rules more ergonomic. |
| 2 | |
| 3 | This might be upstreamed to a "contrib" folder in rules_js at some point. |
| 4 | Follow https://github.com/aspect-build/rules_js/issues/1292 |
| 5 | """ |
| 6 | |
| 7 | load("@aspect_rules_js//js:defs.bzl", "js_run_binary", "js_run_devserver") |
| 8 | |
| 9 | def next( |
| 10 | name, |
| 11 | srcs, |
| 12 | data, |
| 13 | next_js_binary, |
| 14 | next_bin, |
| 15 | next_build_out = ".next", |
| 16 | next_export_out = "out", |
| 17 | **kwargs): |
| 18 | """Generates Next.js targets build, dev & start targets. |
| 19 | |
| 20 | `{name}` - a js_run_binary build target that runs `next build` |
| 21 | `{name}_dev` - a js_run_devserver binary target that runs `next dev` |
| 22 | `{name}_start` - a js_run_devserver binary target that runs `next start` |
| 23 | |
| 24 | Use this macro in the BUILD file at the root of a next app where the `next.config.js` file is |
| 25 | located. |
| 26 | |
| 27 | For example, a target such as |
| 28 | |
| 29 | ``` |
| 30 | next( |
| 31 | name = "next", |
| 32 | srcs = [ |
| 33 | "//next.js/pages", |
| 34 | "//next.js/public", |
| 35 | "//next.js/styles", |
| 36 | ], |
| 37 | data = [ |
| 38 | "//next.js:node_modules/next", |
| 39 | "//next.js:node_modules/react-dom", |
| 40 | "//next.js:node_modules/react", |
| 41 | "//next.js:node_modules/typescript", |
| 42 | "next.config.js", |
| 43 | "package.json", |
| 44 | ], |
| 45 | next_bin = "../../node_modules/.bin/next", |
| 46 | next_js_binary = "//:next_js_binary", |
| 47 | ) |
| 48 | ``` |
| 49 | |
| 50 | in an `next.js/BUILD.bazel` file where the root `BUILD.bazel` file has |
| 51 | next linked to `node_modules` and the `next_js_binary`: |
| 52 | |
| 53 | ``` |
| 54 | load("@npm//:defs.bzl", "npm_link_all_packages") |
| 55 | load("@npm//:next/package_json.bzl", next_bin = "bin") |
| 56 | |
| 57 | npm_link_all_packages(name = "node_modules") |
| 58 | |
| 59 | next_bin.next_binary( |
| 60 | name = "next_js_binary", |
| 61 | visibility = ["//visibility:public"], |
| 62 | ) |
| 63 | ``` |
| 64 | |
| 65 | will create the targets: |
| 66 | |
| 67 | ``` |
| 68 | //next.js:next |
| 69 | //next.js:next_dev |
| 70 | //next.js:next_start |
| 71 | ``` |
| 72 | |
| 73 | To build the above next app, equivalent to running |
| 74 | `next build` outside Bazel, run, |
| 75 | |
| 76 | ``` |
| 77 | bazel build //next.js:next |
| 78 | ``` |
| 79 | |
| 80 | To run the development server in watch mode with |
| 81 | [ibazel](https://github.com/bazelbuild/bazel-watcher), equivalent to running |
| 82 | `next dev` outside Bazel, run |
| 83 | |
| 84 | ``` |
| 85 | ibazel run //next.js:next_dev |
| 86 | ``` |
| 87 | |
| 88 | To run the production server in watch mode with |
| 89 | [ibazel](https://github.com/bazelbuild/bazel-watcher), equivalent to running |
| 90 | `next start` outside Bazel, |
| 91 | |
| 92 | ``` |
| 93 | ibazel run //next.js:next_start |
| 94 | ``` |
| 95 | |
| 96 | To export the above next app, equivalent to running |
| 97 | `next export` outside Bazel, run, |
| 98 | |
| 99 | ``` |
| 100 | bazel build //next.js:next_export |
| 101 | ``` |
| 102 | |
| 103 | Args: |
| 104 | name: The name of the build target. |
| 105 | |
| 106 | srcs: Source files to include in build & dev targets. |
| 107 | Typically these are source files or transpiled source files in Next.js source folders |
| 108 | such as `pages`, `public` & `styles`. |
| 109 | |
| 110 | data: Data files to include in all targets. |
| 111 | These are typically npm packages required for the build & configuration files such as |
| 112 | package.json and next.config.js. |
| 113 | |
| 114 | next_js_binary: The next js_binary. Used for the `build `target. |
| 115 | |
| 116 | Typically this is a js_binary target created using `bin` loaded from the `package_json.bzl` |
| 117 | file of the npm package. |
| 118 | |
| 119 | See main docstring above for example usage. |
| 120 | |
| 121 | next_bin: The next bin command. Used for the `dev` and `start` targets. |
| 122 | |
| 123 | Typically the path to the next entry point from the current package. For example `./node_modules/.bin/next`, |
| 124 | if next is linked to the current package, or a relative path such as `../node_modules/.bin/next`, if next is |
| 125 | linked in the parent package. |
| 126 | |
| 127 | See main docstring above for example usage. |
| 128 | |
| 129 | next_build_out: The `next build` output directory. Defaults to `.next` which is the Next.js default output directory for the `build` command. |
| 130 | |
| 131 | next_export_out: The `next export` output directory. Defaults to `out` which is the Next.js default output directory for the `export` command. |
| 132 | |
| 133 | **kwargs: Other attributes passed to all targets such as `tags`. |
| 134 | """ |
| 135 | |
| 136 | tags = kwargs.pop("tags", []) |
| 137 | |
| 138 | # `next build` creates an optimized bundle of the application |
| 139 | # https://nextjs.org/docs/api-reference/cli#build |
| 140 | js_run_binary( |
| 141 | name = name, |
| 142 | tool = next_js_binary, |
| 143 | args = ["build"], |
| 144 | srcs = srcs + data, |
| 145 | out_dirs = [next_build_out], |
| 146 | chdir = native.package_name(), |
| 147 | tags = tags, |
| 148 | **kwargs |
| 149 | ) |
| 150 | |
| 151 | # `next dev` runs the application in development mode |
| 152 | # https://nextjs.org/docs/api-reference/cli#development |
| 153 | js_run_devserver( |
| 154 | name = "{}_dev".format(name), |
| 155 | command = next_bin, |
| 156 | args = ["dev"], |
| 157 | data = srcs + data, |
| 158 | chdir = native.package_name(), |
| 159 | tags = tags, |
| 160 | **kwargs |
| 161 | ) |
| 162 | |
| 163 | # `next start` runs the application in production mode |
| 164 | # https://nextjs.org/docs/api-reference/cli#production |
| 165 | js_run_devserver( |
| 166 | name = "{}_start".format(name), |
| 167 | command = next_bin, |
| 168 | args = ["start"], |
| 169 | data = data + [name], |
| 170 | chdir = native.package_name(), |
| 171 | tags = tags, |
| 172 | **kwargs |
| 173 | ) |
| 174 | |
| 175 | # `next export` runs the application in production mode |
| 176 | # https://nextjs.org/docs/api-reference/cli#production |
| 177 | js_run_binary( |
| 178 | name = "{}_export".format(name), |
| 179 | tool = next_js_binary, |
| 180 | args = ["export"], |
| 181 | srcs = data + [name], |
| 182 | out_dirs = [next_export_out], |
| 183 | chdir = native.package_name(), |
| 184 | # Tagged as "manual" since this `next export` writes back to the `.next` directory which causes issues with |
| 185 | # trying to write to an input. See https://github.com/vercel/next.js/issues/43344. |
| 186 | # TODO: fix in Next.js (https://github.com/vercel/next.js/issues/43344) or find work-around. |
| 187 | tags = tags + ["manual"], |
| 188 | **kwargs |
| 189 | ) |