-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flight] Wire up bundler configs #18334
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
export type StringDecoder = void; | ||
|
||
export const supportsBinaryStreams = false; | ||
|
||
export function createStringDecoder(): void { | ||
throw new Error('Should never be called'); | ||
} | ||
|
||
export function readPartialStringChunk( | ||
decoder: StringDecoder, | ||
buffer: Uint8Array, | ||
): string { | ||
throw new Error('Should never be called'); | ||
} | ||
|
||
export function readFinalStringChunk( | ||
decoder: StringDecoder, | ||
buffer: Uint8Array, | ||
): string { | ||
throw new Error('Should never be called'); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
function getFakeModule() { | ||
return function FakeModule(props, data) { | ||
return data; | ||
}; | ||
} | ||
|
||
const ReactFlightDOMRelayClientIntegration = { | ||
preloadModule(jsResource) { | ||
return null; | ||
}, | ||
requireModule(jsResource) { | ||
return getFakeModule(); | ||
}, | ||
}; | ||
|
||
module.exports = ReactFlightDOMRelayClientIntegration; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,53 @@ | ||||||
/** | ||||||
* Copyright (c) Facebook, Inc. and its affiliates. | ||||||
* | ||||||
* This source code is licensed under the MIT license found in the | ||||||
* LICENSE file in the root directory of this source tree. | ||||||
* | ||||||
* @flow | ||||||
*/ | ||||||
|
||||||
export type ModuleMetaData = { | ||||||
id: string, | ||||||
chunks: Array<string>, | ||||||
}; | ||||||
|
||||||
type Thenable = { | ||||||
then(resolve: () => mixed, reject: (mixed) => mixed): mixed, | ||||||
... | ||||||
}; | ||||||
|
||||||
// The chunk cache contains all the chunks we've preloaded so far. | ||||||
// If they're still pending they're a thenable. This map also exists | ||||||
// in Webpack but unfortunately it's not exposed so we have to | ||||||
// replicate it in user space. null means that it has already loaded. | ||||||
const chunkCache: Map<string, null | Thenable> = new Map(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sokra In this approach, I'll always call This means I have to replicate this information in a user space map anyway. It would be nice if there was a way to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I consider adding an extra argument to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be great! Thank you. |
||||||
|
||||||
// Returning null means that all dependencies are fulfilled and we | ||||||
// can synchronously require the module now. A thenable is returned | ||||||
// that when resolved, means we can try again. | ||||||
export function preloadModule(moduleData: ModuleMetaData): null | Thenable { | ||||||
let moduleEntry = require.cache[moduleData.id]; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you considered exposing a Webpack specific helper to do something similar to this? In this case I could just get rid of it since it’s just an optimization to avoid having to check many maps. It might be nice to know for scheduling purposes though. E.g. we try to be very particular about when we call |
||||||
if (moduleEntry) { | ||||||
// Fast exit if this module has already been loaded. | ||||||
return null; | ||||||
} | ||||||
let chunks = moduleData.chunks; | ||||||
let anyRemainingThenable = null; | ||||||
for (let i = 0; i < chunks.length; i++) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code snippet doesn't work for more than 1 chunks, as You probably want to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be recalled each time a new chunk resolves which will then get the next one and so on. However in practice it most likely won’t get as far as even retrying the second time until everything has been resolved. So in practice we get one promise, then wait for it, schedule work to try again, in the meantime all of them resolve and then we try again just to confirm they all resolved. If not we’ll do the whole thing again. |
||||||
let chunkId = chunks[i]; | ||||||
let entry = chunkCache.get(chunkId); | ||||||
if (entry === undefined) { | ||||||
anyRemainingThenable = __webpack_chunk_load__(chunkId); | ||||||
chunkCache.set(chunkId, anyRemainingThenable); | ||||||
anyRemainingThenable.then(chunkCache.set.bind(chunkCache, chunkId, null)); | ||||||
} else if (entry !== null) { | ||||||
anyRemainingThenable = entry; | ||||||
} | ||||||
} | ||||||
return anyRemainingThenable; | ||||||
} | ||||||
|
||||||
export function requireModule<T>(moduleData: ModuleMetaData): T { | ||||||
return __webpack_require__(moduleData.id).default; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In production mode webpack may mangles exports names if certain conditions are met. This means It depends on how the module is used and how you get the id. You could opt-out from these optimization, but the better idea is probably to add the mangled export name to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! Yea that sounds like a good idea. |
||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
type WebpackMap = { | ||
[filename: string]: ModuleMetaData, | ||
}; | ||
|
||
export type BundlerConfig = WebpackMap; | ||
|
||
export type ModuleReference = string; | ||
|
||
export type ModuleMetaData = { | ||
id: string, | ||
chunks: Array<string>, | ||
}; | ||
|
||
export function resolveModuleMetaData( | ||
config: BundlerConfig, | ||
modulePath: ModuleReference, | ||
): ModuleMetaData { | ||
return config[modulePath]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.