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

Add support for out-of-tree platform plugins #20825

Closed
wants to merge 4 commits into from

Conversation

empyrical
Copy link
Contributor

@empyrical empyrical commented Aug 24, 2018

This pull request adds the ability for a platform developer to provide a "haste" key under the "rnpm" key in their package.json which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the "jest": { "haste": {} } key used by jest.

For example, React Native Dom would have an entry like:

{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with @matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21

Test Plan:

I've modified a local copy of RNDom to have the above example in its package.json in an unmodified default React Native app project, and a JS bundle was build successfully.

Release Notes:

[CLI] [ENHANCEMENT] [local-cli/core/findPlugins.js] - Modified the findPlugins function to handle this new haste field
[CLI] [ENHANCEMENT] [local-cli/core/index.js] - Removed the hardcoded platforms and switched to use output from findPlugins

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 24, 2018
@@ -71,11 +98,12 @@ const findPluginInFolder = folder => {
if (pkgJson) {
commands = commands.concat(findPluginsInReactNativePackage(pkgJson));

Choose a reason for hiding this comment

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

prettier/prettier: Delete ··

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 am not entirely sure what this means

[/^(.*)\.(android|ios|native|web|windows|dom)$/, '$1'],
// strip platform suffix
[/^(.*)\.(android|ios|native)$/, '$1'],
// strip plugin platform suffixes

Choose a reason for hiding this comment

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

prettier/prettier: Insert ,

@empyrical
Copy link
Contributor Author

@rozele: I had to change around the lines you modified in #20705 because it seems like config.resolver.platforms was always present with metro defaults, meaning defaultConfig.getPlatforms() was never reached even without a metro.config.js. I still have the undefined check there because I am not sure if there are still cases where it will be empty. I am not sure if this will break your use case or not.

haste.providesModuleNodeModules.concat(pkgHaste.providesModuleNodeModules);
}
};

const findPluginInFolder = folder => {

Choose a reason for hiding this comment

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

prettier/prettier: Replace flatten(plugins.map(p·=>·p.haste.providesModuleNodeModules)) with ⏎········flatten(plugins.map(p·=>·p.haste.providesModuleNodeModules)),⏎······

@matthargett
Copy link
Contributor

@rozele @vincentriemer @CaptainNic I’m closing #20662 in favor of this approach.

}]}
style={[
styles.base,
styles.leftMargin,

Choose a reason for hiding this comment

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

react-native/no-inline-styles: Inline style: { borderWidth: 5,
borderTopLeftRadius: 10,
borderTopRightRadius: 20,
borderBottomRightRadius: 30,
borderBottomLeftRadius: 40,
borderColor: 'red' }


const NativeEventEmitter = require('NativeEventEmitter');

module.exports = new NativeEventEmitter('StatusBarManager');

Choose a reason for hiding this comment

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

Cannot call NativeEventEmitter with 'StatusBarManager' bound to nativeModule because string [1] is incompatible with NativeModule [2].

}]}
style={[
styles.base,
styles.leftMargin,

Choose a reason for hiding this comment

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

react-native/no-inline-styles: Inline style: { borderWidth: 5,
borderTopLeftRadius: 10,
borderTopRightRadius: 20,
borderBottomRightRadius: 30,
borderBottomLeftRadius: 40,
borderColor: 'red' }

@empyrical
Copy link
Contributor Author

I've added a dummy platform in RNTester/js/OutOfTreeTestPlatform with the aim of testing RNCLI's support for bundling out of tree platforms.

Currently, there is just a test in ContainerShip/scripts/run-ci-e2e-tests.sh - I wanted to also have a platform suffix test in jest/__tests__/hasteImpl-test.js, but I need to be able to have OutOfTreeTestPlatform/react-native-dummy as a devDependency somehow for that to work. I do not predict this dummy module needing to be changed much - perhaps it could just be installed from npm, and added as another package that gets published in the publish script?

I currently have this module on NPM for testing purposes that I could transfer ownership over if FB devs are interested:

https://www.npmjs.com/package/react-native-dummy

@empyrical
Copy link
Contributor Author

I've added an entry to package.json that installs this local module using this syntax:

    "react-native-dummy": "file:./RNTester/js/OutOfTreeTestPlatform",

Which was sufficient for letting me get a hasteImpl test working.

Copy link
Contributor

@matthargett matthargett left a comment

Choose a reason for hiding this comment

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

Mostly questions and minor styling. Fantastic work on adding unit and e2e tests at the same time! 🥇


class DummyProgressViewIOS extends React.Component {
render() {
return (
Copy link
Contributor

Choose a reason for hiding this comment

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

why not just have the render throw("Not implemented") or something similar? or just export require('UnimplementedView'); like the other files?

class DummySegmentedControlIOS extends React.Component {
render() {
return (
<View style={[styles.dummy, this.props.style]}>
Copy link
Contributor

Choose a reason for hiding this comment

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

same question here -- why not just throw?


'use strict';

module.exports = {};
Copy link
Contributor

Choose a reason for hiding this comment

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

why empty here and not require('UnimplementedView'); as elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

StatusBarIOS isn't a React component

https://github.com/facebook/react-native/blob/master/Libraries/Components/StatusBar/StatusBarIOS.ios.js

None if this code will be ran at all at any point - it is purely for the bundler's sake, so the actual code isn't that important. A lot of the shims, like DummySegmentedControlIOS are just copied over from Android shims in the RN codebase. Sorry for not making this clearer! I'll edit the main post

'use strict';

// Completely empty shim for the sake of bundling.
const Settings = {};
Copy link
Contributor

Choose a reason for hiding this comment

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

if require('UnimplementedView'); can't work here, let's inline the assignment as elsewhere.

@empyrical
Copy link
Contributor Author

I've run unit tests on my fork on a branch that's been rebased against #20854, and it turns out that jest-haste-map doesn't like two instances of this module being in its search paths at the same time, and it still seems to see it despite me adding it to all search path blacklists.

jest-haste-map: @providesModule naming collision:
  Duplicate module name: react-native-dummy
  Paths: /home/circleci/react-native/node_modules/react-native-dummy/package.json collides with /home/circleci/react-native/RNTester/js/OutOfTreeTestPlatform/package.json

This error is caused by a @providesModule declaration with the same name across two different files.

I honestly can't think of a way to get around this, so I will be trying this again as a separate pull request. If anyone wants to peek around at the code, it still exists at this branch:

https://github.com/empyrical/react-native/tree/haste-plugins-plus-test

@jhampton
Copy link
Contributor

@empyrical I think have run across this before. I was trying to do module substitution to emulate tree shaking for an out-of-tree platform. My approach used the getTransformModulePath option in the rn-cli.config.js (I haven't found a ton of documentation, so the signature may have changed). Basically this option is a path to a file that returns a function that lets you hook into the module resolution and decide to replace the implementation wholesale. I can provide a sample and basic walkthrough of what I was doing if you can DM me.

I'm by no means a Metro expert, but I've done a bit of hacking lately with it.

Cheers, and I'll take a look at your fork as well to see what I see.

-Jeff

@kelset
Copy link
Contributor

kelset commented Aug 28, 2018

@rozele @vincentriemer I'd love to hear your feedback on this, seems solid - and thanks for adding the tests too!

@vincentriemer
Copy link
Contributor

I’ll try and take a look tonight 👌

@vincentriemer
Copy link
Contributor

Short of actually pulling the branch and testing it against rndom itself, LGTM 👍

Copy link
Contributor

@hramos hramos left a comment

Choose a reason for hiding this comment

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

Test failures seem unrelated to this PR.

},

getProvidesModuleNodeModules(): Array<string> {
return ['react-native', 'react-native-windows', 'react-native-dom'];
return ['react-native', ...plugins.haste.providesModuleNodeModules];
},

Choose a reason for hiding this comment

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

prettier/prettier: Replace ·config.resolver.providesModuleNodeModules·|| with ⏎····config.resolver.providesModuleNodeModules·||⏎···

},

getProvidesModuleNodeModules(): Array<string> {
return ['react-native', 'react-native-windows', 'react-native-dom'];
return ['react-native', ...plugins.haste.providesModuleNodeModules];
},

Choose a reason for hiding this comment

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

prettier/prettier: Replace ·config.resolver.providesModuleNodeModules·|| with ⏎····config.resolver.providesModuleNodeModules·||⏎···

},

getProvidesModuleNodeModules(): Array<string> {
return ['react-native', 'react-native-windows', 'react-native-dom'];
return ['react-native', ...plugins.haste.providesModuleNodeModules];

Choose a reason for hiding this comment

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

prettier/prettier: Insert ⏎···

@empyrical
Copy link
Contributor Author

Rebased against master, and tests still look good. Looks like I may need to run prettify again (maybe the style guide settings were changed in one of the commits?)

@facebook-github-bot facebook-github-bot added the Import Started This pull request has been imported. This does not imply the PR has been approved. label Aug 30, 2018
Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

hramos is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

hramos is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@react-native-bot
Copy link
Collaborator

@empyrical merged commit 03476a2 into facebook:master.


Once this commit is added to a release, you will see the corresponding version tag below the description at 03476a2. If the commit has a single master tag, it is not yet part of a release.

@facebook facebook locked as resolved and limited conversation to collaborators Aug 30, 2018
@react-native-bot react-native-bot added the Merged This PR has been merged. label Aug 30, 2018
kelset pushed a commit that referenced this pull request Aug 31, 2018
Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: #20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
gengjiawen pushed a commit to gengjiawen/react-native that referenced this pull request Sep 14, 2018
Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds facebook#20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
aleclarson pushed a commit to aleclarson/react-native that referenced this pull request Sep 16, 2018
Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds facebook#20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
grabbou pushed a commit to react-native-community/cli that referenced this pull request Sep 26, 2018
Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook/react-native#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
aleclarson added a commit to aleclarson/react-native-macos that referenced this pull request Dec 25, 2018
Taken from: facebook/react-native@03476a2

Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook/react-native#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
aleclarson added a commit to aleclarson/react-native-macos that referenced this pull request Jan 29, 2019
Taken from: facebook/react-native@03476a2

Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook/react-native#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
aleclarson added a commit to aleclarson/react-native-macos that referenced this pull request Jan 29, 2019
Taken from: facebook/react-native@03476a2

Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook/react-native#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
@hramos hramos removed Import Started This pull request has been imported. This does not imply the PR has been approved. labels Feb 6, 2019
aleclarson added a commit to aleclarson/react-native-macos that referenced this pull request Mar 3, 2019
Taken from: facebook/react-native@03476a2

Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds #20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook/react-native#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
t-nanava pushed a commit to microsoft/react-native-macos that referenced this pull request Jun 17, 2019
Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds facebook#20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
t-nanava pushed a commit to microsoft/react-native-macos that referenced this pull request Jun 17, 2019
Summary:
This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest.

For example, React Native Dom would have an entry like:

```json
{
  "rnpm": {
    "haste": {
      "providesModuleNodeModules": [
        "react-native-dom"
      ],
      "platforms": [
        "dom"
      ]
    }
  }
}
```

Support for more keys (path blacklists perhaps?) could be added in the future.

This succeeds facebook#20662, as per a discussion I had with matthargett.

I've got an open discussion over here as well: react-native-community/discussions-and-proposals#21
Pull Request resolved: facebook#20825

Differential Revision: D9596429

Pulled By: hramos

fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2
@facebook-github-bot facebook-github-bot added the Contributor A React Native contributor. label Apr 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. Merged This PR has been merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants