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

Move all metro logic and commands into a metro package #1447

Merged
merged 19 commits into from
Oct 4, 2021

Conversation

afoxman
Copy link
Contributor

@afoxman afoxman commented Jul 15, 2021

Summary:

I am working on a project where I need to do Metro bundling using the Metro APIs. The CLI has really useful Metro config and Metro bundling logic that I want to use, but it's tied up and not accessible.

This PR move the Metro configuration and bundling logic into separate packages, making them available for my project and to other external users.

Test Plan:

Code is moving, with minimal changes, including tests. Verify that the build passes and that all tests pass.

Manually verify that bundling works on a sample app. Diffed bundles using existing release of CLI vs this PR. Bundle size and md5 hashes were identical.

@grabbou
Copy link
Member

grabbou commented Jul 15, 2021

I love this! It's something I wanted to do for a really really long time!

Can you do one more thing, rename metro-config to just metro and move start as well as bundle commands into that package? This will be a good first step to eventually provide an abstraction for other bundlers to plug into CLI instead of Metro.

The idea is that one should be able too completely replace Metro with e.g. Webpack or other bundler by removing @react-native-community/bundler-metro package and using a different one instead.

CC: @tido64

@afoxman afoxman changed the title Move bundle and metro config logic into separate packages Move all metro logic and commands into a metro package Jul 16, 2021
@afoxman
Copy link
Contributor Author

afoxman commented Jul 16, 2021

I love this! It's something I wanted to do for a really really long time!

Can you do one more thing, rename metro-config to just metro and move start as well as bundle commands into that package? This will be a good first step to eventually provide an abstraction for other bundlers to plug into CLI instead of Metro.

The idea is that one should be able too completely replace Metro with e.g. Webpack or other bundler by removing @react-native-community/bundler-metro package and using a different one instead.

CC: @tido64

Happy to help! This turned into a big PR, so you have a lot of reading to do :). The metro package now has all metro commands (start, bundle, and ramBundle) as well as the metro config/asset code.

I had to move a few "tools" from cli to cli-tools, so I could use them in metro. That made things a bit complicated and added to the PR.

@grabbou
Copy link
Member

grabbou commented Jul 16, 2021

No worries, that's something I've been waiting for quite some time to see, so I am more than happy to review it!

@grabbou
Copy link
Member

grabbou commented Jul 16, 2021

In the future release of React Native, I would like to discuss an opportunity of moving Metro dependency to a user project, so that they can define bundler and complementary CLI plugin for it.

@afoxman
Copy link
Contributor Author

afoxman commented Jul 16, 2021

In the future release of React Native, I would like to discuss an opportunity of moving Metro dependency to a user project, so that they can define bundler and complementary CLI plugin for it.

That sounds good. We should sync up on what you have in mind, and how I can help. Sent you a friend request on Discord to work out the details in DMs.

@afoxman
Copy link
Contributor Author

afoxman commented Sep 3, 2021

@thymikee @grabbou Hi folks - checking in to see when you might merge this, or if you'd like any further changes?

@thymikee
Copy link
Member

I'm sure @grabbou will prioritize this the next time he works on this lib

@grabbou
Copy link
Member

grabbou commented Sep 13, 2021

Yes, I am working on this this week. Will be reviewed on Wednesday.

@grabbou
Copy link
Member

grabbou commented Sep 16, 2021

Update: I am still in progress with this one, expected update tomorrow

Copy link
Member

@grabbou grabbou left a comment

Choose a reason for hiding this comment

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

Conceptually, everything looks fine. I have left some comments, but I believe this is going to be the final round.

TL;DR:

  • Let's not export "all" (via export * from 'foo.ts') and avoid creating index.ts in folders
  • Prefer export default instead of single named exports per file (sticks consistent with the rest of the codebase, happy to revisit later in a separate PR)
  • Export explicitly the public interface via src/index.ts (instead of *)
  • Do not change current exported/private functions beyond the loadMetroConfig.ts that is subject to this PR (unless there's a need for an additional function - then, it's welcome)

