Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: suppport for NX monorepos #387

Merged
merged 41 commits into from Aug 17, 2022

Conversation

FinnDore
Copy link
Contributor

@FinnDore FinnDore commented Aug 7, 2022

What does this PR address?

Out of the box support for NX mono repos. ( nexjs apps, express apps and apps that build to an index.js )

  • Make sure to follow GitHub's guide on creating PR.
  • Did you read through contribution guidelines?
  • Did your changes require updates to the documentation? Have you updated those accordingly? - New env var so yes?
  • Did you write tests to cover your changes? Did it pass locally when running cargo test?
  • Have you run cargo fmt, cargo check and cargo clippy locally to ensure that CI passes?

@FinnDore FinnDore changed the title Finndore/nixpack nx feat: suppport for NX monorepos Aug 7, 2022
src/providers/node.rs Outdated Show resolved Hide resolved
@FinnDore
Copy link
Contributor Author

FinnDore commented Aug 7, 2022

Think this is ready for a review whenever someone is free 😊

@FinnDore FinnDore marked this pull request as ready for review August 7, 2022 20:33
examples/node-nx/.dockerignore Outdated Show resolved Hide resolved
examples/node-nx/.editorconfig Outdated Show resolved Hide resolved
src/providers/node.rs Outdated Show resolved Hide resolved
));
// Remove the package.json so when we run node /dist/**/file.js node does
// not look at the package.json and infer things it should not, Such as wether its a es module or not.
build_phase.add_cmd("rm /app/package.json".to_owned());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little confused by this. It is not common to remove the package.json file. Why is it necessary in this case? I've run many NX apps without the need for removing this file. I also know a few apps that rely on this app existing in production.

This also won't work if the start command is overriden to be something like npm run web:start

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I chose not to use the serve target is that it appears to be for development purposes as it includes a websocket for use with a debugger and hot-reload on file change. If this is ok we can totally use nx run <app-name>:serve:production see the output below. The other three targets that are generated by the default express generator (@nrwl/express:aplication) are lint, build and test.

npx nx run express-app:serve:production

> nx run express-app:serve:production

chunk (runtime: main) main.js (main) 564 bytes [entry] [rendered]
webpack compiled successfully (02f31e3162b7080a)
Debugger listening on ws://localhost:9229/666612ae-1046-4d7f-aefd-f39ef9b3fc16
Debugger listening on ws://localhost:9229/666612ae-1046-4d7f-aefd-f39ef9b3fc16
For help, see: https://nodejs.org/en/docs/inspector
nx express app works
chunk (runtime: main) main.js (main) 572 bytes [entry] [rendered]
webpack compiled successfully (4275d6c19665a755)
Command failed: taskkill /pid 28756 /T /F
ERROR: The process "28756" not found.

Debugger listening on ws://localhost:9229/f9432e74-f926-4596-8ad1-a6a5175ef466
Debugger listening on ws://localhost:9229/f9432e74-f926-4596-8ad1-a6a5175ef466
For help, see: https://nodejs.org/en/docs/inspector
nx express app works, reload

( same story with @nrwl/node:webpack )

