Last active
January 17, 2020 12:20
-
-
Save hasparus/7ee6259477e0cb7b4e00397b16281ad7 to your computer and use it in GitHub Desktop.
vanity babel macro for concise React.lazy components
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const UserProfile = React.lazy(() => import("./scenes/UserProfile").then(module => ({ | |
default: module.UserProfile | |
}))); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"v": 2, | |
"parserID": "babylon7", | |
"toolID": "babel-plugin-macros", | |
"settings": { | |
"babylon7": null | |
}, | |
"versions": { | |
"babylon7": "7.7.2", | |
"babel-plugin-macros": "2.6.1" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lazy from 'lazy.macro' | |
const UserProfile = lazy('./scenes/UserProfile'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { createMacro } = require('babel-plugin-macros'); | |
const last = xs => xs[xs.length - 1]; | |
module.exports = createMacro(({ references, state, babel }) => { | |
/** @type { typeof references.default } */ | |
const refs = references.lazy || references.default || references; | |
const t = babel.types; | |
refs.forEach(referencePath => { | |
if (!referencePath.parentPath.isCallExpression()) { | |
throw new Error("must be call expression"); | |
} | |
const [firstArgumentPath] = referencePath.parentPath.get("arguments"); | |
if (!firstArgumentPath.isStringLiteral()) { | |
throw new Error("first argument must must be string"); | |
} | |
const stringValue = firstArgumentPath.node.value; | |
const componentName = last(stringValue.split("/")); | |
const callExpr = t.callExpression( | |
t.memberExpression(t.identifier("React"), t.identifier("lazy")), | |
[ | |
t.arrowFunctionExpression( | |
[], | |
t.callExpression( | |
t.memberExpression( | |
t.callExpression(t.import(), [t.stringLiteral(stringValue)]), | |
t.identifier("then") | |
), | |
[ | |
t.arrowFunctionExpression( | |
[t.identifier("module")], | |
t.objectExpression([ | |
t.objectProperty( | |
t.identifier("default"), | |
t.memberExpression( | |
t.identifier("module"), | |
t.identifier(componentName) | |
) | |
) | |
]) | |
) | |
] | |
) | |
) | |
] | |
); | |
firstArgumentPath.parentPath.replaceWith(callExpr); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@velein This is possible, but I'm not sure if @0ctothorp wouldn't murder us for pushing this.
You can play around with it in AST Explorer.