Skip to content

Commit

Permalink
Use new configuration in react-native public cli
Browse files Browse the repository at this point in the history
Summary: Change the public react-native CLI to use the new configuration of Metro.

Reviewed By: rafeca

Differential Revision: D8801217

fbshipit-source-id: 112e4812b430ebee1ed41489f803b90c182ccdb4
  • Loading branch information
Ives van Hoorne authored and facebook-github-bot committed Jul 25, 2018
1 parent f0daaf3 commit a32620d
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 140 deletions.
16 changes: 5 additions & 11 deletions local-cli/bundle/buildBundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@ const log = require('../util/log').out('bundle');
/* $FlowFixMe(site=react_native_oss) */
const Server = require('metro/src/Server');

const {convert} = require('metro-config');

/* $FlowFixMe(site=react_native_oss) */
const outputBundle = require('metro/src/shared/output/bundle');
const {convert} = require('metro-config');
const path = require('path');
const saveAssets = require('./saveAssets');

const {ASSET_REGISTRY_PATH} = require('../core/Constants');

import type {RequestOptions, OutputOptions} from './types.flow';
import type {ConfigT} from 'metro-config/src/configTypes.flow';

Expand All @@ -48,6 +45,10 @@ async function buildBundle(
sourceMapUrl = path.basename(sourceMapUrl);
}

config.transformModulePath = args.transformer
? path.resolve(args.transformer)
: config.transformModulePath;

