Skip to content
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

Allow additional identifiers to be passed in to the babel plugin #966

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
300 changes: 295 additions & 5 deletions packages/babel-plugin/src/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,244 @@ loadable({
});"
`;
exports[`plugin custom signatures named signature should not match default import 1`] = `
"import myLoadable from 'myLoadablePackage';
myLoadable(() => import(\`./ModA\`));"
`;
exports[`plugin custom signatures should match custom default signature 1`] = `
"import myLoadable from 'myLoadablePackage';
myLoadable({
resolved: {},
chunkName() {
return \`ModA\`.replace(/[^a-zA-Z0-9_$()=\\\\-^°]+/g, \\"-\\");
},
isReady(props) {
const key = this.resolve(props);
if (this.resolved[key] !== true) {
return false;
}
if (typeof __webpack_modules__ !== 'undefined') {
return !!__webpack_modules__[key];
}
return false;
},
importAsync: () => import(
/* webpackChunkName: \\"ModA\\" */
\`./ModA\`),
requireAsync(props) {
const key = this.resolve(props);
this.resolved[key] = false;
return this.importAsync(props).then(resolved => {
this.resolved[key] = true;
return resolved;
});
},
requireSync(props) {
const id = this.resolve(props);
if (typeof __webpack_require__ !== 'undefined') {
return __webpack_require__(id);
}
return eval('module.require')(id);
},
resolve() {
if (require.resolveWeak) {
return require.resolveWeak(\`./ModA\`);
}
return eval('require.resolve')(\`./ModA\`);
}
});"
`;
exports[`plugin custom signatures should match custom named signature 1`] = `
"import { myLoadable } from 'myLoadablePackage';
myLoadable({
resolved: {},
chunkName() {
return \`ModA\`.replace(/[^a-zA-Z0-9_$()=\\\\-^°]+/g, \\"-\\");
},
isReady(props) {
const key = this.resolve(props);
if (this.resolved[key] !== true) {
return false;
}
if (typeof __webpack_modules__ !== 'undefined') {
return !!__webpack_modules__[key];
}
return false;
},
importAsync: () => import(
/* webpackChunkName: \\"ModA\\" */
\`./ModA\`),
requireAsync(props) {
const key = this.resolve(props);
this.resolved[key] = false;
return this.importAsync(props).then(resolved => {
this.resolved[key] = true;
return resolved;
});
},
requireSync(props) {
const id = this.resolve(props);
if (typeof __webpack_require__ !== 'undefined') {
return __webpack_require__(id);
}
return eval('module.require')(id);
},
resolve() {
if (require.resolveWeak) {
return require.resolveWeak(\`./ModA\`);
}
return eval('require.resolve')(\`./ModA\`);
}
});"
`;
exports[`plugin custom signatures should match renamed default import 1`] = `
"import renamedLoadable from '@loadable/component';
renamedLoadable({
resolved: {},
chunkName() {
return \`ModA\`.replace(/[^a-zA-Z0-9_$()=\\\\-^°]+/g, \\"-\\");
},
isReady(props) {
const key = this.resolve(props);
if (this.resolved[key] !== true) {
return false;
}
if (typeof __webpack_modules__ !== 'undefined') {
return !!__webpack_modules__[key];
}
return false;
},
importAsync: () => import(
/* webpackChunkName: \\"ModA\\" */
\`./ModA\`),
requireAsync(props) {
const key = this.resolve(props);
this.resolved[key] = false;
return this.importAsync(props).then(resolved => {
this.resolved[key] = true;
return resolved;
});
},
requireSync(props) {
const id = this.resolve(props);
if (typeof __webpack_require__ !== 'undefined') {
return __webpack_require__(id);
}
return eval('module.require')(id);
},
resolve() {
if (require.resolveWeak) {
return require.resolveWeak(\`./ModA\`);
}
return eval('require.resolve')(\`./ModA\`);
}
});"
`;
exports[`plugin custom signatures should match simple default import 1`] = `
"import loadable from '@loadable/component';
loadable({
resolved: {},
chunkName() {
return \`ModA\`.replace(/[^a-zA-Z0-9_$()=\\\\-^°]+/g, \\"-\\");
},
isReady(props) {
const key = this.resolve(props);
if (this.resolved[key] !== true) {
return false;
}
if (typeof __webpack_modules__ !== 'undefined') {
return !!__webpack_modules__[key];
}
return false;
},
importAsync: () => import(
/* webpackChunkName: \\"ModA\\" */
\`./ModA\`),
requireAsync(props) {
const key = this.resolve(props);
this.resolved[key] = false;
return this.importAsync(props).then(resolved => {
this.resolved[key] = true;
return resolved;
});
},
requireSync(props) {
const id = this.resolve(props);
if (typeof __webpack_require__ !== 'undefined') {
return __webpack_require__(id);
}
return eval('module.require')(id);
},
resolve() {
if (require.resolveWeak) {
return require.resolveWeak(\`./ModA\`);
}
return eval('require.resolve')(\`./ModA\`);
}
});"
`;
exports[`plugin custom signatures should not match on undeclared specifiers 1`] = `
"import myLoadable from 'myLoadablePackage';
myLoadable(() => import(\`./ModA\`));"
`;
exports[`plugin loadable.lib should be transpiled too 1`] = `
"import loadable from '@loadable/component';
loadable.lib({
Expand Down Expand Up @@ -700,11 +938,6 @@ loadable({
});"
`;
exports[`plugin simple import should not work with renamed specifier by default 1`] = `
"import renamedLoadable from '@loadable/component';
renamedLoadable(() => import(\`./ModA\`));"
`;
exports[`plugin simple import should transform path into "chunk-friendly" name 1`] = `
"import loadable from '@loadable/component';
loadable({
Expand Down Expand Up @@ -990,6 +1223,63 @@ renamedLazy({
});"
`;
exports[`plugin simple import should work with renamed specifier by default 1`] = `
"import renamedLoadable from '@loadable/component';
renamedLoadable({
resolved: {},
chunkName() {
return \`ModA\`.replace(/[^a-zA-Z0-9_$()=\\\\-^°]+/g, \\"-\\");
},
isReady(props) {
const key = this.resolve(props);
if (this.resolved[key] !== true) {
return false;
}
if (typeof __webpack_modules__ !== 'undefined') {
return !!__webpack_modules__[key];
}
return false;
},
importAsync: () => import(
/* webpackChunkName: \\"ModA\\" */
\`./ModA\`),
requireAsync(props) {
const key = this.resolve(props);
this.resolved[key] = false;
return this.importAsync(props).then(resolved => {
this.resolved[key] = true;
return resolved;
});
},
requireSync(props) {
const id = this.resolve(props);
if (typeof __webpack_require__ !== 'undefined') {
return __webpack_require__(id);
}
return eval('module.require')(id);
},
resolve() {
if (require.resolveWeak) {
return require.resolveWeak(\`./ModA\`);
}
return eval('require.resolve')(\`./ModA\`);
}
});"
`;
exports[`plugin simple import should work with template literal 1`] = `
"import loadable from '@loadable/component';
loadable({
Expand Down
36 changes: 21 additions & 15 deletions packages/babel-plugin/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ const properties = [

const LOADABLE_COMMENT = '#__LOADABLE__'

const loadablePlugin = declare((api, { defaultImportSpecifier = 'loadable' }) => {
const loadablePlugin = declare((api, {
signatures = []
}) => {
if (!signatures.find(sig => sig.from == '@loadable/component')) {
signatures.push({name: 'default', from: '@loadable/component'})
}
const { types: t } = api

function collectImportCallPaths(startPath) {
Expand All @@ -35,9 +40,9 @@ const loadablePlugin = declare((api, { defaultImportSpecifier = 'loadable' }) =>

const propertyFactories = properties.map(init => init(api))

function isValidIdentifier(path, loadableImportSpecifier, lazyImportSpecifier) {
// `loadable()`
if (loadableImportSpecifier && path.get('callee').isIdentifier({ name: loadableImportSpecifier })) {
function isValidIdentifier(path, loadableImportSpecifiers, lazyImportSpecifier) {
// loadable signatures
if (loadableImportSpecifiers.find(specifier => path.get('callee').isIdentifier({ name: specifier }))) {
return true
}

Expand All @@ -48,9 +53,8 @@ const loadablePlugin = declare((api, { defaultImportSpecifier = 'loadable' }) =>

// `loadable.lib()`
return (
loadableImportSpecifier &&
path.get('callee').isMemberExpression() &&
path.get('callee.object').isIdentifier({ name: loadableImportSpecifier }) &&
loadableImportSpecifiers.find(specifier => path.get('callee.object').isIdentifier({ name: specifier })) &&
path.get('callee.property').isIdentifier({ name: 'lib' })
)
}
Expand Down Expand Up @@ -119,28 +123,30 @@ const loadablePlugin = declare((api, { defaultImportSpecifier = 'loadable' }) =>
visitor: {
Program: {
enter(programPath) {
let loadableImportSpecifier = defaultImportSpecifier
let lazyImportSpecifier = false
const loadableSpecifiers = []

programPath.traverse({
ImportDefaultSpecifier(path) {
if (!loadableImportSpecifier) {
const { parent } = path
const { local } = path.node
loadableImportSpecifier = parent.source.value == '@loadable/component' &&
local && local.name
const { parent } = path
const { local } = path.node
if (local && signatures.find(signature => signature.name === 'default' && parent.source.value === signature.from)) {
loadableSpecifiers.push(local.name)
}
},
ImportSpecifier(path) {
const { parent } = path
const { imported, local } = path.node
if (!lazyImportSpecifier) {
const { parent } = path
const { imported, local } = path.node
lazyImportSpecifier = parent.source.value == '@loadable/component' &&
imported && imported.name == 'lazy' && local && local.name
}
if (local && imported && signatures.find(signature => imported.name === signature.name && parent.source.value === signature.from)) {
loadableSpecifiers.push(local.name)
}
},
CallExpression(path) {
if (!isValidIdentifier(path, loadableImportSpecifier, lazyImportSpecifier)) return
if (!isValidIdentifier(path, loadableSpecifiers, lazyImportSpecifier)) return
transformImport(path)
},
'ArrowFunctionExpression|FunctionExpression|ObjectMethod': path => {
Expand Down
Loading