-
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: ES Modules + Tree Shaking #16057
Conversation
ec7c705
to
44c18bd
Compare
84bfa3a
to
a68cba7
Compare
a68cba7
to
6de0e92
Compare
6de0e92
to
36aa82e
Compare
After running the commonjs-exports codemod on
The reason that is an error has to do with a problem that is relatively pervasive in wp-calypso and it has to do with trying to destructure imports. Destructuring Imports So for a file that looks like this: import { thing1, thing2 } from 'lib'; This would a syntactically correct lib file: // correct lib implementation
export const thing1 = function(){ ... };
export const thing2 = function(){ ... }; This is an incorrect one: // incorrect lib implementation
export default {
thing1: function(){ ... },
thing2: function(){ ... }
}; Here is a list i generated of offending files and the frequency with which their exports are being used incorrectly. Note all relative urls need more investigation.
|
A full list of all the bad-imports.txt |
96ab0cb
to
e0834f5
Compare
next two things:
|
546d91b
to
f3cab96
Compare
found an issue in notifications-panel. I create a PR there and until its merged will need to test with:
|
528c1af
to
50fa7a8
Compare
Really cool news about the stricter es6 syntax: the code will be able to verify a greater amount of correctness at compile time. Now the interesting bit, I found
|
A few more notes from me whacking at the issue today:
current status: At the start of this PR (after running codemods) there were over 1k compile time errors. Now I'm down to what I think are tens of runtime ones. I'm pretty excited about the progress here so far! The notifications-panel loads properly and I believe the rest of the errors will all be due to the extra requires |
Relevant: webpack/webpack#2061 If I understood it correctly, Webpack does a basic pass to check if an import { otherFunc1, otherFunc2 } from './otherModule';
function callOther() {
otherFunc1();
otherFunc2();
}
export default function () {
if (always_false) {
callOther();
}
} Webpack will assume that But in this case: import { otherFunc1, otherFunc2 } from './otherModule';
export default function () {
if (always_false) {
otherFunc1();
otherFunc2();
}
} Webpack correctly detects that I think our use cases can be adapted to the second case, just use the For the first case, I assume that if the |
I've created a It may be worthwhile to look into whether or not we can selectively include |
@@ -22,6 +22,9 @@ import { setLocale, setLocaleRawData } from 'state/ui/language/actions'; | |||
import { setCurrentUserOnReduxStore } from 'lib/redux-helpers'; | |||
import { installPerfmonPageHandlers } from 'lib/perfmon'; | |||
import { getSections, setupRoutes } from 'sections-middleware'; | |||
import { checkFormHandler } from 'lib/protect-form'; | |||
import notices from 'notices'; | |||
import authController from 'auth/controller'; |
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.
Hah, the notices
and authController
modules still use export default = { ... }
:)
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.
just double checking: this comment is just an observation and doesn't mean that i should make a change here right?
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.
Yes, it can wait for a separate PR.
@@ -23,7 +24,7 @@ import { | |||
requestTranscript, | |||
} from 'state/happychat/connection/actions'; | |||
|
|||
const debug = require( 'debug' )( 'calypso:happychat:connection' ); | |||
const debug = debugFactory()( 'calypso:happychat:connection' ); |
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 should be debugFactory( 'calypso:happychat:connection' )
. Otherwise you create a debug logger and log a message immediately :)
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.
whoops! Nice catch. I'll fixem
client/lib/happychat/connection.js
Outdated
@@ -23,7 +24,7 @@ import { | |||
requestTranscript, | |||
} from 'state/happychat/connection/actions'; | |||
|
|||
const debug = require( 'debug' )( 'calypso:happychat:connection' ); | |||
const debug = debugFactory()( 'calypso:happychat:connection' ); |
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.
same here.
There's a |
@jsnajdr et. al. @samouri and I had a conversation in Slack concerning the change in semantics from runtime Namely the |
The But you have a very good point: for the modules that this PR changes from conditional imports to static, we should check if any of them does some expensive static initialization. If it does, I think the most reliable remedy is to rewrite these modules to do the expensive initialization lazily -- only when an exported function is called or exported class instantiated for the first time. |
I found an insidious bug that's exposed by enabling tree shaking and scope hoisting: in It used to work when the To experience the runtime error, go to the post editor page at How many other modules are affected and where to find them? |
So the solution should be to remove the |
Yes. |
Specifically for the "this" bug you've found, we can do a grep for "this" for all The result of the query was 17 files. They were grouped like this:
It seems to me like you caught something pretty rare. Technically its possible this also happens within jsx files, but I wouldn't know how to search for that. @dmsnell knows of some structural grep tools that could help. It is worrisome to think that there still may be other slight inconsistencies between how CJS and esmodules behave in webpack. I don't think it should stop us progressing with this PR though. |
that's the kind of thing we need to be careful about because if we initialize that via
Good catch! This isn't inherently a problem though; it was just missed in the conversion (probably by me). We rewrote many functions to go from From what I've seen we have very few cases (outside of React components) where we need
maybe? these might be hard to find in the JSX files. on the other hand, if it's in a JSX file it's probably safe because
very much so. this is also why I think in this case code-modding would have been disastrous in practice.
👍 |
timmyc: I know I'm referencing code from about 2 years ago, but I was wondering if you remember what the intention of |
Actually, its only used in a single line in the whole app: |
Memory lane right there, well it was originally used for displaying the correct base path for post slugs. Your changes seem fine to me. |
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 tested this PR quite thoroughly, clicking around Calypso everywhere I could, and I didn't find any bugs. Let's 🚢 this.
The getPagePath
function still needs some fixing, but that's a trivial change.
@dmsnell has a good point that the way how we load wpcom-proxy-request
and other modules can be a little dangerous and could easily lead to errors like dereferencing window
in Node environment.
But I don't think that anything is broken now -- it's more like the code is easy to break if we are not careful. We should clean up the imports a little bit soon, but it's not a blocker for this PR.
client/lib/posts/utils.js
Outdated
|
||
return pathParts.join( '/' ); | ||
const postUrl = get( post, [ 'other_URLs', 'permalink_URL' ] ) || post.URL; | ||
return removeSlug( postUrl ); |
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.
... and you can also revert this back to just return removeSlug( post.URL )
-- the permalink case was already handled.
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.
While I think thats true, it'll fail one of the unit 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.
edit: i lied. it works fine now that the return
was added back :)
Webpack2 and Webpack 3 introduced a couple major features:
Currently, we cant take advantage of either because we are still transpiling to commonjs modules in our babel configuration.
In this PR I try to find (and hopefully solve) all of the blockers towards disabling commonjs transpilation and enabling tree-shaking/scope hoisting.
To Test
Test everything on: https://dserve.a8c.com/?branch=try/scope-hoisting.