The reason for deleting the package.json was to solve an issue where running node <path-to-app>/main.js would have some interaction with the package.json. This iirc. Maybe it would be better ( if we don't use the serve target ) to cd into the output folder and run node main.js?

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/app/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it doesn't make sense to use the serve target. But lots of apps have another separate start task/script that is meant for production. If that target is found we can run that command. As for the ES module error, I think that can be solved with a field in the package.json file. If the app was deployed and run in other production environments it would not be common to delete the package.json file.

Unfortunately deleting this file is not really feasible with Nixpacks since some users may override the start command with the NIXPACKS_START_CMD variable to something like npm run start. This should work even for NX apps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah! i understand now, we check if they have a start target and if they don't we fall back. I'm thinking we do the checks in this order: <appName>:start:production -> <appName>:start -> node <mainFile>.js -> node index.js.

Regarding the package.json thing, I think your right, I tried that but it also felt a bit weird. Instead, we could cd into the dist dir ( either cd dist or cd <outputdir> ) and run the fallback start command. Whats is your thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, I agree that start command priority order makes sense.

As for editing package.json, I think it is fairly common to do when running generated code in a production environment. I must admit, I haven't written raw JavaScript in a long time (mainly just TS), but changing the module type in package.json should be okay. The main thing is that we should not be manually deleting these files for the user just to run their code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair, ill get on that tomorrow (hopefully) when I have time, serde should make this easy. Thanks for the insights as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just removed the rm package.json step and ran the tests ran fine, so I think I've been lying about the module-type issue.
Ill make the start command change and then I can asses if its really an issue

let project_json = NodeProvider::get_nx_project_json_for_app(app, env)?;

let executor = project_json.targets.build.executor;
if executor == "@nrwl/next:build" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments for the NX start command

  • The port shouldn't be set when running a Next app. It should just use the default
  • Instead of cd'ing into the directory, I think it is cleaner to start the app with Nx. E.g. nx run frontend:start
  • The default start command for all NX apps should be running the start command in the app (if it exists). For example for something like Yarn/NX monorepos, each sub-app will have it's own start command that we should use (if it exists). Then we can fallback to running dist/main.js

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the other start commands.

Regarding the port. The default port is something like 3200, I would expect a website to be hosted on port 80 and without this change, it would not be. removing this the user would have to overnight the start command manually to use port 80.

Would the default port be acceptable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Next apps the port is overridable with the PORT environment variable and that is common in many other frameworks. Also, when starting the container, you can map port 3200 inside of the container to any other port on the outside, so the default port in the container does not matter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me. I'll get on this change when I can.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be done now. Just the run commands to change as of present.

src/providers/node.rs Outdated Show resolved Hide resolved
src/providers/node.rs Outdated Show resolved Hide resolved
src/providers/node.rs Outdated Show resolved Hide resolved
src/providers/node.rs Outdated Show resolved Hide resolved
@JakeCooper
Copy link
Contributor

JakeCooper commented Aug 11, 2022

As a result of this provider, can we revert #382?

The reason we added it was for the nwl stuff

@FinnDore
Copy link
Contributor Author

Tbh I have never needed this env var on Railway. Having said that @ChristianIvicevic said not having it causes a sigTerm? I have noticed a sig term on vercel before when using nx but it's very flakey and may be caused by me not setting this env var.

@ChristianIvicevic
Copy link
Contributor

CI=true makes a lot of sense with Node projects such as disabling watch modes for tools (such as tests) or in the case of Nx disabling the background daemon that caused SIGTERMs.

@coffee-cup
Copy link
Contributor

As a result of this provider, can we revert #382?

The reason we added it was for the nwl stuff

This PR does not change the fact that CI=true is needed. It just adds better first class support for NX apps.

docs/pages/docs/providers/node.md Outdated Show resolved Hide resolved
let pkg_manager = NodeProvider::get_package_manager(app);
if NodeProvider::is_nx_monorepo(app) {
let app_name = NodeProvider::get_nx_app_name(app, _env)?.unwrap();
build_phase.add_cmd(format!("{} run {}:build:production", pkg_manager, app_name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be npm nx run APP:build:production since this script may not exist. I am seeing this error when building the default NX app.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you are correct. I'm refactoring the build command so it works no matter what package manager the user is using. Just didn't get enough time last night 😆

@FinnDore
Copy link
Contributor Author

Think all the ducks are in order now. This should be ready for a re-review whenever you are free next week or so 😀.

Copy link
Contributor

@coffee-cup coffee-cup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's looking good! Can you please fix the linting errors and then I will merge :D

@FinnDore
Copy link
Contributor Author

Done!

@FinnDore
Copy link
Contributor Author

Odd, somehow I missed some. I'll get on that asap tomorrow.

@coffee-cup
Copy link
Contributor

I just went ahead and fixed the remaining lint errors (Literally just had to run cargo clippy --fix) 😄

@coffee-cup coffee-cup merged commit 91b7363 into railwayapp:main Aug 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants