Skip to content

Commit

Permalink
[fix] babel-plugin option to rewrite to commonjs paths
Browse files Browse the repository at this point in the history
Allow the babel plugin to be configured to rewrite paths to either ES
modules (default) or CommonJS.

Ref #961
  • Loading branch information
necolas committed Jun 3, 2018
1 parent ed43258 commit d74b2d0
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 14 deletions.
10 changes: 9 additions & 1 deletion packages/babel-plugin-react-native-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ yarn add --dev babel-plugin-react-native-web

```
{
"plugins": ["react-native-web"]
"plugins": [
["react-native-web", { commonjs: true }]
]
}
```

You should configure the plugin to match the module format used by your
bundler. Most modern bundlers will use a package's ES modules by default (i.e.,
if `package.json` has a `module` field). But if you need the plugin to rewrite
import paths to point to CommonJS modules, you must set the `commonjs` option
to `true`.

## Example

NOTE: `react-native-web` internal paths are _not stable_ and you must not rely
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ import * as ReactNativeModules from 'react-native-web/dist/index';
"
`;

exports[`Rewrite react-native to react-native-web import from "native-native": import from "native-native" 2`] = `
"
import ReactNative from 'react-native';
import { View } from 'react-native';
import { Invalid, View as MyView, ViewPropTypes } from 'react-native';
import * as ReactNativeModules from 'react-native';
↓ ↓ ↓ ↓ ↓ ↓
import ReactNative from 'react-native-web/dist/cjs/index';
import View from 'react-native-web/dist/cjs/exports/View';
import { Invalid } from 'react-native-web/dist/cjs/index';
import MyView from 'react-native-web/dist/cjs/exports/View';
import ViewPropTypes from 'react-native-web/dist/cjs/exports/ViewPropTypes';
import * as ReactNativeModules from 'react-native-web/dist/cjs/index';
"
`;

exports[`Rewrite react-native to react-native-web import from "react-native-web": import from "react-native-web" 1`] = `
"
import { createElement } from 'react-native-web';
Expand All @@ -70,7 +88,7 @@ exports[`Rewrite react-native to react-native-web require "react-native": requir
"
const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, TouchableOpacity } = require('react-native');
const { StyleSheet, TouchableOpacity } = require('react-native');
↓ ↓ ↓ ↓ ↓ ↓
Expand All @@ -84,6 +102,24 @@ const TouchableOpacity = require('react-native-web/dist/exports/TouchableOpacity
"
`;

exports[`Rewrite react-native to react-native-web require "react-native": require "react-native" 2`] = `
"
const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, TouchableOpacity } = require('react-native');
↓ ↓ ↓ ↓ ↓ ↓
const ReactNative = require('react-native-web/dist/cjs/index').default;
const View = require('react-native-web/dist/cjs/exports/View').default;
const StyleSheet = require('react-native-web/dist/cjs/exports/StyleSheet').default;
const TouchableOpacity = require('react-native-web/dist/cjs/exports/TouchableOpacity').default;
"
`;

exports[`Rewrite react-native to react-native-web require "react-native-web": require "react-native-web" 1`] = `
"
const ReactNative = require('react-native-web');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ import { Invalid, View as MyView, ViewPropTypes } from 'react-native';
import * as ReactNativeModules from 'react-native';`,
snapshot: true
},
{
title: 'import from "native-native"',
code: `import ReactNative from 'react-native';
import { View } from 'react-native';
import { Invalid, View as MyView, ViewPropTypes } from 'react-native';
import * as ReactNativeModules from 'react-native';`,
snapshot: true,
pluginOptions: { commonjs: true }
},
{
title: 'import from "react-native-web"',
code: `import { createElement } from 'react-native-web';
Expand All @@ -34,9 +43,17 @@ export { ColorPropType, StyleSheet, Text, createElement } from 'react-native-web
title: 'require "react-native"',
code: `const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, TouchableOpacity } = require('react-native');`,
const { StyleSheet, TouchableOpacity } = require('react-native');`,
snapshot: true
},
{
title: 'require "react-native"',
code: `const ReactNative = require('react-native');
const { View } = require('react-native');
const { StyleSheet, TouchableOpacity } = require('react-native');`,
snapshot: true,
pluginOptions: { commonjs: true }
},
{
title: 'require "react-native-web"',
code: `const ReactNative = require('react-native-web');
Expand Down
24 changes: 16 additions & 8 deletions packages/babel-plugin-react-native-web/src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
const moduleMap = require('./moduleMap');

const getDistLocation = importName =>
importName && moduleMap[importName] ? `react-native-web/dist/exports/${importName}` : undefined;
const isCommonJS = opts => opts.commonjs === true;

const getDistLocation = (importName, opts) => {
const format = isCommonJS(opts) ? 'cjs/' : '';
if (importName === 'index') {
return `react-native-web/dist/${format}index`;
} else if (importName && moduleMap[importName]) {
return `react-native-web/dist/${format}exports/${importName}`;
}
};

const isReactNativeRequire = (t, node) => {
const { declarations } = node;
Expand Down Expand Up @@ -35,7 +43,7 @@ module.exports = function({ types: t }) {
.map(specifier => {
if (t.isImportSpecifier(specifier)) {
const importName = specifier.imported.name;
const distLocation = getDistLocation(importName);
const distLocation = getDistLocation(importName, state.opts);

if (distLocation) {
return t.importDeclaration(
Expand All @@ -46,7 +54,7 @@ module.exports = function({ types: t }) {
}
return t.importDeclaration(
[specifier],
t.stringLiteral('react-native-web/dist/index')
t.stringLiteral(getDistLocation('index', state.opts))
);
})
.filter(Boolean);
Expand All @@ -62,7 +70,7 @@ module.exports = function({ types: t }) {
if (t.isExportSpecifier(specifier)) {
const exportName = specifier.exported.name;
const localName = specifier.local.name;
const distLocation = getDistLocation(localName);
const distLocation = getDistLocation(localName, state.opts);

if (distLocation) {
return t.exportNamedDeclaration(
Expand All @@ -75,7 +83,7 @@ module.exports = function({ types: t }) {
return t.exportNamedDeclaration(
null,
[specifier],
t.stringLiteral('react-native-web/dist/index')
t.stringLiteral(getDistLocation('index', state.opts))
);
})
.filter(Boolean);
Expand All @@ -89,7 +97,7 @@ module.exports = function({ types: t }) {
if (t.isObjectPattern(id)) {
const imports = id.properties
.map(identifier => {
const distLocation = getDistLocation(identifier.key.name);
const distLocation = getDistLocation(identifier.key.name, state.opts);
if (distLocation) {
return t.variableDeclaration(path.node.kind, [
t.variableDeclarator(
Expand All @@ -112,7 +120,7 @@ module.exports = function({ types: t }) {
t.identifier(name),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral('react-native-web/dist/index')
t.stringLiteral(getDistLocation('index', state.opts))
]),
t.identifier('default')
)
Expand Down
7 changes: 4 additions & 3 deletions packages/website/guides/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,15 @@ Install webpack-related dependencies, for example:
yarn add --dev babel-loader url-loader webpack webpack-cli webpack-dev-server
```

React Native's Babel preset rewrites ES modules to CommonJS modules, preventing bundlers from automatically performing "tree-shaking" to remove
unused modules from your web app build. To help with this, you can install the following Babel plugin:
React Native's Babel preset rewrites ES modules to CommonJS modules, preventing
bundlers from automatically performing "tree-shaking" to remove unused modules
from your web app build. To help with this, you can install the following Babel
plugin:

```
yarn install --dev babel-plugin-react-native-web
```


Create a `web/webpack.config.js` file:

```js
Expand Down

0 comments on commit d74b2d0

Please sign in to comment.