diff --git a/packages/babel-plugin-react-native-web/README.md b/packages/babel-plugin-react-native-web/README.md index 0147fe29..e24e3a12 100644 --- a/packages/babel-plugin-react-native-web/README.md +++ b/packages/babel-plugin-react-native-web/README.md @@ -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 diff --git a/packages/babel-plugin-react-native-web/src/__tests__/__snapshots__/index-test.js.snap b/packages/babel-plugin-react-native-web/src/__tests__/__snapshots__/index-test.js.snap index 3b7af176..7895b55d 100644 --- a/packages/babel-plugin-react-native-web/src/__tests__/__snapshots__/index-test.js.snap +++ b/packages/babel-plugin-react-native-web/src/__tests__/__snapshots__/index-test.js.snap @@ -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'; @@ -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'); ↓ ↓ ↓ ↓ ↓ ↓ @@ -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'); diff --git a/packages/babel-plugin-react-native-web/src/__tests__/index-test.js b/packages/babel-plugin-react-native-web/src/__tests__/index-test.js index cf560502..9bd9aa05 100644 --- a/packages/babel-plugin-react-native-web/src/__tests__/index-test.js +++ b/packages/babel-plugin-react-native-web/src/__tests__/index-test.js @@ -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'; @@ -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'); diff --git a/packages/babel-plugin-react-native-web/src/index.js b/packages/babel-plugin-react-native-web/src/index.js index bdd2606b..c1f2a71a 100644 --- a/packages/babel-plugin-react-native-web/src/index.js +++ b/packages/babel-plugin-react-native-web/src/index.js @@ -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; @@ -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( @@ -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); @@ -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( @@ -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); @@ -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( @@ -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') ) diff --git a/packages/website/guides/getting-started.md b/packages/website/guides/getting-started.md index 24f3d4b3..85cc8f0b 100644 --- a/packages/website/guides/getting-started.md +++ b/packages/website/guides/getting-started.md @@ -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