I am happy to hop on a Discord/Hangouts call to discuss this in a bit more details if necessary. Thank you for working on that!

packages/metro/src/bundle/buildBundle.ts Outdated Show resolved Hide resolved
packages/metro/src/config/index.ts Outdated Show resolved Hide resolved
packages/metro/src/index.ts Outdated Show resolved Hide resolved
packages/metro/src/start/index.ts Outdated Show resolved Hide resolved
packages/cli/package.json Outdated Show resolved Hide resolved
@afoxman
Copy link
Contributor Author

afoxman commented Sep 22, 2021

Conceptually, everything looks fine. I have left some comments, but I believe this is going to be the final round.

TL;DR:

  • Let's not export "all" (via export * from 'foo.ts') and avoid creating index.ts in folders
  • Prefer export default instead of single named exports per file (sticks consistent with the rest of the codebase, happy to revisit later in a separate PR)
  • Export explicitly the public interface via src/index.ts (instead of *)
  • Do not change current exported/private functions beyond the loadMetroConfig.ts that is subject to this PR (unless there's a need for an additional function - then, it's welcome)

I am happy to hop on a Discord/Hangouts call to discuss this in a bit more details if necessary. Thank you for working on that!

I think I've addressed all these points in my latest push. Use default exports. And all public API exports are now explicit, and only what @react-native-community/cli needs to consume (the command objects) and what I need to consume in @rnx-kit/* packages.

@afoxman
Copy link
Contributor Author

afoxman commented Sep 22, 2021

Looks like an e2e test failed.

I can't log into circleci to find out details. It wants too much access to my Microsoft github account, so I can't sign in.

When I run 'yarn test' and 'yarn test:ci:e2e' (the command circleci runs), I get success. If I broke something, I'll need help diagnosing.

In the meantime, I tried merging the upstream master, to kick off another build to see if it fails with the latest commits.

startCommand as start,
bundleCommand as bundle,
ramBundleCommand as ramBundle,
} from '@react-native-community/cli-plugin-metro';
Copy link
Member

Choose a reason for hiding this comment

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

In the future, we can remove this when this plugin becomes direct React Native dependency.

Here's a snippet:
https://github.com/facebook/react-native/blob/main/react-native.config.js#L16

I believe it should simply say metro.commands, but this is to be decided on the planning meeting.

@grabbou
Copy link
Member

grabbou commented Sep 27, 2021

I updated your PR with some further naming changes. The primary change was to group commands into commands folder (stays uniform with android and iOS plugins) and export them as an array. They're not supposed to be consumed as a public API, but used internally, and array is what the CLI infrastructure prefers.

Please let me know if you're happy with how it looks and whether the public API satisfies your use case.

export {
bundleCommand,
ramBundleCommand,
buildBundleWithConfig,
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 need buildBundleWithConfig to be publicly exported.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added (along with CommandLineArgs type) in my latest push

@afoxman
Copy link
Contributor Author

afoxman commented Sep 27, 2021

I updated your PR with some further naming changes. The primary change was to group commands into commands folder (stays uniform with android and iOS plugins) and export them as an array. They're not supposed to be consumed as a public API, but used internally, and array is what the CLI infrastructure prefers.

Please let me know if you're happy with how it looks and whether the public API satisfies your use case.

Everything looks ok to me. One function export and a type were removed during the shuffle, so I added them back in. I need to be able to call buildBundleWithConfig(...) and so I need it as well as its input type CommandLineArgs.

@grabbou
Copy link
Member

grabbou commented Oct 4, 2021

LGTM.

@grabbou
Copy link
Member

grabbou commented Oct 4, 2021

The CI failure looks unrelated. I will move forward and merge this PR.

@grabbou grabbou merged commit 0993f62 into react-native-community:master Oct 4, 2021
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.

3 participants