bazel-examples
bazel-examples copied to clipboard
NextJs monorepo: Error: > Couldn't find a `pages` directory. Please create one under the project root
Newbie here, was trying to find a nextjs bazel example and found this. Kudos to your team!
I'm currently playing around with the NextJs example. However I want to set my project up as a monorepo, so that I can have multiple Nextjs applications.
My project dir is set up as such
node_modules/
.npmrc
.swcrc
BUILD.bazel
WORKSPACE.bazel
pnpm-lock.yaml
tsconfig.json
web/
ecommerce/
pages/
public/
styles/
BUILD.bazel
next-env.d.ts
next.config.js
In my root BAZEL.build:
load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin")
load("@aspect_rules_ts//ts:defs.bzl", "ts_config")
npm_link_all_packages(name = "node_modules")
copy_to_bin(
name = "swcrc",
srcs = [".swcrc"],
visibility = ["//visibility:public"],
)
ts_config(
name = "tsconfig",
src = "tsconfig.json",
visibility = ["//visibility:public"],
)
In my ecommerce BAZEL.build:
load("@npm//:next/package_json.bzl", next_bin = "bin")
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_run_binary", "js_test")
# Source files passed to Next.js targets
filegroup(
name = "srcs",
srcs = [
"//web/ecommerce/pages",
"//web/ecommerce/public",
"//web/ecommerce/styles",
],
)
# Config files passed to Next.js targets
filegroup(
name = "config",
srcs = [
"next.config.js",
],
visibility = ["//visibility:public"],
)
# `next dev` runs the application in development mode
# https://nextjs.org/docs/api-reference/cli#development
next_bin.next_binary(
name = "dev",
args = ["dev"],
data = [
":config",
"//:node_modules",
":srcs",
],
# TODO: Next.js isn't able to detect when to pick update changes
# when watching the runfiles. This prevents it from rebuilding & refreshing
# when running under ibazel with `ibazel_notify_changes`
# tags = ["ibazel_notify_changes"],
)
When I run bazel run //web/ecommerce:dev, it outputs this error:
❯ bazel run //web/ecommerce:dev
INFO: Analyzed target //web/ecommerce:dev (1 packages loaded, 5 targets configured).
INFO: Found 1 target...
Target //web/ecommerce:dev up-to-date:
bazel-bin/web/ecommerce/dev.sh
INFO: Elapsed time: 0.248s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Build completed successfully, 1 total action
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
Error: > Couldn't find a `pages` directory. Please create one under the project root
at Object.findPagesDir (/home/jaskerv/.cache/bazel/_bazel_jaskerv/bd4b097237f91e06ed79cb1df45916f2/execroot/monorepo/bazel-out/k8-fastbuild/bin/web/ecommerce/dev.sh.runfiles/monorepo/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/lib/find-pages-dir.js:42:19)
at new DevServer (/home/jaskerv/.cache/bazel/_bazel_jaskerv/bd4b097237f91e06ed79cb1df45916f2/execroot/monorepo/bazel-out/k8-fastbuild/bin/web/ecommerce/dev.sh.runfiles/monorepo/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/dev/next-dev-server.js:107:66)
at NextServer.createServer (/home/jaskerv/.cache/bazel/_bazel_jaskerv/bd4b097237f91e06ed79cb1df45916f2/execroot/monorepo/bazel-out/k8-fastbuild/bin/web/ecommerce/dev.sh.runfiles/monorepo/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/next.js:137:20)
at /home/jaskerv/.cache/bazel/_bazel_jaskerv/bd4b097237f91e06ed79cb1df45916f2/execroot/monorepo/bazel-out/k8-fastbuild/bin/web/ecommerce/dev.sh.runfiles/monorepo/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/next.js:149:42
at async NextServer.prepare (/home/jaskerv/.cache/bazel/_bazel_jaskerv/bd4b097237f91e06ed79cb1df45916f2/execroot/monorepo/bazel-out/k8-fastbuild/bin/web/ecommerce/dev.sh.runfiles/monorepo/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/next.js:127:24)
at async /home/jaskerv/.cache/bazel/_bazel_jaskerv/bd4b097237f91e06ed79cb1df45916f2/execroot/monorepo/bazel-out/k8-fastbuild/bin/web/ecommerce/dev.sh.runfiles/monorepo/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/cli/next-dev.js:142:9
I have a few questions around the nextjs example:
- How would I get around this error? 🙏
- What is the next_entry.js? Is this something manually defined?
- How does the
copy_to_binswcrcwork? I see it defined but not sure how its used.
I'm working on improving and generalizing this example presently so you should see some updates next week including a working devserver for development mode.
The next_entry.js is an unfortunate work-around for running next build under bazel so that next & react don't get confused by finding themselves in both the runfiles and execroot node_modules trees. The code is sensitive to only being resolved to a single node_modules tree. Its required atm but the example does not make it very portable so I'll clean it up to abstract away some of the complexity and show how to use it in a monorepo.
The copy_to_bin is a rule that copies a source file to the bazel output tree. rules_js and its derivate rules such as rules_ts always copy source files to the output tree so that node tools don't have to be taught to be aware of both the source tree and the output tree. We took this approach in rules_js since it is easier to adapt Bazel to current node tooling which writes its outputs to the same tree as sources then it is to fix all the node tooling to be aware of two different trees. Some more info on this in the rules_js README if you are curious: https://github.com/aspect-build/rules_js#running-nodejs-programs.
Awesome, super excited to see how it works out 😄
This is generalizing into a next() macro and adding a devserver that works with ibazel: https://github.com/aspect-build/bazel-examples/pull/121
@Jaskerv did that PR solve this for you?
@alexeagle Thankyou so much, that PR was a huge help 🚀🚀🚀
I've changed up how I am managing the monorepo. I made it so that each project is managing its own dependencies. This makes it easier managing dependencies.
For example
projectA
BUILD.bazel
package.json <--- next version 13
projectB
BUILD.bazel
package.json <--- next version 12
WORKSPACE.bazel
Since npm_translate_lock can only be defined in the WORKSPACE.bazel, this causes an issue when referencing npm modules defined in the each project.
Is there a way around this without manually defining npm_import for each project, or should I revert back to having all dependencies in the root package.json?
You could use pnpm workspaces which rules_js support. We have a contrived example here: https://github.com/aspect-build/rules_js/tree/main/e2e/pnpm_workspace of how it is wired up with Bazel.
The pnpm workspaces work well!!
However, I seem to have some trouble building my next project. I get the following sample error:
JsRunBinary web/project/.next failed: (Exit 1): next_js_binary.sh failed: error executing command bazel-out/k8-opt-exec-2B5CBBC6/bin/web/project/next_js_binary.sh build
> Build error occurred
[Error: EROFS: read-only file system, open '.../node_modules/next/dist/server/initialize-require-hook.js'] {
errno: -30,
code: 'EROFS',
syscall: 'open',
path: '.../bazel-out/k8-fastbuild/bin/node_modules/.aspect_rules_js/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/initialize-require-hook.js'
}
Any ideas? 😮
Going to close this as I haven't touched this in a while. Thanks everyone :)