mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-26 23:05:00 +08:00
Refactor hot loading implementation on iOS
Reviewed By: milend Differential Revision: D2795580 fb-gh-sync-id: ad33ba152e40b622b10bfa0122afd6edc28a11bf
This commit is contained in:
committed by
facebook-github-bot-9
parent
54f2586735
commit
ed4478a4ff
@@ -440,6 +440,16 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
||||
object:_parentBridge userInfo:@{@"bridge": self}];
|
||||
});
|
||||
}];
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
if (RCTGetURLQueryParam(self.bundleURL, @"hot")) {
|
||||
NSString *path = [self.bundleURL.path substringFromIndex:1]; // strip initial slash
|
||||
[self enqueueJSCall:@"HMRClient.enable" args:@[@"ios", path]];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
- (void)didFinishLoading
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) RCTBridgeModuleProviderBlock moduleProvider;
|
||||
|
||||
/**
|
||||
* Used by RCTDevMenu to override the `hot` param of the current bundleURL.
|
||||
*/
|
||||
@property (nonatomic, strong, readwrite) NSURL *bundleURL;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTBatchedBridge)
|
||||
|
||||
@@ -123,11 +123,11 @@ RCT_EXTERN BOOL RCTBridgeModuleClassIsRegistered(Class);
|
||||
/**
|
||||
* URL of the script that was loaded into the bridge.
|
||||
*/
|
||||
@property (nonatomic, strong) NSURL *bundleURL;
|
||||
@property (nonatomic, strong, readonly) NSURL *bundleURL;
|
||||
|
||||
/**
|
||||
* The class of the executor currently being used *or* to be used after the next
|
||||
* reload.
|
||||
* The class of the executor currently being used. Changes to this value will
|
||||
* take effect after the bridge is reloaded.
|
||||
*/
|
||||
@property (nonatomic, strong) Class executorClass;
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#import "RCTLog.h"
|
||||
#import "RCTPerformanceLogger.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTBundleURLProcessor.h"
|
||||
|
||||
NSString *const RCTReloadNotification = @"RCTReloadNotification";
|
||||
NSString *const RCTJavaScriptWillStartLoadingNotification = @"RCTJavaScriptWillStartLoadingNotification";
|
||||
@@ -88,6 +87,9 @@ BOOL RCTBridgeModuleClassIsRegistered(Class cls)
|
||||
}
|
||||
|
||||
@implementation RCTBridge
|
||||
{
|
||||
NSURL *_delegateBundleURL;
|
||||
}
|
||||
|
||||
dispatch_queue_t RCTJSThread;
|
||||
|
||||
@@ -257,8 +259,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
_bundleURL = [self.delegate sourceURLForBridge:self] ?: _bundleURL;
|
||||
_bundleURL = [[RCTBundleURLProcessor sharedProcessor] process: _bundleURL];
|
||||
// Only update bundleURL from delegate if delegate bundleURL has changed
|
||||
NSURL *previousDelegateURL = _delegateBundleURL;
|
||||
_delegateBundleURL = [self.delegate sourceURLForBridge:self];
|
||||
if (_delegateBundleURL && ![_delegateBundleURL isEqual:previousDelegateURL]) {
|
||||
_bundleURL = _delegateBundleURL;
|
||||
}
|
||||
|
||||
// Sanitize the bundle URL
|
||||
_bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString];
|
||||
|
||||
@@ -48,9 +48,9 @@ typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source);
|
||||
withBlock:(RCTSourceLoadBlock)loadCallback;
|
||||
|
||||
/**
|
||||
* Indicates wheather Hot Loading is supported or not.
|
||||
* Note this method will get removed soon, once we support Hot Loading on OSS.
|
||||
* Indicates whether Hot Loading is supported or not.
|
||||
* Note: this method will be removed soon, once Hot Loading is supported on OSS.
|
||||
*/
|
||||
- (BOOL)isHotLoadingEnabled;
|
||||
- (BOOL)bridgeSupportsHotLoading:(RCTBridge *)bridge;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
@interface RCTBundleURLProcessor : NSObject
|
||||
|
||||
+ (id)sharedProcessor;
|
||||
|
||||
- (NSString *)getQueryStringValue:(NSString *)attribute;
|
||||
- (void)setQueryStringValue:(NSString *)value forAttribute:(NSString *)attribute;
|
||||
- (NSURL *)process:(NSURL *)url;
|
||||
|
||||
@end
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBundleURLProcessor.h"
|
||||
|
||||
@implementation RCTBundleURLProcessor
|
||||
|
||||
NSDictionary *_qsAttributes;
|
||||
|
||||
+ (id)sharedProcessor
|
||||
{
|
||||
static RCTBundleURLProcessor *sharedProcessor = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedProcessor = [self new];
|
||||
});
|
||||
return sharedProcessor;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
// dictionary with additional query string attributes that will get appended
|
||||
// to the bundle URL
|
||||
_qsAttributes = [NSMutableDictionary new];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)getQueryStringValue:(NSString *)attribute
|
||||
{
|
||||
return [_qsAttributes valueForKey:attribute];
|
||||
}
|
||||
|
||||
- (void)setQueryStringValue:(NSString *)value forAttribute:(NSString *)attribute
|
||||
{
|
||||
[_qsAttributes setValue:value forKey:attribute];
|
||||
}
|
||||
|
||||
- (NSURL *)process:(NSURL *)url
|
||||
{
|
||||
if (url.isFileURL || [_qsAttributes count] == 0) {
|
||||
return url;
|
||||
}
|
||||
|
||||
// append either `?` or `&` depending on whether there are query string
|
||||
// attibutes or not.
|
||||
NSString *urlString = url.absoluteString;
|
||||
if ([urlString rangeOfString:@"?"].location == NSNotFound) {
|
||||
urlString = [urlString stringByAppendingString:@"?"];
|
||||
} else {
|
||||
urlString = [urlString stringByAppendingString:@"&"];
|
||||
}
|
||||
|
||||
// array with new query string attributes
|
||||
NSMutableArray *parts = [NSMutableArray new];
|
||||
for (id attribute in _qsAttributes) {
|
||||
if ([urlString rangeOfString:[NSString stringWithFormat:@"%@=", attribute]].location != NSNotFound) {
|
||||
[NSException raise:@"Cannot override attribute" format:@"Attribute %@ is already present in url: %@", attribute, url.absoluteString];
|
||||
}
|
||||
[parts addObject:[NSString stringWithFormat:@"%@=%@", attribute, _qsAttributes[attribute]]];
|
||||
}
|
||||
|
||||
return [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", urlString, [parts componentsJoinedByString:@"&"]]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -105,3 +105,7 @@ RCT_EXTERN NSString *RCTColorToHexString(CGColorRef color);
|
||||
|
||||
// Get standard localized string (if it exists)
|
||||
RCT_EXTERN NSString *RCTUIKitLocalizedString(NSString *string);
|
||||
|
||||
// URL manipulation
|
||||
RCT_EXTERN NSString *RCTGetURLQueryParam(NSURL *URL, NSString *param);
|
||||
RCT_EXTERN NSURL *RCTURLByReplacingQueryParam(NSURL *URL, NSString *param, NSString *value);
|
||||
|
||||
@@ -576,10 +576,53 @@ NSString *RCTColorToHexString(CGColorRef color)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// (https://github.com/0xced/XCDFormInputAccessoryView/blob/master/XCDFormInputAccessoryView/XCDFormInputAccessoryView.m#L10-L14)
|
||||
RCT_EXTERN NSString *RCTUIKitLocalizedString(NSString *string)
|
||||
NSString *RCTUIKitLocalizedString(NSString *string)
|
||||
{
|
||||
NSBundle *UIKitBundle = [NSBundle bundleForClass:[UIApplication class]];
|
||||
return UIKitBundle ? [UIKitBundle localizedStringForKey:string value:string table:nil] : string;
|
||||
}
|
||||
|
||||
NSString *RCTGetURLQueryParam(NSURL *URL, NSString *param)
|
||||
{
|
||||
RCTAssertParam(param);
|
||||
if (!URL) {
|
||||
return nil;
|
||||
}
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:URL
|
||||
resolvingAgainstBaseURL:YES];
|
||||
for (NSURLQueryItem *item in components.queryItems.reverseObjectEnumerator) {
|
||||
if ([item.name isEqualToString:param]) {
|
||||
return item.value;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSURL *RCTURLByReplacingQueryParam(NSURL *URL, NSString *param, NSString *value)
|
||||
{
|
||||
RCTAssertParam(param);
|
||||
if (!URL) {
|
||||
return nil;
|
||||
}
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:URL
|
||||
resolvingAgainstBaseURL:YES];
|
||||
__block NSInteger paramIndex = NSNotFound;
|
||||
NSMutableArray *queryItems = [components.queryItems mutableCopy];
|
||||
[queryItems enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:
|
||||
^(NSURLQueryItem *item, NSUInteger i, BOOL *stop) {
|
||||
if ([item.name isEqualToString:param]) {
|
||||
paramIndex = i;
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
NSURLQueryItem *newItem = [NSURLQueryItem queryItemWithName:param value:value];
|
||||
if (paramIndex == NSNotFound) {
|
||||
[queryItems addObject:newItem];
|
||||
} else {
|
||||
[queryItems replaceObjectAtIndex:paramIndex withObject:newItem];
|
||||
}
|
||||
components.queryItems = queryItems;
|
||||
return components.URL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user