-
Notifications
You must be signed in to change notification settings - Fork 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
Framework: Implement AsyncLoad for code-splitting using Babel plugin #8544
Conversation
@@ -112,7 +112,14 @@ if ( CALYPSO_ENV === 'desktop' || CALYPSO_ENV === 'desktop-mac-app-store' ) { | |||
jsLoader = { | |||
test: /\.jsx?$/, | |||
exclude: /node_modules/, | |||
loaders: [ 'babel-loader?cacheDirectory' ] | |||
loader: 'babel', | |||
query: { |
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.
probably want to turn cacheDirectory back on?
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.
probably want to turn cacheDirectory back on?
Yep, good catch. Fixed in baab477a9e1a6a1e9c5ef2872ea897dd63c297d2
loader: 'babel', | ||
query: { | ||
plugins: [ | ||
[ 'transform-wpcalypso-async', { |
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.
Do we want this enabled for the server bundle?
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.
Do we want this enabled for the server bundle?
I think so? Otherwise AsyncLoad
and asyncRequire
won't be transformed.
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.
We don't want multiple bundles being generated though, in any case, so can we set async
to false
?
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.
We don't want multiple bundles being generated though, in any case, so can we set
async
tofalse
?
Yeah, that makes sense.
baab477
to
053fb7a
Compare
@@ -12,7 +12,7 @@ import Accordion from 'components/accordion'; | |||
import AccordionSection from 'components/accordion/section'; | |||
import Gridicon from 'components/gridicon'; | |||
import CategoriesTagsAccordion from 'post-editor/editor-categories-tags/accordion'; | |||
import EditorSharingAccordion from 'post-editor/editor-sharing/accordion'; | |||
import EditorSharingAccordion from 'async-component!post-editor/editor-sharing/accordion'; |
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.
how does this work with tests?
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.
how does this work with tests?
Probably not very well, and I'm sure same goes for base <AsyncLoad />
. Will need to think about this some more.
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.
Maybe the loader could check for the NODE_ENV
and return the original source if it's testing?
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.
Hmm, I guess the issue is that Webpack isn't used at all in the context of tests, so it'll choke on the loader syntax...
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.
I would probably split the async-component!
loader syntax up into another PR, since IMHO it adds a fair bit of complexity.
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.
I would probably split the
async-component!
loader syntax up into another PR, since IMHO it adds a fair bit of complexity.
What would you suggest be included in this pull request after that would be removed?
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.
Anything needed for asyncRequire
and AsyncLoad
. That way, I think we can split up changes to the build pipeline into more discrete pieces.
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.
Anything needed for
asyncRequire
andAsyncLoad
. That way, I think we can split up changes to the build pipeline into more discrete pieces.
So, to be clear, for this instance we'd use <AsyncLoad />
directly instead of the loader in this pull request, and defer the loader to a future one?
Just want to be sure we're including something in this one. 😆
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.
So, to be clear, for this instance we'd use directly instead of the loader in this pull request, and defer the loader to a future one?
Sorry, yes. I see this PR as being for usage of AsyncLoad
and asyncRequire?
, along with the babel plugin required to transform those. Then the import
webpack
loader being in another PR, so we're not changing too much at once :)
Couple issues to resolve:
|
|
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.
Oops, forgot to submit.
@@ -156,6 +164,6 @@ if ( config.isEnabled( 'webpack/persistent-caching' ) ) { | |||
webpackConfig.plugins.unshift( new HardSourceWebpackPlugin( { cacheDirectory: path.join( __dirname, '.webpack-cache', 'client' ) } ) ); | |||
} | |||
|
|||
webpackConfig.module.loaders = [ jsLoader ].concat( webpackConfig.module.loaders ); | |||
webpackConfig.module.postLoaders = [ jsLoader ]; |
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.
Having the babel transformation happen in a postLoader worries me a little. Was this just for the import
syntax change?
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.
Having the babel transformation happen in a postLoader worries me a little. Was this just for the
import
syntax change?
Yes, if I recall correctly, it was so that:
(a) The async component loader could return ES6
(b) The Babel plugin would be run last to strip the async-component!
import prefix
@@ -12,7 +12,7 @@ import Accordion from 'components/accordion'; | |||
import AccordionSection from 'components/accordion/section'; | |||
import Gridicon from 'components/gridicon'; | |||
import CategoriesTagsAccordion from 'post-editor/editor-categories-tags/accordion'; | |||
import EditorSharingAccordion from 'post-editor/editor-sharing/accordion'; | |||
import EditorSharingAccordion from 'async-component!post-editor/editor-sharing/accordion'; |
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.
I would probably split the async-component!
loader syntax up into another PR, since IMHO it adds a fair bit of complexity.
e279107
to
c6757d9
Compare
Ok, I performed a surgical rebase, squashed a few commits, but preserved the Webpack loader and a revert so it's kept in history for future reference. How does this look now @ehg? |
}; | ||
} | ||
|
||
componentWillMount() { |
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.
this may also need to have componentWillReceiveProps
in case we get into a situation where React decides to reuse an instance instead of spinning up a new one. Given how this will be used, it's probably unlikely, but worth doing.
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.
It also raises the point that the Babel plugin transforms the string into a function which is created anew for every render. I might experiment a bit to see how difficult it would be to pull the function to the top of the transformed module so that we can do a strict equality check in componentWillReceiveProps
before calling the require
prop.
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.
This brings to mind another Babel plugin that might be interesting to experiment with:
http://babeljs.io/docs/plugins/transform-react-constant-elements/
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.
that thing would be amazing for gridicons
er, no, they take a dynamic size. darn.
const isAsync = state.opts.async; | ||
|
||
// In both asynchronous and synchronous case, we'll finish by | ||
// calling reqquire on the loaded module |
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.
speling on require
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.
speling on require
Fixed in rebased 5b9a658
It looks good. Thanks for this, I hope not too much anesthesia was required :) |
Bit late but something to maybe consider? https://github.com/airbnb/babel-plugin-dynamic-import-webpack |
It's not obvious the point of this plugin vs. simply using |
@aduth yeah, true. I'm happy with what we have anyway. :) |
c6757d9
to
c26d2c9
Compare
The hoisting changes look good. I think we can merge this now! Great work @aduth. |
Thanks for working on this! |
This reverts commit 1e5715ba34b9620dea5b90b9b2d8766973fde9df.
7640e48
to
808cbb6
Compare
Did a few more final rounds of testing (production mode, IE, desktop app). Looking good on all fronts. Going to merge. |
Supersedes #5356
This pull request is related to #5356, implementing
<AsyncLoad />
, but leveraging a new Babel plugintransform-wpcalypso-async
to handle transformations of prop values under the hood torequire.ensure
orrequire
depending on the current environment configuration.The new transform plugin also exposes a lower-level
asyncRequire
function for general usage. See plugin documentation for more information.Testing Instructions:
Navigate to the editor, verifying that the sharing accordion is displayed after visiting the page.
Follow-up Tasks:
We should improve
<AsyncLoad />
to accept additional props to control when the module is required, so that we can load in response to specific interactions (e.g. hovering the accordion title).cc @mtias @ehg @mcsf @seear @umurkontaci