Use new configuration in react-native public cli
Summary: Change the public react-native CLI to use the new configuration of Metro. Reviewed By: rafeca Differential Revision: D8801217 fbshipit-source-id: 112e4812b430ebee1ed41489f803b90c182ccdb4
This commit is contained in:
parent
f0daaf3568
commit
a32620dc3b
|
@ -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';
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
@ -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';
|
||||
|
|
|
@ -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
|
||||
|
@ -28,7 +29,7 @@ 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,
|
||||
|
@ -36,10 +37,6 @@ export type RNConfig = {
|
|||
* 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
|
||||
*/
|
||||
|
@ -69,7 +66,7 @@ const pluginPlatforms = plugins.platforms.reduce((acc, pathToPlatforms) => {
|
|||
);
|
||||
}, {});
|
||||
|
||||
const defaultRNConfig = {
|
||||
const defaultConfig = {
|
||||
hasteImplModulePath: require.resolve('../../jest/hasteImpl'),
|
||||
|
||||
getPlatforms(): Array<string> {
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -53,10 +48,12 @@ 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.
|
||||
|
@ -64,7 +61,7 @@ async function dependencies(argv, configPromise, args, packagerInstance) {
|
|||
// (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) {
|
||||
|
|
|
@ -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>,
|
||||
|
@ -57,23 +54,14 @@ async function runServer(args: Args, config: ConfigT) {
|
|||
|
||||
args.watchFolders.forEach(middlewareManager.serveStatic);
|
||||
|
||||
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,
|
||||
}),
|
||||
config.maxWorkers = args.maxWorkers;
|
||||
config.server.port = args.port;
|
||||
config.reporter = reporter;
|
||||
config.server.enhanceMiddleware = middleware =>
|
||||
middlewareManager.getConnectInstance().use(middleware);
|
||||
|
||||
hmrEnabled: true,
|
||||
const serverInstance = await Metro.runServer({
|
||||
config,
|
||||
host: args.host,
|
||||
secure: args.https,
|
||||
secureCert: args.cert,
|
||||
|
|
|
@ -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';
|
||||
|
||||
/**
|
||||
|
@ -43,7 +43,7 @@ module.exports = {
|
|||
command: '--projectRoot [string]',
|
||||
description: 'Specify the main project root',
|
||||
default: (config: ConfigT) => {
|
||||
return config.getProjectRoot();
|
||||
return config.projectRoot;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ 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;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -60,21 +60,21 @@ module.exports = {
|
|||
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]',
|
||||
|
@ -82,10 +82,9 @@ module.exports = {
|
|||
'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;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -10,21 +10,16 @@
|
|||
'use strict';
|
||||
|
||||
const findSymlinkedModules = require('./findSymlinkedModules');
|
||||
const fs = require('fs');
|
||||
const getPolyfills = require('../../rn-get-polyfills');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const path = require('path');
|
||||
|
||||
const {Config: MetroConfig, createBlacklist} = require('metro');
|
||||
|
||||
const RN_CLI_CONFIG = 'rn-cli.config.js';
|
||||
|
||||
import type {ConfigT as MetroConfigT} from 'metro';
|
||||
const {createBlacklist} = require('metro');
|
||||
const {loadConfig, mergeConfig} = require('metro-config');
|
||||
|
||||
/**
|
||||
* Configuration file of the CLI.
|
||||
*/
|
||||
export type ConfigT = MetroConfigT;
|
||||
import type {ConfigT} from 'metro-config/src/configTypes.flow';
|
||||
|
||||
function getProjectPath() {
|
||||
if (
|
||||
|
@ -70,68 +65,30 @@ const getBlacklistRE = () => {
|
|||
* hierarchy, an error will be thrown.
|
||||
*/
|
||||
const Config = {
|
||||
DEFAULT: ({
|
||||
...MetroConfig.DEFAULT,
|
||||
getBlacklistRE,
|
||||
DEFAULT: {
|
||||
resolver: {
|
||||
resolverMainFields: ['react-native', 'browser', 'main'],
|
||||
blacklistRE: getBlacklistRE(),
|
||||
},
|
||||
serializer: {
|
||||
getModulesRunBeforeMainModule: () => [
|
||||
require.resolve('../../Libraries/Core/InitializeCore'),
|
||||
],
|
||||
getProjectRoots,
|
||||
getPolyfills,
|
||||
getWatchFolders: () => [getProjectPath()],
|
||||
getResolverMainFields: () => ['react-native', 'browser', 'main'],
|
||||
getTransformModulePath: () =>
|
||||
require.resolve('metro/src/reactNativeTransformer'),
|
||||
}: ConfigT),
|
||||
|
||||
find(startDir: string): ConfigT {
|
||||
return this.findWithPath(startDir).config;
|
||||
},
|
||||
|
||||
findWithPath(startDir: string): {config: ConfigT, projectPath: string} {
|
||||
const configPath = findConfigPath(startDir);
|
||||
invariant(
|
||||
configPath,
|
||||
`Can't find "${RN_CLI_CONFIG}" file in any parent folder of "${startDir}"`,
|
||||
);
|
||||
const projectPath = path.dirname(configPath);
|
||||
return {config: this.load(configPath, startDir), projectPath};
|
||||
},
|
||||
|
||||
findOptional(startDir: string): ConfigT {
|
||||
const configPath = findConfigPath(startDir);
|
||||
return configPath ? this.load(configPath, startDir) : {...Config.DEFAULT};
|
||||
watchFolders: [getProjectPath(), ...getProjectRoots()],
|
||||
transformModulePath: require.resolve('metro/src/reactNativeTransformer'),
|
||||
},
|
||||
|
||||
getProjectPath,
|
||||
getProjectRoots,
|
||||
|
||||
load(configFile: string): ConfigT {
|
||||
return MetroConfig.load(configFile, Config.DEFAULT);
|
||||
async load(configFile: string): Promise<ConfigT> {
|
||||
const config: ConfigT = await loadConfig({config: configFile});
|
||||
|
||||
return mergeConfig(config, this.DEFAULT);
|
||||
},
|
||||
};
|
||||
|
||||
function findConfigPath(cwd: string): ?string {
|
||||
const parentDir = findParentDirectory(cwd, RN_CLI_CONFIG);
|
||||
return parentDir ? path.join(parentDir, RN_CLI_CONFIG) : null;
|
||||
}
|
||||
|
||||
// Finds the most near ancestor starting at `currentFullPath` that has
|
||||
// a file named `filename`
|
||||
function findParentDirectory(currentFullPath, filename) {
|
||||
const root = path.parse(currentFullPath).root;
|
||||
const testDir = parts => {
|
||||
if (parts.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fullPath = path.join(root, parts.join(path.sep));
|
||||
|
||||
var exists = fs.existsSync(path.join(fullPath, filename));
|
||||
return exists ? fullPath : testDir(parts.slice(0, -1));
|
||||
};
|
||||
|
||||
return testDir(currentFullPath.substring(root.length).split(path.sep));
|
||||
}
|
||||
|
||||
module.exports = Config;
|
||||
|
|
Loading…
Reference in New Issue