2017-04-17 15:33:40 +00:00
|
|
|
// Based on https://github.com/airbnb/babel-plugin-dynamic-import-webpack
|
|
|
|
// We've added support for SSR with this version
|
2018-04-03 07:34:07 +00:00
|
|
|
import template from '@babel/template'
|
|
|
|
import syntax from '@babel/plugin-syntax-dynamic-import'
|
2017-08-16 20:55:27 +00:00
|
|
|
import { dirname, resolve, sep } from 'path'
|
2017-08-16 17:14:00 +00:00
|
|
|
import Crypto from 'crypto'
|
2017-04-17 15:33:40 +00:00
|
|
|
|
|
|
|
const TYPE_IMPORT = 'Import'
|
|
|
|
|
2017-12-08 01:50:38 +00:00
|
|
|
/*
|
|
|
|
Added "typeof require.resolveWeak !== 'function'" check instead of
|
|
|
|
"typeof window === 'undefined'" to support dynamic impports in non-webpack environments.
|
|
|
|
"require.resolveWeak" and "require.ensure" are webpack specific methods.
|
|
|
|
They would fail in Node/CommonJS environments.
|
|
|
|
*/
|
|
|
|
|
2017-04-17 15:33:40 +00:00
|
|
|
const buildImport = (args) => (template(`
|
|
|
|
(
|
2018-05-25 13:29:26 +00:00
|
|
|
typeof require.resolveWeak !== 'function' ?
|
|
|
|
new (require('next/dynamic').SameLoopPromise)((resolve, reject) => {
|
|
|
|
eval('require.ensure = function (deps, callback) { callback(require) }')
|
|
|
|
require.ensure([], (require) => {
|
2017-04-19 18:25:06 +00:00
|
|
|
let m = require(SOURCE)
|
2018-05-25 13:29:26 +00:00
|
|
|
m.__webpackChunkName = '${args.name}.js'
|
|
|
|
resolve(m);
|
|
|
|
}, 'chunks/${args.name}.js');
|
|
|
|
})
|
|
|
|
:
|
|
|
|
new (require('next/dynamic').SameLoopPromise)((resolve, reject) => {
|
|
|
|
const weakId = require.resolveWeak(SOURCE)
|
|
|
|
try {
|
|
|
|
const weakModule = __webpack_require__(weakId)
|
|
|
|
return resolve(weakModule)
|
|
|
|
} catch (err) {}
|
|
|
|
|
|
|
|
require.ensure([], (require) => {
|
|
|
|
try {
|
|
|
|
let m = require(SOURCE)
|
|
|
|
m.__webpackChunkName = '${args.name}'
|
|
|
|
resolve(m)
|
|
|
|
} catch(error) {
|
|
|
|
reject(error)
|
|
|
|
}
|
|
|
|
}, 'chunks/${args.name}');
|
|
|
|
})
|
2017-04-17 15:33:40 +00:00
|
|
|
)
|
|
|
|
`))
|
|
|
|
|
2017-08-16 17:14:00 +00:00
|
|
|
export function getModulePath (sourceFilename, moduleName) {
|
|
|
|
// resolve only if it's a local module
|
|
|
|
const modulePath = (moduleName[0] === '.')
|
|
|
|
? resolve(dirname(sourceFilename), moduleName) : moduleName
|
|
|
|
|
|
|
|
const cleanedModulePath = modulePath
|
|
|
|
.replace(/(index){0,1}\.js$/, '') // remove .js, index.js
|
|
|
|
.replace(/[/\\]$/, '') // remove end slash
|
|
|
|
|
|
|
|
return cleanedModulePath
|
|
|
|
}
|
|
|
|
|
2017-04-17 15:33:40 +00:00
|
|
|
export default () => ({
|
|
|
|
inherits: syntax,
|
|
|
|
|
|
|
|
visitor: {
|
2017-08-16 17:14:00 +00:00
|
|
|
CallExpression (path, state) {
|
2017-04-17 15:33:40 +00:00
|
|
|
if (path.node.callee.type === TYPE_IMPORT) {
|
2017-06-29 00:25:13 +00:00
|
|
|
const moduleName = path.node.arguments[0].value
|
2017-08-16 17:14:00 +00:00
|
|
|
const sourceFilename = state.file.opts.filename
|
|
|
|
|
|
|
|
const modulePath = getModulePath(sourceFilename, moduleName)
|
|
|
|
const modulePathHash = Crypto.createHash('md5').update(modulePath).digest('hex')
|
|
|
|
|
2017-08-16 20:55:27 +00:00
|
|
|
const relativeModulePath = modulePath.replace(`${process.cwd()}${sep}`, '')
|
|
|
|
const name = `${relativeModulePath.replace(/[^\w]/g, '_')}_${modulePathHash}`
|
2017-08-16 17:14:00 +00:00
|
|
|
|
2017-04-17 15:33:40 +00:00
|
|
|
const newImport = buildImport({
|
2017-06-29 00:25:13 +00:00
|
|
|
name
|
2017-04-17 15:33:40 +00:00
|
|
|
})({
|
|
|
|
SOURCE: path.node.arguments
|
|
|
|
})
|
|
|
|
path.replaceWith(newImport)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|