1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00
next.js/build/babel/plugins/react-loadable-plugin.js
Tim Neutkens 75476a9136
[WIP] Webpack 4, react-error-overlay, react-loadable (#4639)
Webpack 4, react-error-overlay, react-loadable (major)
2018-07-24 11:24:40 +02:00

126 lines
3.8 KiB
JavaScript

// This file is https://github.com/jamiebuilds/react-loadable/blob/master/src/babel.js
// Modified to also look for `next/dynamic`
// Modified to put `webpack` and `modules` under `loadableGenerated` to be backwards compatible with next/dynamic which has a `modules` key
// Modified to support `dynamic(import('something'))` and `dynamic(import('something'), options)
export default function ({ types: t, template }) {
return {
visitor: {
ImportDeclaration (path) {
let source = path.node.source.value
if (source !== 'next/dynamic' && source !== 'react-loadable') return
let defaultSpecifier = path.get('specifiers').find(specifier => {
return specifier.isImportDefaultSpecifier()
})
if (!defaultSpecifier) return
let bindingName = defaultSpecifier.node.local.name
let binding = path.scope.getBinding(bindingName)
binding.referencePaths.forEach(refPath => {
let callExpression = refPath.parentPath
if (
callExpression.isMemberExpression() &&
callExpression.node.computed === false &&
callExpression.get('property').isIdentifier({ name: 'Map' })
) {
callExpression = callExpression.parentPath
}
if (!callExpression.isCallExpression()) return
let args = callExpression.get('arguments')
if (args.length > 2) throw callExpression.error
let loader
let options
if (!args[0]) {
return
}
if (args[0].isCallExpression()) {
if (!args[1]) {
callExpression.pushContainer('arguments', t.objectExpression([]))
}
args = callExpression.get('arguments')
loader = args[0]
options = args[1]
} else {
options = args[0]
}
if (!options.isObjectExpression()) return
let properties = options.get('properties')
let propertiesMap = {}
properties.forEach(property => {
let key = property.get('key')
propertiesMap[key.node.name] = property
})
if (propertiesMap.loadableGenerated) {
return
}
if (propertiesMap.loader) {
loader = propertiesMap.loader.get('value')
}
if (propertiesMap.modules) {
loader = propertiesMap.modules.get('value')
}
let loaderMethod = loader
let dynamicImports = []
loaderMethod.traverse({
Import (path) {
dynamicImports.push(path.parentPath)
}
})
if (!dynamicImports.length) return
options.pushContainer(
'properties',
t.objectProperty(
t.identifier('loadableGenerated'),
t.objectExpression([
t.objectProperty(
t.identifier('webpack'),
t.arrowFunctionExpression(
[],
t.arrayExpression(
dynamicImports.map(dynamicImport => {
return t.callExpression(
t.memberExpression(
t.identifier('require'),
t.identifier('resolveWeak')
),
[dynamicImport.get('arguments')[0].node]
)
})
)
)
),
t.objectProperty(
t.identifier('modules'),
t.arrayExpression(
dynamicImports.map(dynamicImport => {
return dynamicImport.get('arguments')[0].node
})
)
)
])
)
)
})
}
}
}
}