const requestOpts: RequestOptions = {
entryFile: args.entryFile,
sourceMapUrl,
Expand All @@ -56,13 +57,6 @@ async function buildBundle(
platform: args.platform,
};

const transformModulePath = args.transformer
? path.resolve(args.transformer)
: config.transformModulePath;

config.transformModulePath = transformModulePath;
config.transformer.assetRegistryPath = ASSET_REGISTRY_PATH;

const {serverOptions} = convert.convertNewToOld(config);

const server = new Server(serverOptions);
Expand Down
5 changes: 3 additions & 2 deletions local-cli/cliEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

'use strict';

const config = require('./core');
const {configPromise} = require('./core');

const assertRequiredOptions = require('./util/assertRequiredOptions');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
Expand Down Expand Up @@ -137,7 +137,8 @@ const addCommand = (command: CommandT, cfg: RNConfig) => {
cmd.option('--config [string]', 'Path to the CLI configuration file');
};

function run() {
async function run() {
const config = await configPromise;
const setupEnvScript = /^win/.test(process.platform)
? 'setup_env.bat'
: 'setup_env.sh';
Expand Down
55 changes: 30 additions & 25 deletions local-cli/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const findPlugins = require('./findPlugins');
const findAssets = require('./findAssets');
const ios = require('./ios');
const wrapCommands = require('./wrapCommands');
const {ASSET_REGISTRY_PATH} = require('./Constants');

/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
Expand All @@ -28,18 +29,14 @@ const minimist = require('minimist');
const path = require('path');

import type {CommandT} from '../commands';
import type {ConfigT} from 'metro';
import type {ConfigT} from 'metro-config/src/configTypes.flow';

export type RNConfig = {
...ConfigT,
/**
* Returns an object with all platform configurations.
*/
getPlatformConfig(): Object,
/**
* Returns an array of project commands used by the CLI to load
*/
getProjectCommands(): Array<CommandT>,
/**
* Returns project config from the current working directory
*/
Expand Down Expand Up @@ -69,7 +66,7 @@ const pluginPlatforms = plugins.platforms.reduce((acc, pathToPlatforms) => {
);
}, {});

const defaultRNConfig = {
const defaultConfig = {
hasteImplModulePath: require.resolve('../../jest/hasteImpl'),

getPlatforms(): Array<string> {
Expand All @@ -79,20 +76,9 @@ const defaultRNConfig = {
getProvidesModuleNodeModules(): Array<string> {
return ['react-native', 'react-native-windows'];
},
};

getProjectCommands(): Array<CommandT> {
const commands = plugins.commands.map(pathToCommands => {
const name = pathToCommands.split(path.sep)[0];

return attachPackage(
require(path.join(appRoot, 'node_modules', pathToCommands)),
require(path.join(appRoot, 'node_modules', name, 'package.json')),
);
});

return flatten(commands);
},

const defaultRNConfig = {
getPlatformConfig(): Object {
return {
ios,
Expand Down Expand Up @@ -141,14 +127,33 @@ const defaultRNConfig = {
/**
* Loads the CLI configuration
*/
function getCliConfig(): RNConfig {
async function getCliConfig(): Promise<RNConfig> {
const cliArgs = minimist(process.argv.slice(2));
const config =
cliArgs.config != null
? Config.load(path.resolve(__dirname, cliArgs.config))
: Config.findOptional(__dirname);
const config = await Config.load(path.resolve(__dirname, cliArgs.config));

This comment has been minimized.

Copy link
@janicduplessis

janicduplessis Jul 27, 2018

Contributor

This crashes when the config option is not passed to the CLI (this is the default for OSS).

I’m also having issues with my custom rn-cli.config.js, the file gets parsed but seems like none of the method gets called, did the format change? We will want to document this.

This comment has been minimized.

Copy link
@janicduplessis

janicduplessis Jul 27, 2018

Contributor

This comment has been minimized.

Copy link
@rafeca

rafeca Jul 29, 2018

Contributor

Thanks for the report! @CompuIves we should add a simple check here


config.transformer.assetRegistryPath = ASSET_REGISTRY_PATH;
config.resolver.hasteImplModulePath = defaultConfig.hasteImplModulePath;
config.resolver.platforms = defaultConfig.getPlatforms();
config.resolver.providesModuleNodeModules = defaultConfig.getProvidesModuleNodeModules();

return {...defaultRNConfig, ...config};
}

module.exports = getCliConfig();
/**
* Returns an array of project commands used by the CLI to load
*/
function getProjectCommands(): Array<CommandT> {
const commands = plugins.commands.map(pathToCommands => {
const name = pathToCommands.split(path.sep)[0];

return attachPackage(
require(path.join(appRoot, 'node_modules', pathToCommands)),
require(path.join(appRoot, 'node_modules', name, 'package.json')),
);
});

return flatten(commands);
}

module.exports.configPromise = getCliConfig();
module.exports.getProjectCommands = getProjectCommands;
13 changes: 5 additions & 8 deletions local-cli/dependencies/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ const denodeify = require('denodeify');
const fs = require('fs');
const path = require('path');

const {ASSET_REGISTRY_PATH} = require('../core/Constants');

async function dependencies(argv, configPromise, args, packagerInstance) {
const rootModuleAbsolutePath = args.entryFile;
const config = await configPromise;
Expand All @@ -31,12 +29,9 @@ async function dependencies(argv, configPromise, args, packagerInstance) {
config.transformModulePath = args.transformer
? path.resolve(args.transformer)
: config.transformModulePath;
config.transformer.transformModulePath = ASSET_REGISTRY_PATH;

const {serverOptions: packageOpts} = convert.convertNewToOld(config);

const relativePath = path.relative(
packageOpts.projectRoot,
config.projectRoot,
rootModuleAbsolutePath,
);

Expand All @@ -53,18 +48,20 @@ async function dependencies(argv, configPromise, args, packagerInstance) {
? fs.createWriteStream(args.output)
: process.stdout;

const {serverOptions} = convert.convertNewToOld(config);

return Promise.resolve(
(packagerInstance
? packagerInstance.getOrderedDependencyPaths(options)
: Metro.getOrderedDependencyPaths(packageOpts, options)
: Metro.getOrderedDependencyPaths(serverOptions, options)
).then(deps => {
deps.forEach(modulePath => {
// Temporary hack to disable listing dependencies not under this directory.
// Long term, we need either
// (a) JS code to not depend on anything outside this directory, or
// (b) Come up with a way to declare this dependency in Buck.
const isInsideProjectRoots =
packageOpts.watchFolders.filter(root => modulePath.startsWith(root))
config.watchFolders.filter(root => modulePath.startsWith(root))
.length > 0;

if (isInsideProjectRoots) {
Expand Down
28 changes: 8 additions & 20 deletions local-cli/server/runServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ const morgan = require('morgan');
const path = require('path');
const webSocketProxy = require('./util/webSocketProxy');
const MiddlewareManager = require('./middleware/MiddlewareManager');
const {convertOldToNew} = require('metro-config/src/convertConfig');

const {ASSET_REGISTRY_PATH} = require('../core/Constants');

import type {ConfigT} from 'metro';
import type {ConfigT} from 'metro-config/src/configTypes.flow';

export type Args = {|
+assetExts: $ReadOnlyArray<string>,
Expand Down Expand Up @@ -57,23 +54,14 @@ async function runServer(args: Args, config: ConfigT) {

args.watchFolders.forEach(middlewareManager.serveStatic);

config.maxWorkers = args.maxWorkers;
config.server.port = args.port;
config.reporter = reporter;
config.server.enhanceMiddleware = middleware =>
middlewareManager.getConnectInstance().use(middleware);

const serverInstance = await Metro.runServer({
config: convertOldToNew({
config: {
...config,
assetRegistryPath: ASSET_REGISTRY_PATH,
enhanceMiddleware: middleware =>
middlewareManager.getConnectInstance().use(middleware),
transformModulePath: args.transformer
? path.resolve(args.transformer)
: config.getTransformModulePath(),
},
maxWorkers: args.maxWorkers,
port: args.port,
reporter,
}),

hmrEnabled: true,
config,
host: args.host,
secure: args.https,
secureCert: args.cert,
Expand Down
19 changes: 9 additions & 10 deletions local-cli/server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
const runServer = require('./runServer');

import type {RNConfig} from '../core';
import type {ConfigT} from 'metro';
import type {ConfigT} from 'metro-config/src/configTypes.flow';
import type {Args as RunServerArgs} from './runServer';

/**
Expand Down Expand Up @@ -43,7 +43,7 @@ module.exports = {
command: '--projectRoot [string]',
description: 'Specify the main project root',
default: (config: ConfigT) => {
return config.getProjectRoot();
return config.projectRoot;
},
},
{
Expand All @@ -52,40 +52,39 @@ module.exports = {
'Specify any additional folders to be added to the watch list',
parse: (val: string) => val.split(','),
default: (config: ConfigT) => {
return config.getWatchFolders();
return config.watchFolders;
},
},
{
command: '--assetExts [list]',
description:
'Specify any additional asset extensions to be used by the packager',
parse: (val: string) => val.split(','),
default: (config: ConfigT) => config.getAssetExts(),
default: (config: ConfigT) => config.resolver.assetExts,
},
{
command: '--sourceExts [list]',
description:
'Specify any additional source extensions to be used by the packager',
parse: (val: string) => val.split(','),
default: (config: ConfigT) => config.getSourceExts(),
default: (config: ConfigT) => config.resolver.sourceExts,
},
{
command: '--platforms [list]',
description:
'Specify any additional platforms to be used by the packager',
parse: (val: string) => val.split(','),
default: (config: ConfigT) => config.getPlatforms(),
default: (config: ConfigT) => config.resolver.platforms,
},
{
command: '--providesModuleNodeModules [list]',
description:
'Specify any npm packages that import dependencies with providesModule',
parse: (val: string) => val.split(','),
default: (config: RNConfig) => {
if (typeof config.getProvidesModuleNodeModules === 'function') {
return config.getProvidesModuleNodeModules();
}
return null;
return config.resolver
? config.resolver.providesModuleNodeModules
: undefined;
},
},
{
Expand Down
Loading

0 comments on commit a32620d

Please sign in to comment.